For variable assignment in Make, I see := and = operator. What's the difference between them?
5 Answers
This is described in the GNU Make documentation, in the section titled 6.2 The Two Flavors of Variables .
In short, variables defined with :=
are expanded once, but variables defined with =
are expanded whenever they are used.
Simple assignment :=
A simple assignment expression is evaluated only once, at the very first occurrence.
For example, if CC :=${GCC} ${FLAGS}
during the first encounter is evaluated to gcc -W
then
each time ${CC}
occurs it will be replaced with gcc -W
.
Recursive assignment =
A Recursive assignment expression is evaluated everytime the variable is encountered
in the code. For example, a statement like CC = ${GCC} {FLAGS}
will be evaluated only when
an action like ${CC} file.c
is executed. However, if the variable GCC
is reassigned i.e
GCC=c++
then the ${CC}
will be converted to c++ -W
after the reassignment.
Conditional assignment ?=
Conditional assignment assigns a value to a variable only if it does not have a value
Appending +=
Assume that CC = gcc
then the appending operator is used like CC += -w
then CC
now has the value gcc -W
For more check out these tutorials
From http://www.gnu.org/software/make/manual/make.html#Flavors:
=
defines a recursively-expanded variable. :=
defines a simply-expanded variable.
For me, the best way to see it in practice is during this Makefile snippet:
Simple assignment
XX := $(shell date) // date will be executed once
tt:
@echo $(XX)
$(shell sleep 2)
@echo $(XX)
Running
make tt
Will produce:
sex 22 jan 2021 14:56:08 -03
sex 22 jan 2021 14:56:08 -03
( Same value )
Expanded assignment
XX = $(shell date) // date will be executed every time you use XX
tt:
@echo $(XX)
$(shell sleep 2)
@echo $(XX)
Running
make tt
Will produce:
sex 22 jan 2021 14:56:08 -03
sex 22 jan 2021 14:56:10 -03
Different values
This is an old question but this example helps me understand the difference whenever I forget.
Running make
with the following Makefile will instantly exit:
a = $(shell sleep 3)
Running make
with the following Makefile will sleep for 3 seconds, and then exit:
a := $(shell sleep 3)
In the former Makefile, a
is not evaluated until it's used elsewhere in the Makefile, while in the latter a
is evaluated immediately even though it's not used.