我们最近正在讨论我们在基于 make 的构建过程中处理依赖项的 .d 文件的方式。已提出问题,有时当构建中断时 .d 文件可能会损坏。
我们使用 .DELETE_ON_ERROR 目标来确保如果构建被中断或失败,它在生成过程中的目标文件将被删除。然而,我们也在编译时使用 GCC 生成 .d 文件,这些文件也需要删除。似乎没有一种直接的方法来说明这一点。
所以问题是,有没有一种方法可以在出现错误的情况下哄 make 删除我们的对象和我们的依赖文件?有什么办法可以设置规则,让它知道 .d 和 .o 文件是同时生成的,如果出现错误需要删除吗?
或者,我们还能做些什么来解决损坏的 .d 文件的问题?沿着这些路线的一个建议是生成具有临时名称的 .d 文件,并且每个文件都有一个单独的编译后步骤,将其复制到正确的名称。
最佳答案
一般来说,GNU make 不支持具有多个输出的目标。但是,该规则有一个异常(exception):模式规则。如果您可以构建您的 makefile,使其使用模式规则来生成目标文件,那么您就可以实现您的目标。例如:
.DELETE_ON_ERROR:
all: foo.o
%.o %.d: %.c
@touch $*.d
@touch $*.o
@exit 1
您会看到,当在规则中检测到“错误”时,使用此 makefile 会删除 .d 和 .o 文件。这种方法的优点是它通过描述如何生成 .d 文件以及生成它的规则来更准确地表达依赖关系图。
或者,在这种情况下,一个常见的范例就像您建议的那样:让 GCC 将 .d 文件生成为临时文件名,并且仅在 GCC 命令成功完成后才将其移动到位。通常这是通过 shell 的一个技巧来完成的:
all: foo.o
%.o: %.c
gcc -o $@ -MMD -MF $(basename $@).d.tmp -c $< \
&& mv $(basename $@).d.tmp $(basename $@).d
这里的“魔法”技巧是使用 GCC 标志
-MMD
,它会生成依赖文件作为编译的副作用,以及 -MF
,它允许您指定依赖文件的输出名称;以及shell的使用cmd1 && cmd2
语法,导致 shell 只执行 cmd2
如果 cmd1
成功退出。
关于build-process - 获取 make 以在出错时删除其他文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/640076/