Reputation: 6055
I want to check that an environment variable is set before executing some code in a Makefile. If it's not set I want to throw an error with a simple error message:
run:
[ -z "$(MY_APP)" ] && echo "MY_APP must be set" && exit 1
echo "MY_APP is set. Yay!"
echo "Let's continue on with the command..."
When MY_APP
is not set I get the following error, which is desired:
[ -z "" ] && echo "MY_APP must be set" && exit 1
MY_APP must be set
make: *** [run] Error 1
However, when MY_APP
is set I get the following error:
[ -z "EXAMPLE_NAME" ] && echo "MY_APP must be set" && exit 1
make: *** [run] Error 1
Any idea what I'm doing wrong? And is there a better way to do this?
Upvotes: 13
Views: 16610
Reputation: 1389
IF you want to exit the make file without Makefile error code, refer to this answer:
https://stackoverflow.com/a/78390951/10669066
Upvotes: 0
Reputation: 14491
Recall that the &&
condition require that all conditions must be TRUE to pass. Since the first condition fail, the whole command will return a status of 1
(-> false), effectively stopping the make
You can use the following, so that the test will fail only when MY_APP
is missing.
Note that I'm using false
instead of exit 1
. Also better to use "${MY_APP}"
, which make it easier to copy/paste from Make to shell prompt/script.
run:
{ [ -z "$(MY_APP)" ] && echo "MY_APP must be set" && false } || true
...
# Or just if-Then-Else
if [ -z "${MY_APP}" ] ; then echo "MY_APP must be set" ; false ; fi
...
Upvotes: 8
Reputation: 2441
You can conditionally exit the Makefile using error
control function, at least in the GNU version.
This snippet is a helpful condition to put into the head of the Makefile. It exits with a message of help, if make
was not called from within the directory of the Makefile.
MAKEFILE_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
ifneq (${MAKEFILE_DIR}, $(shell pwd))
INVALID_LOCATION:=`make` must be called from within ${MAKEFILE_DIR} (or with option -C ${MAKEFILE_DIR})
$(error ERROR: $(INVALID_LOCATION))
endif
See: https://www.gnu.org/software/make/manual/html_node/Make-Control-Functions.html
Useful in case your paths are relative to the Makefile and you don't want them to prefix with a base.
Upvotes: 1
Reputation: 1420
You can test environment variables with Makefile conditional syntax, like this:
sometarget:
ifndef MY_APP
@echo "MY_APP environment variable missing"
exit 1
endif
somecommand to_run_if_my_app_is_set
Note that ifndef
/ifdef
operate on the name of the variable, not the variable itself.
Upvotes: 4
Reputation: 27073
It seems that you are trying to use a Makefile to run commands which are not building targets (the target name run
is a giveaway). You already got bitten by one of Makefile and shells caveats. Makefile caveat: exit status is inspected after each line and if not zero abort immediately. Shell caveat: the test
command ([
) returns a non zero exit status so the entire line returns non zero.
The rule of thumb is: a recipe of a rule should create a filename named like the target of the rule.
Here is a rule (to clarify the terms):
target:
recipe command lines
should create file named target
There are some exceptions to this rule of thumb. Most notably make clean
and make install
. Both typically do not create files named clean
or install
. One can argue that make run
maybe also be an exception to this rule of thumb.
If your run
is as simple as a typical clean
then I might agree about making an exception. But usually commands are run with command line arguments. Before long you will want make run
accept arguments. And making make accept custom command line arguments is not fun at all.
You tried to manipulate the behaviour using environment variables which is somewhat less problematic than command line arguments. But still problematic enough to make you trip over a caveat.
My suggestion for a fix:
run
target write a wrapper shell script around the makefile which lets the makefile rebuild the target and then run the target. For exampe as explained here: Passing arguments to "make run"Upvotes: 0