我正在尝试编写一个 makefile,它能够确定何时更改了 header ,然后重新编译相应的 .cpp 文件。为了测试这一点,我创建了三个文件: main.cppa.hb.hmain.cpp 包括 s a.ha.h 包括 b.h

我的生成文件如下所示:

prog: main.cpp a.h
        g++ main.cpp -o prog

a.h: b.h

a.hb.hmain.cpp 的任意组合发生变化时,我希望 prog 被重新编译。尽管如此,prog 仅在 a.hmain.cpp 更改时才重新编译,最后一行似乎被忽略。

我在做什么不正确以及如何在不向这样的每个单独的 .cpp 文件中添加完整和完整的 header 集的情况下完成我想要的(因为对于较大的项目,这可能变得非常麻烦):
prog: main.cpp a.h b.h
        g++ ...

最佳答案



你的规则:

a.h: b.h

只是告诉 make a.h 取决于 b.h ,即 a.h 需要
被(重新)制作,以 make 可以从 makefile 中确定的任何方式,如果a.hb.h 旧或不存在。

它没有告诉 make 如何从 a.h 重新制作 b.h 。你的makefile
不包含从 a.h 重新制作 b.h 的方法。它只包含一个配方
用于从 progmain.cpp 重新制作 a.h ,即:
prog: main.cpp a.h
        g++ main.cpp -o prog

此外 make ,当然,没有内置的规则来制作a.h 来自 b.h 。因此,在没有任何从 a.h 制作 b.h 的方法的情况下
它假设这种依赖不需要做任何事情。没有
其他合理违约。因此,即使 a.hb.h 旧,也没有a.h 已完成;尽管 prog 依赖于 a.h ,但无需执行任何操作prog 在该帐户上。

这是幸运的,因为实际上您不希望 a.h
无论何时 b.h 发生任何变化,并且您不希望 main.cpp 成为
a.hb.h 改变时,以任何方式重新制作。你想要前卫
当它们中的任何一个发生变化时重新制作。你想要的由任何一个表达
以下生成文件:

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.cppa.hb.h 上,它们都说明了要做什么prog 需要重新制作,即:
    g++ main.cpp -o prog



确实会,因此 GCC 编译器在很长一段时间内都有
用于生成表示依赖关系的 mini-makefile 的功能
将在每个头文件上生成的目标文件
被读取以制作目标文件。 GNU make 可以利用这个特性
生成这些依赖文件并将它们包含在用于构建 GCC 目标的 makefile 中。之间的这种合作
GCC 和 make 被称为自动依赖生成(或类似)。这
如何在 makefile 中执行此操作的问题是 this one 的拷贝
如果你谷歌,例如“gcc 自动生成依赖项”你也可以找到大师的治疗方法。

在评论中,您建议您对 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 预处理器选项prog.d 。这是 the documentation of -MMD
prog.d 是一个迷你生成文件:
$ cat prog.d
prog.o: main.cpp a.h b.h

表达 prog.o 的所有依赖项。这是第一次运行,include -ed makefile prog.d 将不存在,这将是一个致命的 make错误,但事实上 - 前缀告诉 make 忽略该错误。
因此 make 继续进行,包括 prog.d 在内的所有内容都已生成,此后prog.d 将在任何规则时重新生成 - 包括 prog.d 中的规则
本身 - 需要重新编译 prog.o

关于c++ - 同一 Makefile 中 make 目标之间的递归依赖关系,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41906725/

10-11 18:30