【问题标题】:Using ccache with clang 5 causes different results from just clang5将 ccache 与 clang 5 一起使用会导致与 clang5 不同的结果
【发布时间】:2018-09-30 07:48:45
【问题描述】:

因此,使用这段人为的代码 - 使用 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

还有 cca​​che

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 会改变结果?

【问题讨论】:

  • 在您的第一个示例中,您包含 /usr/local/include 用于直接的 clang 编译,但 /usr/local/xmlib 用于 ccache clang 调用,因此命令不一样。这是故意的吗?

标签: clang++ ccache


【解决方案1】:

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

由于它没有运行预处理器,-I 参数本质上会被忽略,这就是clang 所抱怨的。 gcc 对此并不挑剔,因此不会造成问题。

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

如果你卡在 3.1 上,你可以在你的环境中 export CCACHE_CPP2=yes,这告诉 ccache 不要打扰上述优化,只需将原始 C 或 C++ 文件传递​​给 clang。这会花费多少性能取决于预处理与编译的成本。

我在 TravisCI(有一个旧的 3.1 版本的 ccache)上遇到了这个问题,这为我解决了这个问题。

您的编译错误可能源于相同的原因:clang 可能会忽略部分或所有系统标头(如 &lt;byteswap.h&gt;)中的错误,但不会忽略“用户代码”中的错误。由于ccache 传递给它一个很大的预处理 blob,它看起来就像是用户代码。

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

【讨论】:

  • 这很有意义,我曾假设它 ccache 可能正在获取源的摘要,然后通过它。明天我会尝试编译一个预处理版本 - 但我敢打赌你有答案,这是完全有意义的
  • 它确实需要源的摘要:这就是它在缓存中查找的方式,但对于编译,它会通过预处理的源。我能够在本地重现该问题:尝试使用任何 -I 参数将 *.i 文件传递​​给 clang,它会以同样的方式失败。
  • 完全忘记这个!
猜你喜欢
  • 1970-01-01
  • 2012-02-19
  • 2018-01-29
  • 2020-10-11
  • 2019-09-19
  • 2014-01-28
  • 2019-12-31
  • 2019-08-04
  • 2011-06-30
相关资源
最近更新 更多