将ccache与clang 5一起使用会导致与clang5不同的结果

时间:2018-04-19 17:54:39

标签: clang++ ccache

因此,使用这些设计的代码 - 用clang编译工作就好了,但是当使用ccache时会出现额外的警告/错误 - 我认为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会改变结果?

1 个答案:

答案 0 :(得分:4)

基本问题是,默认情况下,ccache将对文件进行预处理(在其上运行C预处理器),以获得单个预处理的翻译单元,该翻译单元用于检查其缓存。然后,为了提高效率,如果它在缓存中“丢失”并不得不编译文件,则它将经过预处理的文件直接传递到clang,告诉clang不要运行预处理器,仅编译器(例如,给它扩展名.i)。

由于它没有运行预处理器,因此-I参数会被固有地忽略,这就是clang所抱怨的。 gcc对此没有那么挑剔,因此在这里也没有问题。

ccache 3.2中,已经进行了修复,根据我的本地测试,该问题消失了。

如果您坚持使用3.1,则可以在您的环境中使用export CCACHE_CPP2=yes,这告诉ccache不必进行上述优化,而只需将原始C或C ++文件传递到{{1} }。付出多少性能取决于预处理和编译的成本。

我在TravisCI(其旧版本为clang的TravisCI上遇到此问题,并为我解决了此问题。

您的编译错误可能源于相同的原因:ccache可能会忽略某些或所有系统标头(例如clang)中的错误,但不会忽略“用户代码”中的错误。由于<byteswap.h>向其传递了一个很大的预处理Blob,因此所有这些看起来都像用户代码一样。

three part blog series更详细地说明了此问题,并包含指向相关ccache错误和讨论的链接。