如何根据未设置/赋值的makefile变量中止make/makefile执行?
我想出了这个,但只有在调用者没有明确运行目标(即make只运行)时才有效。
make
ifeq ($(MY_FLAG),) abort: ## This MUST be the first target :( ugly @echo Variable MY_FLAG not set && false endif all: @echo MY_FLAG=$(MY_FLAG)
我认为这样的事情是个好主意,但在make的手册中没有找到任何东西:
ifndef MY_FLAG .ABORT endif
TL;DR :使用error功能:
error
ifndef MY_FLAG $(error MY_FLAG is not set) endif
请注意,这些行不能缩进。更准确地说,这些行之前不能有制表符。
如果您要测试许多变量,则值得为此定义一个辅助函数:
# Check that given variables are set and all have non-empty values, # die with an error otherwise. # # Params: # 1. Variable name(s) to test. # 2. (optional) Error message to print. check_defined = \ $(strip $(foreach 1,$1, \ $(call __check_defined,$1,$(strip $(value 2))))) __check_defined = \ $(if $(value $1),, \ $(error Undefined $1$(if $2, ($2))))
以下是如何使用它: ****
$(call check_defined, MY_FLAG) $(call check_defined, OUT_DIR, build directory) $(call check_defined, BIN_DIR, where to put binary artifacts) $(call check_defined, \ LIB_INCLUDE_DIR \ LIB_SOURCE_DIR, \ library path)
这将输出如下错误:
Makefile:17: *** Undefined OUT_DIR (build directory). Stop.
真正的检查在这里完成:
$(if $(value $1),,$(error ...))
这反映了ifndef条件的行为,因此定义为空值的变量也被认为是“未定义的”。但这仅适用于简单变量和显式空递归变量:
ifndef
# ifndef and check_defined consider these UNDEFINED: explicitly_empty = simple_empty := $(explicitly_empty) # ifndef and check_defined consider it OK (defined): recursive_empty = $(explicitly_empty)
正如@VictorSergienko 在评论中所建议的那样,可能需要稍微不同的行为:
$(if $(value $1)测试该值是否为非空。 如果变量定义为空值, 有时也可以。我会用$(if $(filter undefined,$(origin $1)) ...
$(if $(value $1)
$(if $(filter undefined,$(origin $1)) ...
和:
此外, 如果它是一个目录并且在运行检查时它必须存在 ,我会使用$(if $(wildcard $1)). 但将是另一个功能。
$(if $(wildcard $1))
还可以扩展解决方案,以便仅在调用某个目标时才需要变量。
$(call check_defined, ...)
只需将支票移入配方: ****
foo : @:$(call check_defined, BAR, baz value)
前导@符号关闭命令回显,并且:是实际命令,即 shell no-op stub。
@
:
该check_defined功能可以改进为还输出目标名称(通过$@变量提供):
check_defined
$@
check_defined = \ $(strip $(foreach 1,$1, \ $(call __check_defined,$1,$(strip $(value 2))))) __check_defined = \ $(if $(value $1),, \ $(error Undefined $1$(if $2, ($2))$(if $(value @), \ required by target `$@')))
因此,现在失败的检查会产生格式良好的输出:
Makefile:7: *** Undefined BAR (baz value) required by target `foo'. Stop.
check-defined-MY_FLAG
我个人会使用上面简单直接的解决方案。但是,例如,此答案建议使用特殊目标来执行实际检查。可以尝试将其概括并将目标定义为隐式模式规则:
# Check that a variable specified through the stem is defined and has # a non-empty value, die with an error otherwise. # # %: The name of the variable to test. # check-defined-% : __check_defined_FORCE @:$(call check_defined, $*, target-specific) # Since pattern rules can't be listed as prerequisites of .PHONY, # we use the old-school and hackish FORCE workaround. # You could go without this, but otherwise a check can be missed # in case a file named like `check-defined-...` exists in the root # directory, e.g. left by an accidental `make -t` invocation. .PHONY : __check_defined_FORCE __check_defined_FORCE :
用法: ****
foo :|check-defined-BAR
请注意,check-defined- BAR被列为仅订单( |...) 先决条件。
check-defined- BAR
|...
优点:
缺点:
make -t
check-defined-...
.PHONY
eval我相信,可以使用一些魔法和二次扩展技巧来克服这些限制,尽管我不确定这是否值得。
eval