在make目标的if语句中,是否可以将一个变量与多个值进行比较



我正试图运行一个在CLI上传递特定值的make-target,但该值应与2个或多个可能的值进行比较,就像在CLI上传递的值应等于预先存在的列表中的任何一个值一样,这样,如果块被执行,条件就会变为true!

.PHONY:plan-infra
plan-infra: configure  ## Plan Infra
@if [ "${infra_module_path}" = "emr" or "gmr" ]; then
echo "test";
fi

$ make plan-infra -e infra_module_path=emr

因此,如果变量";模块路径下";是";emr";或";gmr";应该执行if块!

过滤器GNU make函数是您的朋友:

.PHONY:plan-infra
MATCH := $(filter emr gmr,$(infra_module_path))
plan-infra: configure  ## Plan Infra
@if [ -n "$(MATCH)" ]; then
echo "test";
fi

但请注意,如果您传递包含多个空格分隔的令牌的值,并且至少有一个匹配,例如,这也会匹配

make plan-infra -e infra_module_path="emr foo bar"

正如MadScientist所指出的,filter-out要好一点,因为当字符串只包含过滤后的令牌时,它会返回空字符串;因此它更准确:

.PHONY:plan-infra
MATCH := $(filter-out emr gmr,$(infra_module_path))
plan-infra: configure  ## Plan Infra
@if [ -z "$(MATCH)" ]; then
echo "test";
fi

但它仍然不是100%准确:

make plan-infra -e infra_module_path="emr qmr"

仍然匹配。如Charles Duffy和MadScientist所指出的,如果你真的需要精确匹配,尽管使用make函数是可行的(至少在你的情况下(,但最好使用shell结构。万一您绝对需要使用make函数进行精确匹配:

.PHONY:plan-infra
ifeq ($(words $(infra_module_path)),1)
MATCH := $(filter-out emr gmr,$(infra_module_path))
else
MATCH := no
endif
plan-infra: configure  ## Plan Infra
@if [ -z "$(MATCH)" ]; then
echo "test";
fi

您可以使用shell OR(-o(条件,或者使用case语句来检查两个可能值中的一个。案例陈述更容易理解。

使用if:

.PHONY:plan-infra
plan-infra: configure  ## Plan Infra
@if [ "${infra_module_path}" = "emr" -o "${infra_module_path}" = "gmr" ]; then
echo "test";
fi

$ make plan-infra -e infra_module_path=emr

用例:

.PHONY:plan-infra
plan-infra: configure  ## Plan Infra
@case "${infra_module_path"}" in emr | gmr) echo "test";; esac
$ make plan-infra -e infra_module_path=emr

我可能建议使用make条件语句,而不是bash条件语句。你可能想做:

plan-infra: configure  ## Plan Infr
ifeq ($(filter-out emr gmr,$(infra_module_path)),)
@echo "in emr or gmr";
else
@echo "not in emr or gmr"
endif

(请注意,ifeqelseendif前面有空格,而不是制表符——实际上并不需要空格,但它们对可读性很有用(

我认为,这个问题可以通过以下方式彻底解决:

  1. 使用filter,而不是findsting-选择完全匹配
  2. 使用单词,过滤掉(先验不正确的(多单词参数
  3. 如果内部允许空格,则可以拆分(不是我的情况(

这种方法允许与两个或更多的参数值进行比较。

这是我的项目中的插图,但经过适当的重命名:

ifeq ($(words ${infra_module_path}),1)
MATCH:=$(or $(filter emr,${infra_module_path}),$(filter gmr,${infra_module_path}),$(filter qa,${infra_module_path}),$(filter pre-prod,${infra_module_path}))
else
MATCH:=
endif
$(if ${MATCH},,$(error not recognised infra_module_path))

最新更新