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



我有一个Makefile,它在应用构建规则(该工具为我编写)之前先运行一个工具。如果这个工具是一个python脚本,它以非null状态代码退出,我希望GNUMake停止,不再继续构建程序。

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

$(info Generating build rules...)
$(shell python collect_sources.py)
include BuildRules.mk

但如果collect_sources.py以状态代码1退出,则这不会停止。这也捕获了collect_sources.py的标准输出,但没有打印出来,所以我有一种看错方向的感觉。

如果可能的话,当一个简单的MS-DOS shell是标准的系统shell时,该解决方案应该也能工作。

有什么建议吗?

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

$(if $(shell if your_command; then echo ok; fi), , $(error your_command failed))

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

编辑:为了使它与默认的Windows shell(可能还有任何合适的shell)一起工作,您可以在shell函数中编写your_command && echo ok而不是if。我认为这对于(旧的)DOS shell是不可能的。对于这些,您可能想要调整your_command,或者编写一个包装脚本,以便在出错(或成功)时打印一些内容。

好吧,这是我自己的解决方案,不幸的是,它不是基于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

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

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

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

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

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

修复https://stackoverflow.com/a/226974/192373

.PHONY: BuildRules.mk
BuildRules.mk: collect_sources.py
        echo Generating build rules...)
        python $< >$@
        $(MAKE) -f BuildRules.mk

确保您没有使用-k选项调用Make/gmake。

最新更新