You may like an approach I came up with some time ago.
In my include
d file that’s common among my Makefile
s:
# Ensure the macro named is set to a non-empty value.
varchk_call = $(if $($(1)),,$(error $(1) is not set from calling environment))
# Ensure all the macros named in the list are set to a non-empty value.
varchklist_call = $(foreach v,$(1),$(call varchk_call,$v))
At the top of a Makefile
that I want to ensure certain variables are set before it runs:
$(call varchklist_call,\
INSTDIR \
PACKAGE \
RELEASE \
VERSION)
I usually do these checks in sub-Makefiles to ensure someone didn’t break the top level Makefile by not passing down a required macro.
To solve your DRY problem, you may not realize that you can generate target rules from built-in functions
eval
andforeach
and a user-defined new-line macro. Think of it like a preprocessor step.For example:
# This defines a new-line macro. It must have two blank lines. define nl endef # Generate two rules for ansible playbooks: $(eval $(foreach v,1 2,\ .PHONY : ansible.run-playbook$v $(nl)\ \ ansible.run-playbook$v : ensure-variables cleanup-residue | $$(ansible.venv)$(nl)\ ansible.run-playbook$v :;\ ... $(nl)\ ))
I winged it a bit for you, but hopefully I got it right, or at least right enough you get what I’m doing with this technique.