Makefile gnumake:运行shell命令并使用退出代码设置全局变量
我有一个复杂的脚本Makefile gnumake:运行shell命令并使用退出代码设置全局变量,makefile,gnu-make,Makefile,Gnu Make,我有一个复杂的脚本c.sh,它测试机器运行环境的某些部分。它应该使用bash运行。它会打印一些有用的信息,供stdout和stderr使用。如果满足某些特殊条件,c.sh存在,退出代码为1,否则为0。如果出现问题,可能会出现其他退出代码。根据退出代码,我希望执行不同的配方 all: # test using c.sh everything-OK: # prerequisites # *recurse* on this if c.sh exits with zero #
c.sh
,它测试机器运行环境的某些部分。它应该使用bash
运行。它会打印一些有用的信息,供stdout
和stderr
使用。如果满足某些特殊条件,c.sh
存在,退出代码为1,否则为0。如果出现问题,可能会出现其他退出代码。根据退出代码,我希望执行不同的配方
all:
# test using c.sh
everything-OK: # prerequisites
# *recurse* on this if c.sh exits with zero
# e.g. "$(MAKE) everything-OK" in all if ...
something-went-wrong: # prerequisites
# *recurse* on this if c.sh exists with anything else
我已经找到了有用的答案,但并没有多大帮助。因为我似乎无法根据退出代码使递归或if开关工作。使用$(.SHELLSTATUS)
起初看起来很有希望,但该解决方案不会立即从脚本重定向stdout
另一种解决方案可能如下所示:
EVERYTHING_OK = 0 # 0: false, 1: true
all:
# test using c.sh
# set EVERYTHING_OK depending on exit code
$(MAKE) second-stage
ifeq (1,EVERYTHING_OK)
second-stage: # prerequisites
# ...
else
second-stage: # prerequisites
# ...
endif
(我更喜欢这样,因为我可以将if条件放在宏中)如果您只对脚本的退出状态感兴趣,最简单的方法可能是在make变量中捕获它,并在make条件或目标名称中使用它。目标名称的示例:
C_EXIT_STATUS := $(shell ./c.sh &> /dev/null; echo $$?)
.PHONY: all everithing-%
all: everything-$(C_EXIT_STATUS)
everything-0:
@echo "all right"
everything-%:
@echo "not all right ($*)"
然后,如果退出状态为0的/c.sh
:
$ make all
all right
而如果它以状态7退出:
$ make all
not all right (7)
带有make条件的示例:
C_EXIT_STATUS := $(shell ./c.sh &> /dev/null; echo $$?)
.PHONY: all
ifeq ($(C_EXIT_STATUS),0)
all:
@echo "all right"
else
all:
@echo "not all right ($(C_EXIT_STATUS))"
endif
最后但并非最不重要的一点是,正如您自己所建议的,递归生成也是一个选项:
.PHONY: all
ifeq ($(C_EXIT_STATUS),)
all:
s=0; ./c.sh &> /dev/null || s=$$?; \
$(MAKE) C_EXIT_STATUS=$$s
else ifeq ($(C_EXIT_STATUS),0)
all:
@echo "all right"
else
all:
@echo "not all right ($(C_EXIT_STATUS))"
endif
我是否也可以使用
1>&2
而不是&>
将调用的输出重定向到c.sh
?是否尝试在make变量中捕获标准输出和退出状态?我希望stdout(和-err)保持可见,因为它包含错误信息。我已经测试过了,它能正常工作。啊,好的,我明白了。是的,绝对可以,您可以将stdout
重定向到stderr
,并保留stdout
作为退出状态。