在同一个Makefile中生成目标之间的递归依赖关系

时间:2017-01-28 05:41:23

标签: c++ makefile

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

我的makefile如下所示:

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

a.h: b.h

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

我做错了什么,如何在不向每个单独的.cpp文件添加完整和完整的标题集的情况下完成我想要的内容(因为对于较大的项目,这可能会变得非常麻烦):

prog: main.cpp a.h b.h
        g++ ...

1 个答案:

答案 0 :(得分:6)

  

我做错了什么

你的规则:

a.h: b.h

仅告诉make a.h取决于b.h,即a.h需要make 以({1}}可以从makefile中确定的任何方式(重新)创建if a.h早于b.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的{​​{1}}。因此,如果没有任何方法,可以从b.h制作a.h 它假定这种依赖性要求无需执行任何操作。没有 其他合理的默认。因此即使b.h早于a.h,也没有。{ 完成b.h;虽然a.h取决于prog,但不需要做任何事情 到该帐户的a.h

这很幸运,因为事实上你不想重新制作 prog a.h更改时的任何方式,并且您不希望b.h成为main.cppa.hb.h更改时以任何方式重新制作。你想要 prog 当任何一个改变时重制。你想要的是任何一个表达的 以下makefile:

<强> 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
  

如何在不添加完整整套的情况下完成我想要的任务   像这样的每个.cpp文件的标头   (因为对于较大的项目,这可能变得非常麻烦)

确实会这样,因此GCC编译器已经有很长一段时间了 用于生成表示依赖性的迷你makefile的功能 将在每个头文件上生成的目标文件 被读取以便制作目标文件。 GNU make可以利用此功能 生成那些依赖文件并将它们包含在makefile中以构建GCC目标。这种合作之间 GCC和make称为自动依赖生成(或类似)。该 如何在makefile中执行此操作的问题与this one重复 如果你谷歌,例如“gcc auto generate dependencies”你也可以找到guru治疗。

在评论中,您建议您还没有足够的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