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

vog*_*vog 3 shell makefile stdout gnu-make redirectstandardoutput

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

target_file: src_file
        some_tool src_file > target_file
Run Code Online (Sandbox Code Playgroud)

(当然,在现实中我使用$@$<,但对于这个问题,我更喜欢一个更明确的风格.)

问题是target_fileshell始终使用新的时间戳创建,即使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
Run Code Online (Sandbox Code Playgroud)

但是,这有一个缺点,即Make如果some_tool失败则不会注意到,因为在那种情况下rm接管并返回exitcode 0(成功).

另一种方法可能是:

target_file: src_file
        some_tool src_file > target_file.tmp
        mv target_file.tmp target_file
Run Code Online (Sandbox Code Playgroud)

但是这种代码很乏味,而且在失败时会留下令人讨厌的文件target_file.tmp.

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

And*_*ndo 8

你可以使用特殊目标 .DELETE_ON_ERROR:

如果.DELETE_ON_ERROR在makefile中的任何位置被提及为目标,则make将删除规则的目标(如果它已更改且其配方以非零退出状态退出),就像它接收到信号时一样.

所需要的只是一行:

.DELETE_ON_ERROR:
Run Code Online (Sandbox Code Playgroud)

所有失败的规则都会删除目标.

  • 谢谢!这应该是 make 中的默认行为。 (2认同)