为何Clang在编译时未使用已生成的test.hpp预编译头?
Clang 预编译头命中标记异常问题说明
测试用例代码
// test.hpp #include <iostream> // test.cpp #include "test.hpp" int main(){std::cout << "hello world" << std::endl;}
测试操作流程
- 生成预编译头:执行命令
clang++ -c test.hpp,在当前目录生成对应预编译头文件test.hpp.gch - 带头文件路径打印功能编译:执行命令
clang++ test.cpp -H,获取编译过程中的头文件引用链路输出
实际测试现象
GCC 编译时命中预编译头,会在对应引用的头文件路径前显示 ! 标记做提示。本次测试中,Clang 的 -H 输出列表里,test.hpp 条目前没有出现代表预编译头命中的 ! 标记,实际输出内容如下:
. ./test.hpp .. /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/iostream ... /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/x86_64-linux-gnu/c++/9/bits/c++config.h .... /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/x86_64-linux-gnu/c++/9/bits/os_defines.h ..... /usr/include/features.h
问题核心原因
- 预编译头自动加载规则差异:Clang 与 GCC 的默认预编译头查找逻辑不兼容。GCC 会在编译时自动扫描当前目录下与被包含头文件同名的
.gch预编译头文件,匹配成功就直接加载复用;但 Clang 默认 不会 主动扫描加载同目录下生成的预编译头文件,必须通过编译参数显式指定预编译头路径才会触发匹配流程。本次测试使用的编译命令没有添加任何预编译头相关参数,Clang 完全跳过了刚才生成的test.hpp.gch文件,走正常的逐行解析头文件流程,自然不会出现预编译头命中的相关表现。 - 输出标记规则差异:即便通过显式参数让 Clang 正确加载预编译头,Clang 的
-H输出格式也没有照搬 GCC 的!命中标记逻辑,不会在被预编译的头文件路径前追加该标识,这是两个编译器的内置实现区别,不属于功能异常。 - Clang 预编译头正确编译命令参考:如果要让 Clang 实际加载已生成的预编译头,需要执行带显式指定的编译命令:
clang++ test.cpp -H -include-pch test.hpp.gch,此时编译会直接复用预编译头的解析结果,不会逐行展开 test.hpp 内部的#include <iostream>引用链路。
内容的提问来源于stack exchange,提问作者programmer
相关产品推荐
相关产品推荐

