代码之家  ›  专栏  ›  技术社区  ›  Adrian Cornish Sean Johnson

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

  •  5
  • Adrian Cornish Sean Johnson  · 技术社区  · 6 年前

    因此,有了这段精心设计的代码,使用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没有额外的include,效果很好:

    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 回复  |  直到 6 年前
        1
  •  7
  •   BeeOnRope    6 年前

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

    由于它没有运行预处理器, -I 争论本质上是被忽视的,这就是 叮当声 正在抱怨。 gcc 对此并不挑剔,因此不会造成问题。

    在里面 ccache公司 3.2,已进行修复,根据我的本地测试,此问题消失。

    如果你被困在3.1上,你可以 export CCACHE_CPP2=yes 在您的环境中 ccache公司 不必为上述优化而烦恼,只需将原始C或C++文件传递到 叮当声 。性能成本取决于预处理与编译的成本。

    我在TravisCI上遇到过这个问题(它有一个旧的3.1版本 ccache公司 )这帮我解决了这个问题。

    编译错误的根源可能与此相同: 叮当声 可能会忽略某些或所有系统标头中的错误,如 <byteswap.h> 但不在“用户代码”中。自从 ccache公司 通过一个大的预处理blob,它看起来就像用户代码发出叮当声。

    three part blog series 更详细地解释此问题,并包含相关链接 ccache公司 错误和讨论。