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_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
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
.
有没有更优雅的方法来解决这个问题?
你可以使用特殊目标 .DELETE_ON_ERROR
:
如果.DELETE_ON_ERROR在makefile中的任何位置被提及为目标,则make将删除规则的目标(如果它已更改且其配方以非零退出状态退出),就像它接收到信号时一样.
所需要的只是一行:
.DELETE_ON_ERROR:
Run Code Online (Sandbox Code Playgroud)
所有失败的规则都会删除目标.