3.5 Target- and Pattern-Specific Variables
Variables usually have only one value during the execution of a makefile . This is ensured by the two-phase nature of makefile processing. In phase one, the makefile is read, variables are assigned and expanded, and the dependency graph is built. In phase two, the dependency graph is analyzed and traversed. So when command scripts are being executed, all variable processing has already completed. But suppose we wanted to redefine a variable for just a single rule or pattern.
In this example, the particular file we are compiling needs an extra command-line option, -DUSE_NEW_MALLOC=1 , that should not be provided to other compiles:
gui.o: gui.h $(COMPILE.c) -DUSE_NEW_MALLOC=1 $(OUTPUT_OPTION) $<
Here, we've solved the problem by duplicating the compilation command script and adding the new required option. This approach is unsatisfactory in several respects. First, we are duplicating code. If the rule ever changes or if we choose to replace the built-in rule with a custom pattern rule, this code would need to be updated and we might forget. Second, if many files require special treatment, the task of pasting in this code will quickly become very tedious and error-prone (imagine a hundred files like this).
To address this issue and others, make provides target-specific variables . These are variable definitions attached to a target that are valid only during the processing of that target and any of its prerequisites. We can rewrite our previous example using this feature like this:
gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1 gui.o: gui.h $(COMPILE.c) $(OUTPUT_OPTION) $<
The variable CPPFLAGS is built in to the default C compilation rule and is meant to contain options for the C preprocessor. By using the += form of assignment, we append our new option to any existing value already present. Now the compile command script can be removed entirely:
gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1 gui.o: gui.h
While the gui.o target is being processed , the value of CPPFLAGS will contain -DUSE_NEW_MALLOC=1 in addition to its original contents. When the gui.o target is finished, CPPFLAGS will revert to its original value.
The general syntax for target-specific variables is:
target ...: variable = value target ...: variable := value target ...: variable += value target ...: variable ?= value
As you can see, all the various forms of assignment are valid for a target-specific variable. The variable does not need to exist before the assignment.
Furthermore, the variable assignment is not actually performed until the processing of the target begins. So the righthand side of the assignment can itself be a value set in another target-specific variable. The variable is valid during the processing of all prerequisites as well.