获取make以在出错时删除其他文件

时间:2009-03-12 19:11:20

标签: build-process makefile

我们最近讨论了在基于make的构建过程中处理依赖项的.d文件的方式。提出的问题是,当构建中断时,.d文件有时会被破坏。

我们正在使用.DELETE_ON_ERROR目标来确保在构建中断或失败时,删除它正在生成的目标文件。但是我们也在编译时使用GCC生成.d文件,这些文件也需要删除。似乎没有一种直截了当的方式来说明这一点。

所以问题是,在出现错误的情况下,有没有一种方法可以同步删除我们的对象和我们的依赖文件?我们是否可以通过某种方式设置规则,以便它知道.d和.o文件同时生成,如果出现错误则需要删除?

或者,我们还能做些什么来解决损坏的.d文件的问题吗?这些方面的一个建议是使用临时名称生成.d文件,并为每个文件分别进行一次后编译步骤,将其复制到正确的名称。

2 个答案:

答案 0 :(得分:6)

一般来说,GNU make不支持具有多个输出的目标。但是,该规则有一个例外:模式规则。如果您可以构建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语法的使用,如果cmd2成功退出,则shell只会执行cmd1

答案 1 :(得分:-1)

我没有让Eric的例子正常工作。传入-MM开关时,GCC(版本4.4)不会编译任何内容,因此看起来你不能一次编译和编写.d。这是我做的:

%.o: %.c
    @rm -f $@ $(patsubst %.o,%.d,$@)
    gcc -c $< -o $@
    @$(CXX) -MM -MG > $(patsubst %.o,%.d,$@)

首先删除现有的.d文件,生成新文件的第三行只在第二个命令(实际编译步骤)成功时执行(Eric的&amp;&amp;技巧不是必需的,make确实这自动)。 出于某些原因,我不明白,如果编译失败,则不会自动删除现有的.o文件,但通过将$@添加到第一个rm可以轻松解决这个问题。