18

我知道以下 makefile 将使预处理器自动生成依赖项(在 .d 文件中)并将它们包含在 makefile 中(因为我的课程笔记是这样说的),因此不必自动维护它们。旗帜是对此-MMD负责的。我不明白的是: .d 文件是在什么时候生成的?甚至没有${CXXFLAGS}使用任何命令。大概,像这样的命令${CXX} ${CXXFLAGS} -c x.C -o x.o将由 make 为每个目标文件自动推断,但如果这些是生成 .d 文件的命令,我们不是已经过了知道 xo、yo 和 zo 的依赖关系可能相关的地步吗? ,如果我们只通过执行生成这些 .o 文件的命令来了解它们?(假设有 .h 文件,如果让其自行推断规则或其他东西,makefile 将忽略这些文件。)

CXX = g++                     # compiler
CXXFLAGS = -g -Wall -MMD      # compiler flags
OBJECTS = x.o y.o z.o         # object files forming executable
DEPENDS = ${OBJECTS:.o=.d}    # substitutes ".o" with ".d"
EXEC = a.out                  # executable name

${EXEC} : ${OBJECTS}          # link step
    ${CXX} ${OBJECTS} -o ${EXEC}

-include ${DEPENDS}           # copies files x.d, y.d, z.d (if they exist)
4

3 回答 3

15

大概,${CXX} ${CXXFLAGS} -c x.C -o x.omake 会为每个目标文件自动推导出类似的命令,但如果这些是生成 .d 文件的命令,我们不是已经过了知道 xo、yo 和 zo 的依赖关系的地步吗?如果我们只通过执行生成这些 .o 文件的命令来了解它们,那么它们是否相关?

你在这里是对的。第一次运行 Makefile 时不存在依赖项。

但这无关紧要 - 仅当 .o 文件已经存在并且您更改了 .h 文件时才需要依赖信息。第一次运行 Make 时,无论如何都需要构建所有 .o 文件,同时生成 .d 文件。

之后,.d 文件将给出依赖信息。如果一个头被改变,依赖信息会告诉 Make 哪些 .o 文件需要重建。如果源文件发生变化,总是需要重新构建 .o,同时会生成更新的依赖信息。

于 2012-08-08T05:27:05.757 回答
2

如果您想知道背后的 makefile 正在做什么,请使用 -p 标志,并将输出重定向到一个文件,因为它有很多东西。

make -p foo > bar将转储 a 的所有变量值和规则make foo,然后查看bar将显示为隐式规则运行的命令。在您的情况下,它会向您显示.cpp.oor %.o: %.cpp(奇怪的是它们都在那里)规则将调用$(COMPILE.cpp)which resolves to $(COMPILE.cc)which resolves to $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c。它有一个有趣的属性,您可以将内容添加到 CXXFLAGS 或 CPPFLAGS 以将它们添加到您的 .cpp.o 编译中,但不能添加仅由.c.o规则使用的 CFLAGS,这有点意义,因为您可能想要您的 C 文件和 C++ 文件的处理方式不同(CC 和 CXX 通常也设置为不同的编译器)。

于 2015-10-05T01:16:39.243 回答
0

是的,你是对的,如果你删除了依赖文件,但保留了目标文件,那么 make 将使用不完整的依赖信息运行,并且可能无法重新构建标头已更改的目标文件。

Make 也可能拒绝构建 - 当依赖文件引用您已删除的标头时会发生这种情况(并且显然不再从任何其他来源引用)。由于 Make 在编译之前不知道如何重建依赖文件,它所能做的就是报告缺少的依赖项(然后显而易见的操作是删除依赖项文件,导致上面的第一个条件)。

唯一的答案是纪律:删除依赖文件时,始终删除目标文件。您可以使用clean目标来帮助解决此问题。

clean::
        $(RM) *.o *.d

另外,告诉 Make 如何创建依赖文件:

%.dep: %.cc
        $(CXX) -MM $(CPPFLAGS) $< | sed -e 's,\($*\)\.o[ :]*,\1.o $@: ,g' > $@

(该sed命令确保依赖项本身依赖于与目标文件相同的源)。

于 2016-10-25T08:17:10.170 回答