Make
Overview
A makefile, typically named Makefile, is used to describe tasks where some files must be updated automatically from others whenever the others change. The make program reads in makefiles and executes these updates. It works in two distinct phases:
- Read-In: Build a dependency graph of the targets and prerequisites, internalizing any variables/values along the way.
- Target-Update: Determine which targets need to be updated and runs the appropriate recipes.
An immediate expansion is one that happens in the first phase. An expansion is deferred if it happens once the expansion is used. This may be in either phase.
Rules
A makefile consists of a number of rules with the following basic structure:
targets : prerequisites [; recipe]
recipe
...
A target is usually the name of a file that is generated by a program. It may also be the name of an action to carry out. A prerequisite is a file used as input to create a target. A recipe is an action that make carries out. Usually it is used to read in the prequisites and produce the target.
Targets
When an explicit rule has multiple targets, they can be treated in one of two possible ways: as independent targets or as grouped targets.
If the standard target separator : is used, each target is independent. This is equivalent to writing the same rule once for each target, with duplicated prerequisites and recipes. If the grouped target separator &: is used, its understood the recipe generates all the target files with a single invocation.
Goals
A goal is a target that make strives to update. The default goal is the first target of the first rule in the first makefile, with two exceptions:
- A target starting with a period is not a default unless it contains at least one forward slash (
/). - A target that defines a pattern rule has no effect on the default goal.
The default goal is the goal make updates when no target is specified in the command line.
Phony Targets
A phony target is a target that does not refer to a file. That is, it only specifies an action of some sort. To ensure that such a target runs its recipe unconditionally, regardless of whether a file with the target name exists, it can be specified as the prerequisite of special target .PHONY.
.PHONY: clean
clean:
rm -r *.o
Force Targets
If a rule has no prerequisites or recipe, and the target of the rule is a nonexistent file, then make treats this force target as updated whenever its rule is run. This mean rules that depend on a force target will always have their recipe run:
clean: FORCE
rm -r *.o
FORCE:
Generally speaking, .PHONY has superseded the use of force targets. Force targets remain useful though when wanting to rebuild a pattern rule.
.SILENT
Recipes corresponding to prerequisites for the .SILENT target will not be printed on execution. If .SILENT has no prerequisites, make does not print any recipes before executing them.
.IGNORE
Recipes corresponding to prerequisites for the .IGNORE target will not abort make on errors (i.e. nonzero status codes). If .IGNORE has no prerequisites, make ignores errors in execution of recipes for all files.
.INTERMEDIATE
The targets which .INTERMEDIATE depends on are treated as intermediate files. Such files are automatically removed once they are no longer needed.
You can force a file to not be considered an intermediate by listing it as a prerequisite of the .NOTINTERMEDIATE target.
Prerequisites
There are two types of prerequisites: normal prerequisites and order-only prerequisites. An order-only prerequisite is built before a target, but a newer order-only prerequisite does not force the target to be updated. Normal and order-only prerequisites are separated via a pipe symbol (|) in the prerequisites list:
targets: normal-prerequisites | order-only prerequisites
Static Pattern Rules
Static pattern rules are rules which specify multiple targets and construct the prerequisite names for each target based on the target name.
targets ... : target-pattern : prereq-patterns ...
recipe
Recipes
By default, the /bin/sh shell is used to execute each line of a recipe. To run multiple lines within a single shell, one can connect the lines using a \ and newline. Unlike elsewhere in a Makefile, the \ is not replaced. Recipe prefix characters (by default, the \t character) are removed though.
To suppress echoing of specific lines in a recipe, prefix the line with the @ symbol. The @ is discarded before the line is passed to the shell.
To ignore errors in a recipe line (e.g. a command that returns a nonzero status), prefix the line with the - symbol. The - is discarded before the line is passed to the shell.
Implicit
An implicit rule is a rule provided by make that does not need to be specified explicitly in the Makefile. File names determine which implicit rules are run. For example, the implicit rule for C compilation is used when a .o file is made the prerequisite of a .c file.
When an implicit prerequisite is the result of another implicit rule, we say chaining is occurring. Files created in a chain are called intermediates. Make automatically deletes them when they are no longer needed.
Pattern Rules
A new implicit rule can be defined by writing a pattern rule.
target-pattern : prereq-patterns ...
recipe
Variables
A variable is a name used to represent a string of text, called the variable's value. A variable foo is substituted within a rule by specifying either $(foo) or ${foo}. A single letter variable name may omit the parenthesis or curly braces.
Recursively Expanded
A variable defined with a = operator is recursively expanded. On substitution, the variable's value is replaced verbatim and then further expanded if the value also contains other variable references.
immediate = deferred
Simply Expanded
A variable defined with a := operator is simply expanded. The value of a simply expanded variable is scanned once, with references to variables and functions expanded at time of definition. Once the expansion is complete, the value of the variable is never expanded again.
immediate := immediate
Conditionally Assigned
A variable defined with a ?= operator is conditionally assigned. The assignment only has an effect if the variable in question is not yet defined.
immediate ?= deferred
Automatic Variables
There exists a number of automatic variables computed afresh for each rule executed, based on the target and prerequisites of the rule. Some commonly used ones are:
$@- The filename of a rule's target.
- In a pattern rule with multiple targets, it expands to the target that caused the rule's recipe to be run.
$<- The name of the first prerequisite.
$^- The names of all normal prerequisites, without duplication and with spaces between them.
$+- The names of all normal prerequisites, with duplication and with spaces between them.
$|- The names of all order-only prerequisites, with spaces between them.
$*- The stem used in implicit or static pattern rules.
Target-Specific
Using target-specific variable values, make can define different values for a variable based on the target it is currently building. This follows the pattern:
target ... : variable-assignment
Target-specific variable values are also in effect recursively for all prerequisites of the target.
Pattern-Specific
Using pattern-specific variable values, make can define different values for a variable based on the target it is currently building. This follows the pattern:
pattern ... : variable-assignment
where pattern refers to a %-pattern. If a target matches more than one pattern, the matching pattern-specific variables with longer stems are interpreted first.
Priority
Environment variables that make sees when it starts up are transformed into a make variable with the same name and value. Such variables have the lowest priority.
Ordinary assignment of variables found in a makefile have higher priority than environment variables.
Command arguments, i.e. assignments supplied as an argument to the make command, have higher priority than ordinary assignments. They allow the user to update the makefile without having to edit it.
Variables marked #override have the highest priority.
Directives
A directive is an instruction for make to do something special.
define
The define directive is used to define multi-line variables. If an operator is not included after the variable name, the = operator is assumed.
define <variable-name> [=|:=|?=|+=]
...
endef
override
Variable assignments marked with the override directive have a higher priority than all other assignments (except another override). Subsequent assignments or appends to a variable marked with override are ignored.