如何使失败的$(shell)命令中断Make

Car*_*org 20 shell makefile

我有一个Makefile,它在应用构建规则之前运行工具开始(这个工具为我写的).如果这个工具是一个python脚本,以非空状态代码退出,我希望GNU Make在那里停止,而不是继续构建程序.

目前,我做这样的事情(顶级,即第1列):

$(info Generating build rules...)
$(shell python collect_sources.py)
include BuildRules.mk
Run Code Online (Sandbox Code Playgroud)

但是如果collect_sources.py退出时状态代码为1,则不会停止make .这也会捕获标准输出collect_sources.py但不打印出来,所以我感觉我看错了方向.

如果可能的话,解决方案甚至应该在简单的MS-DOS shell是标准系统shell时工作.

有什么建议吗?

mwe*_*den 6

可能有更好的方法,但我尝试了以下内容并且它有效:

$(if $(shell if your_command; then echo ok; fi), , $(error your_command failed))
Run Code Online (Sandbox Code Playgroud)

在这里,我确实假设your_command不提供任何输出,但解决这种情况应该不难.

编辑:为了使它可以使用默认的Windows shell(可能是任何体面的shell),你可以编写your_command && echo ok而不是ifshell函数内.我不认为这对于(较旧的)DOS shell是可能的.对于这些,您可能希望调整your_command或编写包装器脚本以在错误(或成功)上打印某些内容.


Jes*_*erE 5

您应该使用常规目标来创建 BuildRules.mk:

BuildRules.mk: collect_sources.py
        python $< >$@

include BuildRules.mk
Run Code Online (Sandbox Code Playgroud)

这是自动生成依赖项时使用的标准技巧。


Car*_*org 4

好的,这是我自己的解决方案,不幸的是,它不是基于collect_sources.py 脚本的状态代码,但它对我有用(TM)并让我看到脚本产生的任何输出:

SHELL_OUTPUT := $(shell python collect_sources.py 2>&1)
ifeq ($(filter error: [Errno %],$(SHELL_OUTPUT)),)
  $(info $(SHELL_OUTPUT))
else
  $(error $(SHELL_OUTPUT))
endif
Run Code Online (Sandbox Code Playgroud)

编写脚本时,任何错误都会产生以 开头的输出"collect_sources: error:"。此外,如果 python 无法找到或执行给定的脚本,它会输出包含该消息"[Errno 2]"或类似消息的错误消息。所以这段代码只是捕获输出(将 stderr 重定向到 stdout)并搜索错误消息。如果没有找到,它只是使用$(info)打印输出,否则它使用$(error),这实际上使 Make 停止。

请注意, 中的缩进ifeq ... endif是用空格完成的。如果使用选项卡,Make 会认为您正在尝试调用命令并对此进行抱怨。