如果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 

使用errorfunction :

 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