Reputation: 137
I have this makefile:
echo:
echo "PASS=$(PASS)"
Which I invoke:
PASS='MYPA$$' make
Which shows me:
echo "PASS=MYPA$"
PASS=MYPA$
Somebody is evaluating $$
-> $
.
Is this the shell? Not when inputting the value, since I use single-quotes, preventing the shell to evaluate it.
Maybe the shell invoked by make is doing this ...
Or is it maybe make
itself?
How can I avoid it?
Upvotes: 4
Views: 1548
Reputation: 18697
make
variablesIt's better to think of make
variables as macros, than as conventional variables (actually in some versions of make
, variables are called macros). The reason is, each time a variable is referenced, it is expanded.
An example from the docs illustrates the standard recursively expanded variables behaviour:
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:
echo $(foo)
# echoes: Huh?
# `$(foo)' expands to `$(bar)' which expands to `$(ugh)' which finally expands to `Huh?'
If you are using GNU make
, one way to avoid further expansion is by using the simply expanded variables:
Simply expanded variables are defined by lines using
:=
(see section Setting Variables). The value of a simply expanded variable is scanned once and for all, expanding any references to other variables and functions, when the variable is defined. The actual value of the simply expanded variable is the result of expanding the text that you write. It does not contain any references to other variables; it contains their values as of the time this variable was defined.
Although simply expanded variables behave more like variables in most programming languages, their sole usage wouldn't solve the problem of environment variables' expansion here because even the first reference var := $(PASS)
would expand $$
from the PASS
environment variable.
We can use the shell
function in make
to read our environment variable in shell (and not expand it in make
):
expanded := $(shell echo "$$PASS")
test:
echo 'PASS=$(expanded)'
echo "PASS=$$PASS"
The shell
function will execute echo "$PASS"
in shell ($$
is expanded to $
by make
when function is executed), and the result (the value of your shell variable PASS
) will be stored in the make
variable expanded
. This variable can now be freely used elsewhere in make
, without ever being further expanded.
The only processing make
does on the result, before substituting it into the surrounding text, is to convert each newline or carriage-return / newline pair to a single space. It also removes the trailing (carriage-return and) newline, if it's the last thing in the result.
The example above illustrates how to use the make
variable expanded
and the environment variable PASS
in your Makefile
script:
$ PASS='MYPA$$' make
echo 'PASS=MYPA$$'
PASS=MYPA$$
echo "PASS=$PASS"
PASS=MYPA$$
Upvotes: 7