Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
–
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
–
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.
–
–
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
@echo $(XX)
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
@echo $(XX)
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.
Recursive assignment =
is evaluated everytime it is used, but not in the order of when it is encountered among the recipe commands, but rather before running any recipe command.
Based on the following example:
default: target1 target2
target1 target2:
@echo "Running at: `gdate +%s.%N`"
@echo "Simple assignment: $(SIMPLE_ASSIGNMENT)"
@echo "Recursive assignment: $(RECURSIVE_ASSIGNMENT)"
sleep 1
@echo "Running at: `gdate +%s.%N`"
@echo "Simple assignment: $(SIMPLE_ASSIGNMENT)"
@echo "Recursive assignment: $(RECURSIVE_ASSIGNMENT)"
@echo
SIMPLE_ASSIGNMENT := $(shell gdate +%s.%N)
RECURSIVE_ASSIGNMENT = $(shell gdate +%s.%N)
Outputs:
❯ make
Running at: 1645056840.980488000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056840.958590000
sleep 1
Running at: 1645056842.008998000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056840.969616000
Running at: 1645056842.047367000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056842.027600000
sleep 1
Running at: 1645056843.076696000
Simple assignment: 1645056840.949181000
Recursive assignment: 1645056842.035901000
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.