这是一个简单的Makefile,具有4个目标(a
,b
,c
和all
)。目标b
可能会失败(此处用exit 1
表示)。
a:
echo "a"
b:
exit 1
c:
echo "c"
all: a b c
运行make all
时,c
不会打印,因为b
会失败,因此目标c
不会运行。但是在我的情况下,即使c
失败,我也希望运行b
。
我想知道是否有一种方法可以在目标all
的依赖项中直接直接定义“继续执行错误”策略。
我知道可以通过以下方式达到所需的行为:
make -i all
(--ignore-errors
)或make -k all
(--keep-going
)b
中用-
前缀失败的命令(例如-exit 1
)make a; make b || make c
单独运行任务但是所有这些选项都意味着要修改目标a
,b
或c
,或修改make all
的调用方式。
是否有一种方法可以通过仅修改 all
目标依赖项(类似于all: a -b c
,但是显然该定义不起作用)来实现预期的行为?< / p>
其他要求:即使make all
目标成功,b
也应以退出代码1返回,如果c
失败。
答案 0 :(得分:2)
如果您要运行a, -b, c
的所有配方,即使-<something>
的配方失败,则可以对-<something>
目标使用模式规则:
a c:
@echo "$@"
b:
@echo "$@"; exit 1
all: a -b c
-%:
-@$(MAKE) $*
演示(使用--no-print-directory
可以简化输出):
$ make --no-print-directory all
a
b
Makefile:5: recipe for target 'b' failed
make[1]: *** [b] Error 1
Makefile:10: recipe for target '-b' failed
make: [-b] Error 2 (ignored)
c
但是,如果您还想“记住”它们的退出状态,则事情会有些困难。我们需要将退出状态存储在某个地方,例如存储在文件中,并将其重新用于all
配方:
a c:
@echo "$@"
b:
@echo "$@"; exit 1
all: a -b c
@exit_status=`cat b_exit_status`; exit $$exit_status
-%:
-@$(MAKE) $*; echo "$$?" > $*_exit_status
演示:
$ make --no-print-directory all
a
b
Makefile:5: recipe for target 'b' failed
make[1]: *** [b] Error 1
c
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2
在all
的配方中硬接线可能失败目标的名称不是很优雅。但这应该很容易解决:
a b c:
@echo "$@"
d:
@echo "$@"; exit 1
all: a -b c -d
@for f in $(patsubst -%,%_exit_status,$(filter -%,$^)); do \
tmp=`cat $$f`; \
printf '%s: %s\n' "$$f" "$$tmp"; \
if [ "$$tmp" -ne 0 ]; then exit $$tmp; fi; \
done
-%:
-@$(MAKE) $*; echo "$$?" > $*_exit_status
.PHONY: clean
clean:
rm -f *_exit_status
演示:
$ make --no-print-directory all
a
b
c
d
Makefile:5: recipe for target 'd' failed
make[1]: *** [d] Error 1
b_exit_status: 0
d_exit_status: 2
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2
答案 1 :(得分:0)
虽然您不能通过先决条件名称(或至少仅在完全更改先决条件时)来传递参数,但是可以使用特定于目标的变量。但是解决方案并不完美,在每个配方行前都有一个附加变量:
CIE_DASH = $(if $(filter $@,$(CONTINUE_SET)),-)
all: a b c
all: CONTINUE_SET += b
a:
$(CIE_DASH)echo "a"
b: CONTINUE_SET += e
b: e
$(CIE_DASH)exit 1
e:
$(CIE_DASH)exit 1
c:
$(CIE_DASH)echo "c"