如果variables未设置,则中止makefile
我怎么能放弃基于makefile的variables不被设置/赋值的make / makefile执行?
我想出了这个,但只有当调用者没有明确地运行一个目标(即只运行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的手册中没有find任何东西:
ifndef MY_FLAG .ABORT endif
使用error
function :
ifndef MY_FLAG $(error MY_FLAG is not set) endif
请注意,行不能缩进。 更确切地说,没有标签必须在这些行之前。
通用解决scheme
如果你要testing许多variables,那么值得定义一个辅助函数:
# 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.
目标特定的检查
也可以扩展解决scheme,以便只有在调用某个目标时才需要variables。
$(call check_defined, ...)
从配方里面
只需将支票移入配方:
foo : @:$(call check_defined, BAR, baz value)
前导的@
符号closures命令回显,而:
是实际的命令,一个shell 无操作存根 。
显示目标名称
可以改进check_defined
函数以输出目标名称(通过$@
variables提供):
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
特殊目标
就我个人而言,我会使用上面的简单和直接的解决scheme。 但是,例如, 这个答案build议使用一个特殊的目标来执行实际的检查。 人们可以尝试将其推广并将目标定义为隐式模式规则:
# 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, eg left by an accidental `make -t` invocation. .PHONY : __check_defined_FORCE __check_defined_FORCE :
用法:
foo :|check-defined-BAR
请注意, check-defined-BAR
被列为仅限订单 ( |...
)的先决条件。
优点:
- (可以说)是一个更干净的语法
缺点:
- 不能指定自定义错误消息
- 运行
make -t
(参见“执行配方”而不是“执行” )将会用很多check-defined-...
文件来污染你的根目录。 这是一个可悲的缺点,即模式规则不能声明.PHONY
。
我相信,这些限制可以使用一些eval
魔术和二次扩展黑客来克服,尽pipe我不确定这是否值得。
使用shell函数test
:
foo: test $(something)
用法:
$ make foo test Makefile:2: recipe for target 'foo' failed make: *** [foo] Error 1 $ make foo something=x test x