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

joh*_*dav 3 c++ makefile

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

我的makefile看起来像这样:

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

a.h: b.h
Run Code Online (Sandbox Code Playgroud)

当和,和更改的任何组合时a.h,我希望重新编译.尽管如此,只有重新编译时或发生变化,到最后一行似乎被忽略.b.hmain.cppprogproga.hmain.cpp

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

prog: main.cpp a.h b.h
        g++ ...
Run Code Online (Sandbox Code Playgroud)

Mik*_*han 6

我做错了什么

你的规则:

a.h: b.h
Run Code Online (Sandbox Code Playgroud)

只是告诉makea.h取决于b.h,即a.h需要(重新)制成,以任何方式make可以从makefile文件确定,如果 a.h是比旧b.h或不存在.

它没有告诉make 怎么做重拍a.hb.h.你的Makefile不包含食谱的改造a.hb.h.它仅包含改造配方progmain.cppa.h,即:

prog: main.cpp a.h
        g++ main.cpp -o prog
Run Code Online (Sandbox Code Playgroud)

此外make,当然,有制作配方没有内置规则 a.hb.h.所以在没有任何秘方制作a.hb.h 它假定这种依赖性要求无计可施.没有其他合理的默认值.所以即使a.h比年龄大b.h,也没有做任何事情a.h; 虽然prog取决于a.h,但prog该帐户无需进行任何操作.

这是幸运的,因为实际上你不希望 a.h以任何方式重新制作任何b.h变化,并且你不想main.cpp以任何方式重新制作任何时候a.hb.h变化.您希望在任何更改时重建prog.你想要的是由以下任何makefile表达的:

1

prog: main.cpp a.h b.h
    g++ main.cpp -o prog
Run Code Online (Sandbox Code Playgroud)

2

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

prog: b.h
Run Code Online (Sandbox Code Playgroud)

3

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

prog: a.h
Run Code Online (Sandbox Code Playgroud)

4

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

prog: a.h b.h
Run Code Online (Sandbox Code Playgroud)

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

prog: a.h
prog: b.h
Run Code Online (Sandbox Code Playgroud)

(还有一些).他们都是等同的.他们都说这prog取决于main.cpp,a.h而且b.h他们都说prog需要重新制作时要做什么 ,即:

    g++ main.cpp -o prog
Run Code Online (Sandbox Code Playgroud)

如何在不向每个单独的.cpp文件添加完整和完整的标头集的情况下完成我想要的工作(因为对于较大的项目,这可能变得非常麻烦)

实际上它会,并且因此GCC编译器在很长一段时间内都有一个生成mini-makefile的功能,它表示将在每个读取的头文件上生成的目标文件的依赖关系,以便制作目标文件.GNU make可以利用此功能生成这些依赖项文件,并将它们包含在makefile中以构建GCC目标.GCC之间的这种合作make被称为自动依赖生成(或类似).如何在makefile中执行此操作的问题与此相关 ,如果您使用google,例如"gcc auto generate dependencies",您还可以找到guru处理.

在评论中,您建议您尚未充分了解GNU make,以便对这些答案中说明的自动依赖生成技术充满信心.好吧,您可以通过简单的实现开始了解它(这也使得makefile在其他方面更正常):

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
Run Code Online (Sandbox Code Playgroud)

-MMD是生成依赖项文件的GCC预处理器选项 prog.d.这是文档-MMD

prog.d 是一个迷你makefile:

$ cat prog.d 
prog.o: main.cpp a.h b.h
Run Code Online (Sandbox Code Playgroud)

表达的所有依赖关系prog.o.第一次运行时,include-ed makefile prog.d将不存在,这将是一个致命的make 错误,但-前缀告诉make忽略该错误.因此make,无论何时 需要重新编译任何规则(包括规则本身),所以继续进行所有事情,包括prog.d获取,然后 prog.d再进行.prog.dprog.o