直接在目标依赖项中定义 "continue if error" 策略
Define "continue if error" policy directly in target dependencies
这是一个包含 4 个目标(a
、b
、c
和 all
)的简单 Makefile。目标 b
可能会失败(此处用 exit 1
表示)。
a:
echo "a"
b:
exit 1
c:
echo "c"
all: a b c
当 运行ning make all
时,c
永远不会打印,因为 b
失败并且目标 c
因此不是 运行。但在我的特殊情况下,我希望 c
成为 运行,即使 b
失败。
我想知道是否有一种方法可以在目标 all
.
的依赖项中直接 定义 "continue if error" 策略
我知道可以通过以下方式实现所需的行为:
- 运行宁
make -i all
(--ignore-errors
)或make -k all
(--keep-going
)
- 使用 "recursive" make
- 在
b
中用 -
为失败的命令添加前缀(如 -exit 1
)
- 运行宁任务与
make a; make b || make c
分开
但所有这些选项都意味着修改目标 a
、b
或 c
,或修改调用 make all
的方式。
有没有办法通过 修改 all
目标依赖项(类似于 all: a -b c
,但该定义不起作用, 显然)?
附加要求:如果 b
失败,make all
应该 return 退出代码 1,即使 c
目标成功.
虽然您不能通过先决条件名称传输参数(或者至少只有在您完全更改先决条件时),您可以使用特定于目标的变量。但是这个解决方案并不完美,每个配方行都有一个额外的变量:
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"
如果你想 运行 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
这是一个包含 4 个目标(a
、b
、c
和 all
)的简单 Makefile。目标 b
可能会失败(此处用 exit 1
表示)。
a:
echo "a"
b:
exit 1
c:
echo "c"
all: a b c
当 运行ning make all
时,c
永远不会打印,因为 b
失败并且目标 c
因此不是 运行。但在我的特殊情况下,我希望 c
成为 运行,即使 b
失败。
我想知道是否有一种方法可以在目标 all
.
我知道可以通过以下方式实现所需的行为:
- 运行宁
make -i all
(--ignore-errors
)或make -k all
(--keep-going
) - 使用 "recursive" make
- 在
b
中用-
为失败的命令添加前缀(如-exit 1
) - 运行宁任务与
make a; make b || make c
分开
但所有这些选项都意味着修改目标 a
、b
或 c
,或修改调用 make all
的方式。
有没有办法通过 修改 all
目标依赖项(类似于 all: a -b c
,但该定义不起作用, 显然)?
附加要求:如果 b
失败,make all
应该 return 退出代码 1,即使 c
目标成功.
虽然您不能通过先决条件名称传输参数(或者至少只有在您完全更改先决条件时),您可以使用特定于目标的变量。但是这个解决方案并不完美,每个配方行都有一个额外的变量:
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"
如果你想 运行 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