Can anybody give a clear explanation of how variable assignment really works in Makefiles.
What is the difference between :
VARIABLE = value
VARIABLE ?= value
VARIABLE := value
VARIABLE += value
I have read the section in GNU Make's manual, but it still doesn't make sense to me.
In the above answers, it is important to understand what is meant by "values are expanded at declaration/use time". Giving a value like
*.c
does not entail any expansion. It is only when this string is used by a command that it will maybe trigger some globbing. Similarly, a value like$(wildcard *.c)
or$(shell ls *.c)
does not entail any expansion and is completely evaluated at definition time even if we used:=
in the variable definition.Try the following Makefile in directory where you have some C files:
Running
make
will trigger a rule that creates an extra (empty) C file, calledfoo.c
but none of the 6 variables hasfoo.c
in its value.When you use
VARIABLE = value
, ifvalue
is actually a reference to another variable, then the value is only determined whenVARIABLE
is used. This is best illustrated with an example:When you use
VARIABLE := value
, you get the value ofvalue
as it is now. For example:Using
VARIABLE ?= val
means that you only set the value ofVARIABLE
ifVARIABLE
is not set already. If it's not set already, the setting of the value is deferred untilVARIABLE
is used (as in example 1).VARIABLE += value
just appendsvalue
toVARIABLE
. The actual value ofvalue
is determined as it was when it was initially set, using either=
or:=
.Lazy Set
Normal setting of a variable - values within it are recursively expanded when the variable is used, not when it's declared
Immediate Set
Setting of a variable with simple expansion of the values inside - values within it are expanded at declaration time.
Set If Absent
Setting of a variable only if it doesn't have a value
Append
Appending the supplied value to the existing value (or setting to that value if the variable didn't exist)
I suggest you do some experiments using "make". Here is a simple demo, showing the difference between
=
and:=
.make test
prints:Check more elaborate explanation here
Using
=
causes the variable to be assigned a value. If the variable already had a value, it is replaced. This value will be expanded when it is used. For example:Using
:=
is similar to using=
. However, instead of the value being expanded when it is used, it is expanded during the assignment. For example:Using
?=
assigns the variable a value iff the variable was not previously assigned. If the variable was previously assigned a blank value (VAR=
), it is still considered set I think. Otherwise, functions exactly like=
.Using
+=
is like using=
, but instead of replacing the value, the value is appended to the current one, with a space in between. If the variable was previously set with:=
, it is expanded I think. The resulting value is expanded when it is used I think. For example:If something like
HELLO_WORLD = $(HELLO_WORLD) world!
were used, recursion would result, which would most likely end the execution of your Makefile. IfA := $(A) $(B)
were used, the result would not be the exact same as using+=
becauseB
is expanded with:=
whereas+=
would not causeB
to be expanded.