I\'d like to use $(error ...)
to abort my make process if certain preconditions aren\'t met. The fails_to_work
target should abort when failing t
You're trying to get the shell stuff in a recipe to conditionally invoke makefile stuff, which doesn't work, as you've found.
I can think of two options:
Simply remove the $(error)
stuff. If test
fails, then it will return a non-zero exit status, and the Make process will terminate at that point.
Take the test out of the rule, and use a Make conditional (which in turn invokes shell functionality), e.g.:
ifeq ($(shell test -d /foobar; echo $$?),1)
$(error Not a directory)
endif
Shell commands for a make recipe are effectively stored as a single recursively expanded variable. At the point make decides to run the recipe, it expands the variable, and then runs each line in its own shell invocation. Any $(error ...)
that gets expanded will cause make to abort even before invoking the first command.
Note though that the untaken branch of a $(if ...)
or $(or ...)
&c. will not be expanded. Thus, you could do
.PHONY: rule-with-assert
rule-with-assert:
$(if $(realpath ${should-be-file}/),$(error Assertion failure: ${should-be-file} is a folder!))
⋮
Note that trailing /
in the realpath
.
Of course macros help to tidy this up a lot.
assert-is-file = $(if $(realpath $1/),$(error Assertion failure: [$1] is a folder!))
.PHONY: rule-with-assert
rule-with-assert:
$(call assert-is-file,${should-be-file})
⋮
It's worth noting again that it doesn't matter where you put the $(call assert-is-file,…)
in the recipe.
Any $(error)
will be generated as the recipe is expanded,
before any shell commands are run.