当makefile规则的目标是foreach函数时停止错误

8bi*_*ide 9 makefile gnu-make

我有一个makefile,它定义了一些目标是foreach函数的规则.

$(foreach var,$(list), $($(var)_stuff) $($(var)_more_stuff)):
    @echo Building $@ from $^...
    $(CC) $(FLAGS) ...
Run Code Online (Sandbox Code Playgroud)

有没有办法让make在遇到错误时退出而不通过整个列表.

Oli*_*rth 8

在执行任何规则foreach之前完全评估和替换.所以这个行为应该是相同的,好像你没有使用硬编码规则.换句话说,它与问题没有直接关系.foreach

有你所看到的,大多是在手册中描述的只有少数几个可能的解释在这里:

  • 您正在运行Make with -k--keep-going
  • 您正在运行Make with -i--ignore-errors
  • 您的目标被定义为特殊.IGNORE目标的先决条件
  • 你的食谱以a开头 -
  • 您的食谱实际上并未返回非零退出状态


Rod*_*Rod 8

一种解决方法是exit在失败时"手动"调用.

例如,假设我们有一个目录,scripts其中包含许多.sh我们想要执行的shell脚本(文件名以其结尾).

然后像这样的变量声明:

LIST_OF_SCRIPTS ?= $(wildcard scripts/*.sh)
Run Code Online (Sandbox Code Playgroud)

将为我们提供这些脚本的列表,以及这样的目标:

run-all-scripts
  @$(foreach scriptfile,$(LIST_OF_SCRIPTS),$(scriptfile);)
Run Code Online (Sandbox Code Playgroud)

将运行所有这些脚本,但正如您所注意到的,无论其中一个脚本是否返回错误代码,foreach循环都将继续运行.添加|| exit到命令将强制子命令在出错时退出,然后将Make视为失败.

例如,

run-all-scripts
  @$(foreach scriptfile,$(LIST_OF_SCRIPTS),$(scriptfile) || exit;)
Run Code Online (Sandbox Code Playgroud)

会做你想做的事(我相信).

具体来说,使用你的伪代码示例,我想你想要这样的东西:

$(foreach var,$(list), $($(var)_stuff) $($(var)_more_stuff)):
    @echo Building $@ from $^...
    ($(CC) $(FLAGS) ...) || exit
Run Code Online (Sandbox Code Playgroud)

(我所做的就是将所有内容都包裹(CC) $(FLAGS) ...在parens中并附|| exit加以使其在出错时失败).

  • 我刚刚遇到了这个问题,foreach 循环没有因错误而终止,这个解决方案对我有用。@Oleg 知道了在没有明确检查错误代码的情况下它不会终止的原因。感谢这个解决方案! (5认同)
  • 谢谢,添加'|| exit' 是我的环境中唯一可行的事情并且它有效。 (2认同)

Ole*_*zko 6

不确定您的示例,但可能问题出在;- 查看Makefile : show 和 execute

dirs = $(shell ls)
clean:
    $(foreach dir,$(dirs),echo $(dir);)
Run Code Online (Sandbox Code Playgroud)

生产:

$ make clean
echo bin; echo install.sh; echo Makefile; echo README.md; echo utils;
Run Code Online (Sandbox Code Playgroud)

因此,请检查退出代码只对最后的命令:echo utils