What is the difference between the GNU Makefile variable assignments =, ?=, = and +=?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
GNU Make is a powerful tool used for controlling the generation of executables and other non-source files in a program from the program's source files. Make uses what are called Makefiles, which specify how to derive the target program. Among the various components of Makefiles, variable assignments play a crucial role. In GNU Make, there are several types of variable assignments, each with different behaviors: =, ?=, :=, and +=. Understanding the difference between these assignment operators is key to mastering Makefile syntax and behavior.
The = Operator: Recursive Expansion
The = operator is used for recursively expanded variables in Make. When you assign a value to a variable using =, the value is not evaluated at the moment of assignment but is expanded whenever the variable is used. This means that variables and functions within the value are not expanded until the variable is actually used in a target or prerequisite list.
In the above example, FOO is defined as $(BAR) which does not get expanded until FOO is echoed.
The ?= Operator: Conditional Variable Assignment
The ?= operator is used to assign a value to a variable only if that variable is not already defined. If the variable has a previous value, the assignment using ?= is ignored.
Here, BAR retains its first assigned value "bar-value" because the second assignment is ignored, given that BAR is already set.
The := Operator: Immediate Expansion
The := operator stands for simple or immediate expansion. The variables or functions in the right-hand side are expanded at the point of assignment, unlike recursive expansion where expansion is deferred until use.
This differs from the = operator where the expansion of Y would happen at echo time.
The += Operator: Appending Values
The += operator allows you to append additional data onto previous variable definitions, effectively simplifying the process of building up the content of a variable incrementally.
It stands out as particularly useful when constructing lists of items iteratively.
Summary Table
| Operator | Description | Expansion Type | Example | Result |
= | Standard assignment | Recursive | FOO = $(BAR), BAR = bar-value echo $(FOO) | bar-value |
?= | Conditional assignment | Recursive | FOO ?= foo, FOO ?= bar
echo $(FOO) | foo |
:= | Immediate assignment | Immediate | BAR = bar, FOO := $(BAR) BAR = new-bar, echo $(FOO) | bar |
+= | Append to variable | Depends on initial type | FOO = foo, FOO += bar
echo $(FOO) | foo bar |
Additional Details
When using these operators, it's important to understand the scope and lifecycle of make variables (i.e., target-specific variables versus globally defined). This ensures that variables behave as expected when used across different contexts within the Makefile.
Correct use of variable assignment operators can optimize Makefile processing time and overall system performance by avoiding unnecessary computation or recalculation of values.
In summary, the GNU Make variable assignment operators =, ?=, :=, and += each serve unique purposes that, when utilized effectively, can allow for more precise and efficient Makefile configurations. Understanding the differences between them facilitates more robust control over the build process and can be crucial in complex build environments.

