代码之家  ›  专栏  ›  技术社区  ›  Dan Olson

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

  •  7
  • Dan Olson  · 技术社区  · 15 年前

    我们最近讨论了在基于make的构建过程中如何处理依赖项的.d文件。有人提出了这样一个问题:当构建被中断时,.d文件有时会损坏。

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

    或者,我们还可以做些什么来修复损坏的.d文件的问题吗?沿着这些思路的一个建议是使用临时名称生成.d文件,并且每个文件都有一个单独的编译后步骤,将其复制到正确的名称。

    2 回复  |  直到 15 年前
        1
  •  6
  •   Eric Melski    12 年前

    一般来说,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命令成功完成后将其移动到位。通常,这是通过壳的技巧实现的:

    all: foo.o
    
    %.o: %.c
        gcc -o $@ -MMD -MF $(basename $@).d.tmp -c $< \
            && mv $(basename $@).d.tmp $(basename $@).d
    

    这里的“魔术”是使用GCC标志 -MMD ,生成依赖项文件作为编译的副作用,以及 -MF ,用于指定依赖项文件的输出名称;以及外壳的使用 cmd1 && cmd2 语法,这将导致shell仅执行 cmd2 如果 cmd1

        2
  •  -1
  •   Wim    13 年前

    埃里克的两个例子我都没有用。当您传入-MM开关时,GCC(版本4.4)不会编译任何东西,因此看起来您无法一次性编译和编写.d。以下是我所做的:

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

    它首先删除一个现有的.d文件,生成新文件的第三行只有在第二个命令(实际的编译步骤)成功时才会执行(Eric的技巧不是必需的,make会自动执行)。 出于某种原因,我不明白,如果编译失败,现有的.o文件不会自动删除,但通过添加 $@ 首先 rm .