将 ccache 与 clang 5 一起使用会导致与仅 clang5 不同的结果
Using ccache with clang 5 causes different results from just clang5
所以使用这段人为设计的代码 - 用 clang 编译工作得很好,但是当使用 ccache 时额外 warnings/errors 出现 - 我认为 ccache 应该透明地传递这些。这是来自 epel repo 的 CentOS 6 上的 ccache 3.1.6 - 升级不是一个选项,因为这是生产环境。
#include <byteswap.h>
int main()
{
int i = 42;
auto j = bswap_32(i);
(void)j;
return 0;
}
所以带有未使用的包含路径的示例 1 没有给出错误:
clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -I/usr/local/include -c ccache.cpp
但是使用 ccache 我得到:
ccache clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -I/usr/include/xmlib -c ccache.cpp
clang-5.0: error: argument unused during compilation: '-I /usr/include/xmlib' [-Werror,-Wunused-command-line-argument]
没有额外包含的示例 2 工作得很好:
clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -c ccache.cpp
还有ccache
cache clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -c ccache.cpp
ccache.cpp:6:32: error: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
auto j = (__extension__ ({ register unsigned int __v, __x = (i); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }));
^~~~~~~~~
ccache.cpp:6:32: error: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
auto j = (__extension__ ({ register unsigned int __v, __x = (i); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }));
^~~~~~~~~
2 errors generated.
为什么使用 ccache 会改变结果?
基本问题是,默认情况下,ccache
会pre-process文件(运行 C-preprocessor就可以了)得到单个pre-process ed 用于检查缓存的翻译单元。然后,为了效率起见,如果它 "misses" 在其缓存中并且必须编译文件,它将 pre-processed 文件直接传递给 clang
,告诉 clang
不要 运行 pre-process 或者,只有编译器(例如,给它扩展名 .i
)。
因为它不是 运行 宁 pre-processor,-I
参数本质上被忽略,这就是 clang
抱怨的。 gcc
对此没有那么挑剔,所以这不会造成问题。
在 ccache
3.2 中,已进行修复,根据我的本地测试,此问题已消失。
如果你卡在 3.1 上,你可以在你的环境中 export CCACHE_CPP2=yes
,这告诉 ccache
不要理会上述优化,只需将原始 C 或 C++ 文件传递到 clang
。这会消耗多少性能取决于 pre-processing 与编译的成本。
我在 TravisCI(它有一个旧的 3.1 版本 ccache
)上遇到了这个问题,这为我解决了它。
您的编译错误可能源于相同的原因:clang
可能会忽略某些或所有系统 headers 中的错误,例如 <byteswap.h>
,但不会忽略 "user code" 中的错误。由于 ccache
将一个大的 pre-processd blob 传递给它,所以它看起来像 user-code 到 clang。
此 three part blog series 更详细地解释了这个问题,并包含指向相关 ccache
错误和讨论的链接。
所以使用这段人为设计的代码 - 用 clang 编译工作得很好,但是当使用 ccache 时额外 warnings/errors 出现 - 我认为 ccache 应该透明地传递这些。这是来自 epel repo 的 CentOS 6 上的 ccache 3.1.6 - 升级不是一个选项,因为这是生产环境。
#include <byteswap.h>
int main()
{
int i = 42;
auto j = bswap_32(i);
(void)j;
return 0;
}
所以带有未使用的包含路径的示例 1 没有给出错误:
clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -I/usr/local/include -c ccache.cpp
但是使用 ccache 我得到:
ccache clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -I/usr/include/xmlib -c ccache.cpp
clang-5.0: error: argument unused during compilation: '-I /usr/include/xmlib' [-Werror,-Wunused-command-line-argument]
没有额外包含的示例 2 工作得很好:
clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -c ccache.cpp
还有ccache
cache clang++ -Wno-c++98-compat -Wall -Werror -std=c++17 -c ccache.cpp
ccache.cpp:6:32: error: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
auto j = (__extension__ ({ register unsigned int __v, __x = (i); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }));
^~~~~~~~~
ccache.cpp:6:32: error: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
auto j = (__extension__ ({ register unsigned int __v, __x = (i); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v; }));
^~~~~~~~~
2 errors generated.
为什么使用 ccache 会改变结果?
基本问题是,默认情况下,ccache
会pre-process文件(运行 C-preprocessor就可以了)得到单个pre-process ed 用于检查缓存的翻译单元。然后,为了效率起见,如果它 "misses" 在其缓存中并且必须编译文件,它将 pre-processed 文件直接传递给 clang
,告诉 clang
不要 运行 pre-process 或者,只有编译器(例如,给它扩展名 .i
)。
因为它不是 运行 宁 pre-processor,-I
参数本质上被忽略,这就是 clang
抱怨的。 gcc
对此没有那么挑剔,所以这不会造成问题。
在 ccache
3.2 中,已进行修复,根据我的本地测试,此问题已消失。
如果你卡在 3.1 上,你可以在你的环境中 export CCACHE_CPP2=yes
,这告诉 ccache
不要理会上述优化,只需将原始 C 或 C++ 文件传递到 clang
。这会消耗多少性能取决于 pre-processing 与编译的成本。
我在 TravisCI(它有一个旧的 3.1 版本 ccache
)上遇到了这个问题,这为我解决了它。
您的编译错误可能源于相同的原因:clang
可能会忽略某些或所有系统 headers 中的错误,例如 <byteswap.h>
,但不会忽略 "user code" 中的错误。由于 ccache
将一个大的 pre-processd blob 传递给它,所以它看起来像 user-code 到 clang。
此 three part blog series 更详细地解释了这个问题,并包含指向相关 ccache
错误和讨论的链接。