Cancel makefile if variable is not set

How can I abort make / makefile based on a makefile variable not set / meaning?

I came up with this, but it only works if the caller does not explicitly launch the target (i.e. only make works).

 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) 

I think something like this would be a good idea, but found nothing in the manual:

 ifndef MY_FLAG .ABORT endif 
+73
makefile
Jun 01 2018-12-12T00:
source share
2 answers

Use the error function:

 ifndef MY_FLAG $(error MY_FLAG is not set) endif 

Note that lines should not be indented. More precisely, no tabs should precede these lines.

Common decision

If you are going to test many variables, you should define a helper function for this:

 # 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)))) 

And here is how to use it:

 $(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) 


This will result in an error:

 Makefile:17: *** Undefined OUT_DIR (build directory). Stop. 

Verification for specific objects

You can also expand the solution so that you can require a variable only if a specific target is called.

$(call check_defined, ...) from inside the recipe

Just move the check to the recipe:

 foo : @:$(call check_defined, BAR, baz value) 

The leading @ sign disables the echo command, and : - a valid command, no-op stub shell.

Target Name Display

The check_defined function can be improved to display the target name (provided via the $@ variable):

 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 `$@'))) 

So, now a failed check produces a well-formatted output:

 Makefile:7: *** Undefined BAR (baz value) required by target `foo'. Stop. 

check-defined-MY_FLAG special purpose

Personally, I would use the simple and direct solution above. However, for example, this answer suggests using a special purpose to perform the actual check. You can try to generalize this and define the goal as a rule of the implicit template:

 # 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 : 

Using:

 foo :|check-defined-BAR 

Please note that the check-defined-BAR is specified as an order only ( |... ).

Pros:

  • (possibly) cleaner syntax

Minuses:

  • Unable to specify custom error message
  • Running make -t (see Instead of executing recipes ) will contaminate your root directory with a large number of check-defined-... files. This is a sad flaw that template rules cannot be declared .PHONY .

I believe that these limitations can be overcome using eval magic and a secondary extension , although I'm not sure if it's worth it.

+131
Jun 01. 2018-12-12T00:
source share

Use the test shell function:

 foo: test $(something) 

Using:

 $ make foo test Makefile:2: recipe for target 'foo' failed make: *** [foo] Error 1 $ make foo something=x test x 
+6
Jan 18 '17 at 14:35
source share