如果 Make 规则失败,则删除目标文件的优雅方法

Elegant way to remove target file if a Make rule fails

我的 Makefile 中有一条规则,大致如下所示:

target_file: src_file
        some_tool src_file > target_file

(当然,现实中我用的是$@$<,不过这道题我更喜欢直白的风格。)

问题是 target_file 总是由带有新时间戳的 shell 创建,即使 some_tool 失败。在那种情况下,存在一个空的 target_file,即使我修复了潜在的问题,它也不会重建,直到我手动删除 target_file 或触摸 src_file.

此外,some_tool 仅写入标准输出,因此我无法通过 some_tool ... -o target_file.

等更简洁的方法解决此问题

我目前的做法是删除

target_file: src_file
        some_tool src_file > target_file || rm -f target_file

然而,这有一个缺点,如果 some_tool 失败,Make 不会注意到,因为在那种情况下 rm 接管并且 returns exitcode 0(成功).

另一种方法可能是:

target_file: src_file
        some_tool src_file > target_file.tmp
        mv target_file.tmp target_file

但是那种代码很乏味,失败时会留下一个烦人的文件 target_file.tmp

有没有更优雅的方法解决这个问题?

您可以使用 special target .DELETE_ON_ERROR:

If .DELETE_ON_ERROR is mentioned as a target anywhere in the makefile, then make will delete the target of a rule if it has changed and its recipe exits with a nonzero exit status, just as it does when it receives a signal.

只需要一行:

.DELETE_ON_ERROR:

所有失败的规则都将删除其目标。