我有一个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。