【问题标题】:Makefile result message during parallel build并行构建期间的 Makefile 结果消息
【发布时间】:2019-09-23 21:25:48
【问题描述】:

给定一个经常使用 -j 标志运行的 Makefile,用于并行构建。我希望它以结果消息终止。我希望这条消息说明构建是否失败,如果失败,错误是什么。如果构建成功(尽管可以),它不必说任何内容,但它必须在目标构建失败时警告用户以及原因。

此行为在顺序构建期间已经存在,但在并行构建期间不存在。并行构建将输出交织在一起,并且错误消息经常被忽略,因为来自其他目标的输出可能会将失败目标的错误推离屏幕。粗心的开发人员可能在他/她的屏幕上看不到任何错误,并认为构建成功。

这是一个非常直观的功能,我已经搜索了答案,但似乎没有任何直接的解决方案。有什么想法吗?

【问题讨论】:

标签: makefile


【解决方案1】:

你基本上是在跑

make -j 8 2> >(tee /tmp/error.log)
test $? -ne 0 && echo "build errors:"
cat /tmp/error.log

构建完成后,您将获得所有标准错误。

【讨论】:

  • 这实际上比我的解决方案更干净一些,因为它将所有标准错误传送到输出,而不是寻找特定的字符串。大多数编译器/链接器向标准错误输出错误和警告,因此这将为您提供一种简单的方法来查找所有失败的内容,而无需对格式做出任何假设。上面的语法是 bash 特定的,在 make 经常使用的 bourn shell (sh) 中不起作用。如果您想在 makefile 中执行此操作,您可以切换默认 shell(或参见 this answersh 中执行此操作)
  • 我想这以一种创造性的方式解决了我的问题,但这并不是我想要的。人们总是可以手动检查$? 中的返回码以查看是否有错误并在终端中向上滚动直到找到错误,但并非每个开发人员都会记得这样做。我可以将它放在一个脚本中并使用该脚本作为入口点,但这不是一个规范的 Makefile 解决方案,并增加了脚本的开销。
【解决方案2】:

-- 编辑--

更新以使用 tee,输出到标准输出并写入文件:


如果其中一个配方失败,则 Make 返回非零,因此您可以从命令行执行类似的操作(假设 bash shell):

make 2>&1 | tee build.log
[ ${PIPESTATUS}[0] -eq 0 ] || ( echo "MAKE FAILED!"; grep --color build.log "Error:" )

${PIPESTATUS}[0] 为您提供第一个命令的退出代码 (make 2>&1),而不是整个命令的退出状态(如果 make 失败,退出状态将是 tee)。它是特定于 bash 的,因此它在 zsh 中不起作用。

或者,您可以添加与递归 make 的顶级目标相同的逻辑。

ifndef IN_RECURSION
export IN_RECURSION:=1

$(info At top level -- defining default target)

_default: 
    @echo "doing recursive call of make"
    @$(MAKE) $(MAKECMDGOALS) IN_RECURSION=1 2>&1 | tee build.log; \
     [ ${PIPESTATUS}[0] -eq 0 ] || ( echo "MAKE FAILED!"; grep --color "Error:" build.log )

.PHONY: _default

endif

all: 
   ....

请注意,在这种情况下,用于连接两个配方行的 \ 至关重要,因为第二个命令必须与第一个命令在相同的 shell 实例中运行。

【讨论】:

  • 我将 sn-p 添加到我的 Makefile 中,但它似乎不起作用。什么都没有被执行。也许我对 GNU Make 的理解太有限了,但我的印象是在运行期间调用了.PHONY,它执行了_default,然后_default 使用给定的相同参数调用make,如果出现问题,从build.log 打印错误,对吗?到目前为止,似乎根本没有执行_default。我在@$(MAKE) 之前添加了一个虚拟回声,没有打印任何内容。
  • .PHONY 只是告诉 make _default 不代表文件名——参见here。这不是一个实际的目标。因此,代码 sn-p 定义了目标 _default。如果这是 makefile 中的第一个目标,那么 make 应该调用它...尝试在目标上方添加 $(info got here) 以查看它是否包含在内。还要确保它是第一个目标。此外,示例管道输出到 build.log,而不是在屏幕上显示。我将修改示例以使用tee...
猜你喜欢
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
相关资源
最近更新 更多