人:
我正在尝试将预编译头与依赖项生成(-MM)结合起来。最终目标是生成make的依赖文件。无法将它们与 -fpch-deps 组合在一起。动机是加快(增量)构建需要数小时才能构建的庞大代码库。
使用GCC 9.3.1,“C”代码。 与 GCC10 (Redhat 版本) 的结果相同
src/a.c:
#include "h.h"
int main(int argc, char **argv) { printf("hello\n") ; }
include/h.h
#include <stdio.h>
用类似的东西进行测试:
mkdir obj
gcc include/h.h -o obj/h.h.gch
# Compile against PCH
gcc -I obj src/a.c
# Validation:
# Next line will print hello - showing PCH-based build works.
obj/a.out
# Build dependecy from pch - fail
gcc -MM -I obj -fpch-deps a.c -Winvalid-pch
GCC 消息是
fatal error: h.h: no such file or directory
,这意味着它没有搜索 obj/h.h.gch。
有什么帮助吗,我是否误解/滥用了“-fpch-deps”
已验证:
你有这个目录树:
$ tree
.
├── include
│ └── h.h
├── obj
└── src
└── a.c
所以命令:
$ gcc include/h.h -o obj/h.h.gch
$ gcc -I obj src/a.c
必须在
.
中运行才能工作,后者将输出./a.out
,
不是./obj/a.out
命令:
$ gcc -MM -I obj -fpch-deps a.c -Winvalid-pch
cc1: fatal error: a.c: No such file or directory
不会工作,除非你:
$ cd src
正如您所观察到的,它会失败的地方:
$ gcc -MM -I obj -fpch-deps a.c -Winvalid-pch
a.c:1:10: fatal error: h.h: No such file or directory
1 | #include "h.h"
| ^~~~~
为什么会发生这种情况可以通过以下方式查看:
$ gcc -v -MM -I obj -fpch-deps a.c -Winvalid-pch
...[cut]...
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "obj"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/13/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
a.c:1:10: fatal error: h.h: No such file or directory
1 | #include "h.h"
| ^~~~~
compilation terminated.
当前目录下没有
h.h
且:
ignoring nonexistent directory "obj"
obj
下没有目录src
。
如果
-I obj
不容忽视,那么你必须:
$ cd .. # up from src
然后运行:
$ gcc -v -MM -I obj -fpch-deps src/a.c -Winvalid-pch
...[cut]...
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
obj
/usr/lib/gcc/x86_64-linux-gnu/13/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
src/a.c:1:10: fatal error: h.h: No such file or directory
1 | #include "h.h"
| ^~~~~
compilation terminated.
现在找到了 包含目录
obj
,但仍然找不到标题 h.h
,
尽管如此:
$ ls obj
h.h.gch
那是因为那里:
gcc
不会考虑寻找与a匹配的预编译头
找不到头文件。gcc
不会认为头文件与预编译头相匹配
与头文件不在同一目录中的文件。编译中看到#include 则说明是在搜索预编译头文件。当它搜索时 包含的文件(请参阅 C 预处理器中的搜索路径)编译器查找预编译头 在每个目录中查找该目录中的包含文件之前。搜索到的名字是 #include 中指定的名称并附加“.gch”。如果预编译头文件无法使用, 它被忽略了。
例如,如果您有 #include "all.h",并且 all.h.gch 与 all.h 位于同一目录中, 那么如果可能就使用预编译头文件,否则就使用原始头文件。
所以如果你这样做:
$ mv obj/h.h.gch include/
然后:
$ gcc -MM -I include -fpch-deps src/a.c -Winvalid-pch
a.o: src/a.c include/h.h
将会成功,并且您将获得
make
的 a.o
依赖行。但如果你
然后我们要做:
$ mv include/h.h include/hide-h.h
然后再一次:
$ gcc -MM -I include -fpch-deps src/a.c -Winvalid-pch
src/a.c:1:10: fatal error: h.h: No such file or directory
1 | #include "h.h"
| ^~~~~