clang++ 不尊重 -isystem 标志,与 g++

问题描述

在我的 macOS 系统上,我安装了以下内容

  • Protobuf 3.14.0 通过 brew install [email protected]
  • g++ 10.2.0_4 通过 brew install gcc@10
  • clang++ 1200.0.32.29 通过 XCode

当我查看 Google 的 Protobuf 存储库并使用 clang++ 构建文件时,它似乎忽略了我传递的 -isystem 标志:

git clone https://github.com/protocolbuffers/protobuf.git && cd protobuf && git checkout 326ea555b
clang++ -std=c++17 -isystem src -c src/google/protobuf/any_lite.cc

这给出了一个错误

src/google/protobuf/any_lite.cc:56:19: error: return type of out-of-line deFinition of 'google::protobuf::internal::AnyMetadata::InternalPackFrom' differs from that in the declaration
bool AnyMetadata::InternalPackFrom(const MessageLite& message,~~~~              ^
/usr/local/include/google/protobuf/any.h:108:8: note: prevIoUs declaration is here
  void InternalPackFrom(const MessageLite& message,~~~~ ^
1 error generated.

发生这种情况是因为 #include <google/protobuf/any.h> 找到了文件 /usr/local/include/google/protobuf/any.h。我希望它找到文件 src/google/protobuf/any.h,因为该文件存在并且我通过了 -isystem src。自 3.14.0 版以来,私有函数 InternalPackFrom 的签名已更改,因此出现错误

此外,当我尝试用 clang++ 替换 g++-10 时,我得到了成功的构建。 (我的印象是 Clang 努力争取与 GCC 的 flag-for-flag 兼容性):

git clone https://github.com/protocolbuffers/protobuf.git && cd protobuf && git checkout 326ea555b
g++-10 -std=c++17 -isystem src -c src/google/protobuf/any_lite.cc

为什么 clang++ 在这里忽略 -isystem 标志?

解决方法

那不是因为-isystem src。出现问题是因为 clang++ 在其标准包含目录列表中包含路径 /usr/local/include,而 g++ 没有。

您可以使用以下命令检查标准包含目录的列表:

clang++ -nostdlib -Wp,-v -E -

g++-10 -Wp,-v -E -

为了避免通过 clang++ 包含 /usr/local/include/google/protobuf/any.h,您可以删除文件或使用 -nostdinc-nostdinc++ 标志并手动传递旧的包含目录。

,

结合来自 Anton MalyshevAve Milia 的答案/评论,显而易见的原因是 Apple 的自定义 clang++ 版本(安装 XCode 时安装)总是在开头插入 /usr/local/include系统包括路径列表,在任何其他条目之上,包括在命令行上传递的 -isystem 选项。 (这可能是一个错误)。您可以通过运行来确认这一点

clang++ -isystem /tmp -Wp,-v -E -

并注意线条

#include <...> search starts here:
 /usr/local/include
 /tmp

在输出中。

上游 clang++g++ 都没有这种行为,所以这是 Apple 构建的一个怪癖。

修复这个问题,您可以使用 Homebrew 安装 llvm

brew install llvm

然后按照

输出的说明将 Homebrew 的 clang++ 放在您的路径上
brew link llvm