English 中文(简体)
让 make 在出错时删除额外的文件。
原标题:
  • 时间:2009-03-12 19:11:20
  •  标签:

最近我们正在讨论我们在基于make的构建过程中处理依赖项的.d文件的方法。问题已经被提出,有时在构建被中断时.d文件可能会变得损坏。

我们正在使用.DELETE_ON_ERROR目标,以确保如果构建被中断或失败,则删除正在生成过程中的对象文件。但是,我们还在使用GCC在编译时生成.d文件,这些文件也需要被删除。现在没有简单的方法告诉make这一点。

问题是,我们是否有办法在出现错误的情况下引导make删除我们的对象和依赖文件?是否有一些方法可以设置规则,以便它知道.d和.o文件是同时生成的,如果出现错误,则需要删除?

另外,我们还能做些什么来解决损坏的 .d 文件的问题吗?提出的一个建议是使用临时名称生成 .d 文件,每个文件有单独的后期编译步骤将其复制到正确的名称。

最佳回答

一般来说,GNU make 不支持具有多个输出的目标。但是,有一种例外情况:模式规则。如果你可以组织你的 makefile 使它使用模式规则生成对象文件,你就可以实现你的目标。例如:

.DELETE_ON_ERROR:

all: foo.o

%.o %.d: %.c
    @touch $*.d
    @touch $*.o
    @exit 1

你将看到,使用这个makefile时,当规则中检测到"error"时,两个文件.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 允许您指定依赖文件的输出名称;和使用shellcmd1 && cmd2 语法,如果cmd1成功退出,则导致shell仅执行cmd2

问题回答

我无法使 Eric 的任何一个示例正常工作。当您传递-MM开关时,GCC(版本4.4)不会编译任何内容,因此看起来您无法一次编译并写入.d。这是我所做的:

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

It starts out by deleting an existing .d file, the third line which generates the new one is only executed if the second command, the actual compilation step, succeeds (Eric s && trick isn t necessary, make does this automatically). For some reason I don t understand, an existing .o file isn t automatically deleted if the compilation fails, but that was easily solved by adding $@ to the first rm.





相关问题
热门标签