clang++ 不尊重 -isystem 标志,与 g++ 的行为不同
clang++ does not respect -isystem flag, different behavior from g++
在我的 macOS 系统上,我安装了以下软件:
- Protobuf 3.14.0 通过
brew install protobuf@3.14
- 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>
finds the file /usr/local/include/google/protobuf/any.h
. I would expect it to find the file src/google/protobuf/any.h
,因为该文件存在并且我通过了 -isystem src
。自 3.14.0 版本以来,私有函数 InternalPackFrom
的签名已更改,因此出现错误。
此外,当我尝试用 g++-10
替换 clang++
时,我得到了一个成功的构建。 (我的印象是 Clang 努力实现与 GCC 的标志对标志兼容性):
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 Malyshev and Ave Milia 中的 answers/comments,明显的原因是 Apple 的自定义 clang++
版本(在安装 XCode 时安装)总是在 /usr/local/include
处插入 /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
在我的 macOS 系统上,我安装了以下软件:
- Protobuf 3.14.0 通过
brew install protobuf@3.14
- 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>
finds the file /usr/local/include/google/protobuf/any.h
. I would expect it to find the file src/google/protobuf/any.h
,因为该文件存在并且我通过了 -isystem src
。自 3.14.0 版本以来,私有函数 InternalPackFrom
的签名已更改,因此出现错误。
此外,当我尝试用 g++-10
替换 clang++
时,我得到了一个成功的构建。 (我的印象是 Clang 努力实现与 GCC 的标志对标志兼容性):
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 Malyshev and Ave Milia 中的 answers/comments,明显的原因是 Apple 的自定义 clang++
版本(在安装 XCode 时安装)总是在 /usr/local/include
处插入 /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