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

发布于 2024-07-08 09:58:25 字数 479 浏览 6 评论 0原文

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

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

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

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

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

有什么建议吗?

I have a Makefile that starts by running a tool before applying the build rules (which this tool writes for me). If this tool, which is a python script, exits with a non-null status code, I want GNU Make to stop right there and not go on with building the program.

Currently, I do something like this (top level, i.e. column 1):

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

But this does not stop make if collect_sources.py exits with a status code of 1. This also captures the standard output of collect_sources.py but does not print it out, so I have the feeling I'm looking in the wrong direction.

If at all possible, the solution should even work when a simple MS-DOS shell is the standard system shell.

Any suggestion?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

单调的奢华 2024-07-15 09:58:26

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

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

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

编辑:要使其与默认的 Windows shell(可能还有任何像样的 shell)一起工作,您可以编写 your_command && echo ok 而不是 shell 函数中的 if。 我认为这对于(较旧的)DOS shell 来说是不可能的。 对于这些,您可能需要调整 your_command 或编写一个包装脚本来打印错误(或成功)的内容。

There might be a better way, but I tried the following and it works:

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

Here I did assume that your_command does not give any output, but it shouldn't be hard to work around such a situation.

Edit: To make it work with the default Windows shell (and probably any decent shell) you could write your_command && echo ok instead of the if within the shell function. I do not think this is possible for (older) DOS shells. For these you probably want to adapt your_command or write a wrapper script to print something on error (or success).

浅暮の光 2024-07-15 09:58:26

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

BuildRules.mk: collect_sources.py
        python 
lt; >$@

include BuildRules.mk

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

You should use a regular target to create BuildRules.mk:

BuildRules.mk: collect_sources.py
        python 
lt; >$@

include BuildRules.mk

This is the standard trick to use when automatically generating dependencies.

怪我闹别瞎闹 2024-07-15 09:58:26

好的,这是我自己的解决方案,不幸的是,它不是基于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 会认为您正在尝试调用命令并对此进行抱怨。

Ok, here's my own solution, which is unfortunately not based on the status code of the collect_sources.py script, but which Works For Me (TM) and lets me see any output that the script produces:

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

The script is written so that any error produces an output beginning with "collect_sources: error:". Additionally, if python cannot find or execute the given script, it outputs an error message containing the message "[Errno 2]" or similar. So this little piece of code just captures the output (redirecting stderr to stdout) and searches for error messages. If none is found, it simply uses $(info) to print the output, otherwise it uses $(error), which effectively makes Make stop.

Note that the indentation in the ifeq ... endif is done with spaces. If tabs are used, Make thinks you're trying to invoke a command and complains about it.

过潦 2024-07-15 09:58:26

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

.PHONY: BuildRules.mk

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

Fixing https://stackoverflow.com/a/226974/192373

.PHONY: BuildRules.mk

BuildRules.mk: collect_sources.py
        echo Generating build rules...)
        python 
lt; >$@
        $(MAKE) -f BuildRules.mk
瀟灑尐姊 2024-07-15 09:58:26

基于@MadScientist 对原始问题的评论:

如果您有 GNU make 4.2 或更高版本,您可以检查 $(.SHELL_STATUS)
变量将包含最后一个 $(shell ...) 的退出状态
函数评估

...您可能想定义这个宏:

.SHELLSTATUS_CHECK=$(or $(filter 0,${.SHELLSTATUS}),$(error .SHELLSTATUS_CHECK FAILED with .SHELLSTATUS=$(.SHELLSTATUS)))

...并将其注入到您的代码中,如下所示:

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

Building on @MadScientist's comment on the original question:

If you have GNU make 4.2 or above, you can check the $(.SHELL_STATUS)
variable which will contain the exit status of the last $(shell ...)
function evaluated

... you might like to define this macro:

.SHELLSTATUS_CHECK=$(or $(filter 0,${.SHELLSTATUS}),$(error .SHELLSTATUS_CHECK FAILED with .SHELLSTATUS=$(.SHELLSTATUS)))

... and inject it into your code like this:

$(info Generating build rules...)
$(shell python collect_sources.py)
$(.SHELLSTATUS_CHECK)
include BuildRules.mk
憧憬巴黎街头的黎明 2024-07-15 09:58:26

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

Make sure you're not invoking make/gmake with the -k option.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文