我正在尝试编写一个 makefile,它能够确定 header 何时更改,然后重新编译相应的 .cpp 文件。为了对此进行测试,我创建了三个文件:main.cpp
、a.h
和 b.h
。 main.cpp
包含 sa.h
和 a.h
包含 b.h
。
我的 makefile 看起来像这样:
prog: main.cpp a.h
g++ main.cpp -o prog
a.h: b.h
当 a.h
、b.h
和 main.cpp
的任意组合发生变化时,我希望 prog
重新编译。尽管如此,prog
仅在 a.h
或 main.cpp
更改时重新编译,最后一行似乎被忽略。
我做错了什么,如果不向每个单独的 .cpp 文件添加完整的 header 集,我该如何完成我想要的(因为对于较大的项目,这可能会变得非常麻烦):
prog: main.cpp a.h b.h
g++ ...
最佳答案
What am I doing incorrectly
您的规则:
a.h: b.h
只是告诉 make
a.h
依赖于 b.h
,即 a.h
需要
以 make
可以从 makefile 中确定的任何方式被(重新)制作,如果
a.h
早于 b.h
或不存在。
它不会告诉 make
做什么 从 b.h
重新制作 a.h
。你的生成文件
不包含从 b.h
重新制作 a.h
的配方。它只包含一个食谱
从main.cpp
和a.h
重新制作prog
,即:
prog: main.cpp a.h
g++ main.cpp -o prog
此外 make
,当然,没有内置的规则和配方
a.h
来自 b.h
。所以在没有任何从b.h
制作a.h
的方法的情况下
它假定此依赖项无需执行任何操作。没有
其他合理默认。所以即使 a.h
比 b.h
旧,也没什么
对 a.h
完成;虽然 prog
依赖于 a.h
,但不需要做任何事情
到该帐户的 prog
。
这是幸运的,因为事实上你不希望 a.h
在
当 b.h
改变时以任何方式进行,并且您不希望 main.cpp
成为
当 a.h
或 b.h
更改时以任何方式重新制作。你希望 prog 成为
当其中任何一个发生变化时重新制作。你想要的是任何表达
以下生成文件:
1
prog: main.cpp a.h b.h
g++ main.cpp -o prog
2
prog: main.cpp a.h
g++ main.cpp -o prog
prog: b.h
3
prog: main.cpp b.h
g++ main.cpp -o prog
prog: a.h
4
prog: main.cpp
g++ main.cpp -o prog
prog: a.h b.h
5
prog: main.cpp
g++ main.cpp -o prog
prog: a.h
prog: b.h
(以及更多)。它们都是等价的。他们都说 prog
取决于
在 main.cpp
、a.h
和 b.h
上,它们都说明了无论何时要做什么
prog
需要重新制作,即:
g++ main.cpp -o prog
how can I accomplish what I want without adding the full and complete set of headers to each individual .cpp file like this (since for larger projects this could become extremely cumbersome)
的确如此,因此 GCC 编译器长期以来一直
用于生成表达依赖关系的迷你 makefile 的功能
将在每个头文件上生成的目标文件
被读取以生成目标文件。 GNU make 可以利用这个特性
生成那些依赖文件,并将它们包含在用于构建 GCC 目标的 makefile 中。之间的这种合作
GCC 和 make
被称为自动依赖生成(或类似的)。这
如何在 makefile 中执行此操作的问题是 this one 的拷贝
如果你谷歌,例如“gcc auto generate dependencies”你也可以找到 guru treatments。
在评论中,您表示您还不够精通 GNU 对所示的自动依赖生成技术充满信心 在 those answers .那么,你 可以开始通过简单的基本实现来掌握它 像这样(这也使得 makefile 在其他方面更正常):
生成文件
.PHONY: all clean
all: prog
prog: prog.o
prog.o: main.cpp
g++ -MMD -c -o prog.o main.cpp
prog: prog.o
g++ -o prog prog.o
clean:
rm -f prog *.o *.d
-include prog.d
-MMD
是生成依赖文件的GCC预处理器选项
程序.d
。这是 the documentation of -MMD
prog.d
是一个迷你 makefile:
$ cat prog.d
prog.o: main.cpp a.h b.h
表示 prog.o
的所有依赖项。这是第一次运行,
include
编辑的 makefile prog.d
将不存在,这将是致命的 make
错误,但因为 -
前缀告诉 make
忽略该错误。
所以 make
继续进行,所有的东西,包括 prog.d
都被制作出来,然后
prog.d
将在任何规则出现时重新生成 - 包括 prog.d
中的规则
本身 - 需要重新编译 prog.o
。
关于c++ - 同一 Makefile 中 make 目标之间的递归依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41906725/