说我有以下文件:
buggy_program:
#!/bin/sh
echo "wops, some bug made me exit with failure"
exit 1
Run Code Online (Sandbox Code Playgroud)
Makefile文件:
file.gz:
buggy_program | gzip -9 -c >$@
Run Code Online (Sandbox Code Playgroud)
现在如果我输入make
,file.gz
即使buggy_program
退出非零状态,GNU make也会很乐意构建.
在bash中set -o pipefail
,如果管道中至少有一个程序出现故障,我可以做一个失败的管道退出.GNU make中有类似的方法吗?或者一些不涉及临时文件的解决方法?(这里gzipping的原因正是为了避免一个巨大的临时文件.)
Qua*_*ong 21
试试这个
SHELL=/bin/bash -o pipefail
file.gz:
buggy_program | gzip -9 -c >$@
Run Code Online (Sandbox Code Playgroud)
这是一个不需要bash的可能解决方案.想象一下,你有两个项目thisworks
和thisfails
失败或分别做工精细.然后以下只会留下你work.gz
,删除fail.gz
,即.当且仅当程序正确执行时,创建gzipped make目标:
all: fail.gz work.gz
work.gz:
( thisworks && touch $@.ok ) | gzip -c -9 >$@
rm $@.ok || rm $@
fail.gz:
( thisfails && touch $@.ok ) | gzip -c -9 >$@
rm $@.ok || rm $@
Run Code Online (Sandbox Code Playgroud)
说明:
在work.gz
规则的第一行,thisworks
将成功退出,并将work.gz.ok
创建一个文件,并且所有stdout都通过gzip进入work.gz
.然后在第二行,因为work.gz.ok
存在,第一个rm
命令也会成功退出 - 并且由于||
是短路,第二个命令rm
不会运行,因此work.gz
不会被删除.
OTOH,在第一行fail.gz
的规则,thisfails
将与失败退出,fail.gz.ok
将不会被创建.所有stdout仍然通过gzip进入fail.gz
.然后,在第二行中,因为fail.gz.ok
没有不存在,则第一rm
命令退出故障,所以||
尝试第二个rm
,其删除该命令fail.gz
文件.
为了方便地查看这个工程,因为它应该,只需更换thisworks
并thisfails
与命令true
和false
分别,把它放在一个Makefile和类型make
.
(感谢#autotools中善良的人帮助我解决这个问题.)
你可以这样做:
SHELL=/bin/bash
.DELETE_ON_ERROR:
file.gz:
set -o pipefail; buggy_program | gzip -9 -c >$@
Run Code Online (Sandbox Code Playgroud)
但这只适用于bash.