说我有以下文件:
buggy_program:
#!/bin/sh
echo "wops, some bug made me exit with failure"
exit 1
生成文件:
file.gz:
buggy_program | gzip -9 -c >$@
现在,如果我输入make
,即使file.gz
以非零状态退出,GNU make也会很乐意构建buggy_program
。
在bash中,如果管道中至少有一个程序出现故障,我可以set -o pipefail
使管道退出失败。 GNU make中有类似的方法吗?或者一些不涉及临时文件的解决方法? (这里gzipping的原因正是为了避免一个巨大的临时文件。)
答案 0 :(得分:19)
试试这个
SHELL=/bin/bash -o pipefail
file.gz:
buggy_program | gzip -9 -c >$@
答案 1 :(得分:8)
这是一个不需要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 $@
说明:
在work.gz
规则的第一行,thisworks
将成功退出,并创建一个文件work.gz.ok
,并且所有标准输出都会通过gzip进入work.gz
。然后在第二行,因为work.gz.ok
存在,第一个rm
命令也会成功退出 - 并且||
short-circuiting为{{3}},第二个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中善良的人帮助我。)
答案 2 :(得分:5)
你可以这样做:
SHELL=/bin/bash
.DELETE_ON_ERROR:
file.gz:
set -o pipefail; buggy_program | gzip -9 -c >$@
但仅适用于bash 。