【问题标题】:equivalent of pipefail in GNU make?相当于 GNU make 中的 pipefail?
【发布时间】:2014-05-29 13:37:08
【问题描述】:

假设我有以下文件:

buggy_program:

#!/bin/sh
echo "wops, some bug made me exit with failure"
exit 1

生成文件:

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

现在,如果我输入make,GNU make 将愉快地构建file.gz,即使buggy_program 以非零状态退出。

在 bash 中,如果管道中的至少一个程序因失败退出,我可以使用 set -o pipefail 使管道退出失败。 GNU make 中是否有类似的方法?或者一些不涉及临时文件的解决方法? (这里gzip的原因正是为了避免一个巨大的临时文件。)

【问题讨论】:

    标签: makefile pipe


    【解决方案1】:

    试试这个

    SHELL=/bin/bash -o pipefail
    
    file.gz:
        buggy_program | gzip -9 -c >$@
    

    【讨论】:

    • 请注意,这将影响文件中的每个规则。甚至是上面的那些。
    • /usr/bin/env 可以做到这一点吗?
    【解决方案2】:

    这是一个不需要 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,第二个 rm 没有运行所以work.gz 不会被删除。

    OTOH,在fail.gz 规则的第一行,thisfails 将失败退出,fail.gz.ok创建。所有标准输出仍然通过 gzip 进入fail.gz。然后在第二行中,因为fail.gz.ok 确实 存在,第一个rm 命令失败退出,所以|| 尝试第二个rm 命令删除fail.gz 文件。


    要轻松检查它是否正常工作,只需将 thisworksthisfails 分别替换为命令 truefalse,将其放入 Makefile 并键入 make

    (感谢#autotools 中的好心人帮助我。)

    【讨论】:

    • 你能解释一下这个答案吗?我不确定我是否完全理解这里发生了什么。
    【解决方案3】:

    你可以这样做:

    SHELL=/bin/bash
    
    .DELETE_ON_ERROR:
    file.gz:
        set -o pipefail; buggy_program | gzip -9 -c >$@
    

    但这仅适用于 bash

    【讨论】:

    • 我更喜欢这个解决方案,因为它不会改变整个文件的行为。
    猜你喜欢
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 2015-08-17
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    相关资源
    最近更新 更多