使用带有依赖项生成的预编译头

问题描述 投票:0回答:1

人:

我正在尝试将预编译头与依赖项生成(-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”

已验证:

  • 使用 strace - 验证 gcc 在依赖项生成期间不尝试访问 pch
  • 使用“gcc -v” - 验证的 pch-deps 和无效的 pch 传递给 cc1
  • obj/h.h.gch 文件已生成,具有正确的权限等
gcc makefile dependency-management pch
1个回答
0
投票

你有这个目录树:

$ 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
    不会认为头文件与预编译头相匹配 与头文件不在同一目录中的文件。

GCC 手册:3.22 使用预编译头文件

编译中看到#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"
      |          ^~~~~
© www.soinside.com 2019 - 2024. All rights reserved.