我如何在 Makefile 中捕获命令退出代码以供稍后使用?

我如何在 Makefile 中捕获命令退出代码以供稍后使用?

我有一个 makefile,带有测试套件目标,如下所示:

rcheck:
        foo

这显示了 stdout 上命令的输出foo,并返回一个退出代码,foomake 正常处理该退出代码。

我想添加某物到这个目标,解析foo的输出而不影响现有行为 - 即:

  1. foo的 stdout/stderr 应该像以前一样显示在 stdout/stderr 上
  2. 就 Make 而言,rcheck 目标的最终结果是foo退出代码是什么
  3. stdout fromfoo应该以某种方式传递给第二个命令barbar的退出代码并不重要,bar除了上面的 1. 之外,不应该向 stdout 或 stderr 输出任何内容(除非解决方案意味着bar处理 1. 本身)

这里最巧妙的解决方案是什么?

答案1

如果您不担心数据从 foo 传递到 bar 的时间,并且您可以使用需要在干净目标中处理的临时文件,那么只需:

rcheck:
        foo | tee sometempfile
        -bar < sometempfile >/dev/null 2>/dev/null

另一方面,如果您非常关心时间,那么您可以让 bar 重复其对 stdout 的输入,并尝试如下操作:

rcheck:
        -(foo; echo $$? > sometempfile) | bar
        exit $(cat sometempfile)

我确信会有更干净的方法,但我想到了上面的方法。 (注意,两者均未经测试)

答案2

如果您使用的 shell 支持该pipefail选项(bash、ksh 和 zsh 都支持),您可以这样做:

rcheck:
    set -o pipefail; foo | tee /dev/stderr | { bar >/dev/null 2>&1; true; }

我的 ksh 手册页将该选项记录为:

管道故障
      直到管道的所有组件都完成后,管道才会完成
      完成,返回值将是最后一个非零的值
      命令失败或为零(如果没有命令失败)。

与默认行为相反:

管道的退出状态是最后一个命令的退出状态
除非启用了 pipelinefail 选项。

相关内容