相当于GNU make中的pipefail?

时间:2014-04-15 09:27:45

标签: makefile pipe

说我有以下文件:

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的原因正是为了避免一个巨大的临时文件。)

3 个答案:

答案 0 :(得分:19)

试试这个

SHELL=/bin/bash -o pipefail

file.gz:
    buggy_program | gzip -9 -c >$@

答案 1 :(得分:8)

这是一个不需要bash的可能解决方案。想象一下,你有两个程序thisworksthisfails分别失败或工作正常。然后,以下内容只会留下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文件。


要轻松检查这是否正常,只需分别用命令thisworksthisfails替换truefalse,将其放入Makefile并输入make

(感谢#autotools中善良的人帮助我。)

答案 2 :(得分:5)

你可以这样做:

SHELL=/bin/bash

.DELETE_ON_ERROR:
file.gz:
    set -o pipefail; buggy_program | gzip -9 -c >$@

仅适用于bash