The most upvoted answer can be improved.
Let me refer to GNU Make manual "Setting variables" and "Flavors", and add some comments.
Recursively expanded variables
The value you specify is installed verbatim; if it contains references to other variables, these references are expanded whenever this variable is substituted (in the course of expanding some other string). When this happens, it is called recursive expansion.
foo = $(bar)
The catch: foo
will be expanded to the value of $(bar)
each time foo
is evaluated, possibly resulting in different values. Surely you cannot call it "lazy"! This can surprise you if executed on midnight:
# This variable is haunted!
WHEN = $(shell date -I)
something:
touch $(WHEN).flag
# If this is executed on 00:00:00:000, $(WHEN) will have a different value!
something-else-later: something
test -f $(WHEN).flag || echo "Boo!"
Simply expanded variable
VARIABLE := value
VARIABLE ::= value
Variables defined with ‘:=’ or ‘::=’ are simply expanded variables.
Simply expanded variables are defined by lines using ‘:=’ or ‘::=’ [...]. Both forms are equivalent in GNU make; however only the ‘::=’ form is described by the POSIX standard [...] 2012.
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.
Not much to add. It's evaluated immediately, including recursive expansion of, well, recursively expanded variables.
The catch: If VARIABLE
refers to ANOTHER_VARIABLE
:
VARIABLE := $(ANOTHER_VARIABLE)-yohoho
and ANOTHER_VARIABLE
is not defined before this assignment, ANOTHER_VARIABLE
will expand to an empty value.
Assign if not set
FOO ?= bar
is equivalent to
ifeq ($(origin FOO), undefined)
FOO = bar
endif
where $(origin FOO)
equals to undefined
only if the variable was not set at all.
The catch: if FOO
was set to an empty string, either in makefiles, shell environment, or command line overrides, it will not be assigned bar
.
Appending
VAR += bar
Appending:
When the variable in question has not been defined before, ‘+=’ acts just like normal ‘=’: it defines a recursively-expanded variable. However, when there is a previous definition, exactly what ‘+=’ does depends on what flavor of variable you defined originally.
So, this will print foo bar
:
VAR = foo
# ... a mile of code
VAR += $(BAR)
BAR = bar
$(info $(VAR))
but this will print foo
:
VAR := foo
# ... a mile of code
VAR += $(BAR)
BAR = bar
$(info $(VAR))
The catch is that +=
behaves differently depending on what type of variable VAR
was assigned before.
Multiline values
The syntax to assign multiline value to a variable is:
define VAR_NAME :=
line
line
endef
or
define VAR_NAME =
line
line
endef
Assignment operator can be omitted, then it creates a recursively-expanded variable.
define VAR_NAME
line
line
endef
The last newline before endef
is removed.
Bonus: the shell assignment operator ‘!=’
HASH != printf '\043'
is the same as
HASH := $(shell printf '\043')
Don't use it. $(shell)
call is more readable, and the usage of both in a makefiles is highly discouraged. At least, $(shell)
follows Joel's advice and makes wrong code look obviously wrong.