I came across some odd behavior when using Make recently (v3.81).
Suppose I have the following Makefile:
FOOBAR = $(shell find nonexistentdirectory -iname "foobar" | tr '\n' ' ')
all:
@echo "Hi"
clean:
@echo "Hi again"
Seems straightforward enough, right? Notably, FOOBAR
is a "recursively-expanded variable", so it should not be evaluated until I refer to it. Note that I never refer to it. Also note that nonexistentdirectory
does not exist as you might expect.
Now suppose I set FOOBAR
in the shell before I invoke a Make target:
compy386$ FOOBAR="stuff" make clean
find: nonexistentdirectory: No such file or directory
Hi again
Why is FOOBAR
being evaluated? Clearly it has something to do with the fact that the variable is defined in the shell. Am I supposed to anticipate that a user might have set variables in their shell? What am I doing wrong here?!
However, setting some environment variables makes some things easier. PATH If the jre/bin folder is on the path, you don't have to qualify to run the java command. If the jdk/bin folder is on the path, you don't have to qualify to run the java and javac commands. As well as some other commands provided by Java.
The hidden danger of using environment variables for secrets management is that the architectural solution could allow users to unwillingly cross security boundaries even with only a single piece of information leaked.
Check if variable is defined in a Makefilecheck_defined = \ $(strip $(foreach 1,$1, \ $(call __check_defined,$1,$(strip $(value 2))))) __check_defined = \ $(if $(value $1),, \ $(error Undefined $1$(if $2, ($2)))) install: $(call check_defined, var1) $(call check_defined, var2) # do stuff here..
FOOBAR
is being evaluated because you are running a recipe (for clean
) and FOOBAR
existed in the environment on entry to make
. Because FOOBAR
existed in the environment on entry, it becomes an exported variable, which means that make
will provide it as part of the environment to any program in the recipe. make
doesn't special-case echo
; it just uses the one found in your path. And it can't know whether or not that utility will reference a particular environment variable, so it has to export all exported variables, which means it has to evaluate FOOBAR
.
(For the official word, see the third paragraph of Variables from the Environment in the make manual. Also see the recipe on recursive make invocation.)
To answer the direct question, you can tell make
to ignore the fact that a variable came from the environment, so that it doesn't re-export it, by unexporting it:
unexport FOOBAR
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With