Chapter 20. Using make to Build C Programs

As you saw in Chapter 18, the commands involved in compiling and linking C programs can be numerous and complex. The make utility automates and manages the process of compiling programs of any size and complexity, so that a single make command replaces hundreds of compiler and linker commands. Moreover, make compares the timestamps of related files to avoid having to repeat any previous work. And most importantly, make manages the individual rules that define how to build various targets, and automatically analyzes the dependency relationships between all the files involved.

There are a number of different versions of make, and their features and usage differ to varying degrees. They feature different sets of built-in variables and targets with special meanings. In this brief chapter, rather than trying to cover different varieties, we concentrate on GNU make, which is widely available. (On systems that use a different default make, GNU make is often available under the executable name gmake.) Furthermore, even as far as GNU make is concerned, this chapter sticks more or less to the basics: in this book, we want to use make only as a tool for building programs from C source code. If you want to go on to exploit the full capabilities of make, an inevitable step is to read the program’s documentation itself. For a well-structured course in using make’s advanced capabilities, see also Managing Projects with GNU make by Robert Mecklenburg (O’Reilly).

Targets, Prerequisites, and Commands

Before we describe the make solution, we will briefly review the problem. To make an executable program, we need to link compiled object files. To generate object files, we need to compile C source files. The source files in turn need to be preprocessed to include their header files. And whenever we have edited a source or header file, then any file that was directly or indirectly generated from it needs to be rebuilt.

The make utility organizes the work just described in the form of rules. For C programs, these rules generally take the following form: the executable file is a target that must be rebuilt whenever certain object files have changed—the object files are its prerequisites. At the same time, the object files are intermediate targets, which must be recompiled if the source and header files have changed. (Thus, the executable depends indirectly on the source files. make manages such dependency chains elegantly, even when they become complex.) The rule for each target generally contains one or more commands, called the command script, that make executes to build it. For example, the rule for building the executable file says to run the linker, while the rule for building object files says to run the preprocessor and compiler. In other words, a rule’s prerequisites say when to build the target, and the command script says how to build it.

The Makefile

The make program has a special syntax for its rules. Furthermore, the rules for all the operations that you want make to manage in your project generally need to be collected in a file for make to read. The command-line option -f filename tells make which file contains the rules you want it to apply. Usually, though, this option is omitted and make looks for a file with the default name makefile, or failing that, Makefile.1

When you read makefiles, remember that they are not simply scripts to be executed in sequential order. Rather, make first analyzes an entire makefile to build a dependency tree of possible targets and their prerequisites, then iterates through that dependency tree to build the desired targets.

In addition to rules, makefiles also contain comments, variable assignments, macro definitions, include directives, and conditional directives. These will be discussed in later sections of this chapter, after we have taken a closer look at the meat of the makefile: the rules.

Rules

Example 20-1 shows a makefile that might be used to build the program in Example 1-2.

Example 20-1. A basic makefile
# A basic makefile for "circle".
 
CC = gcc
CFLAGS = -Wall -g -std=c99
LDFLAGS = -lm
 
circle : circle.o circulararea.o
        $(CC) $(LDFLAGS) -o $@ $^
 
circle.o : circle.c
        $(CC) $(CFLAGS) -o $@ -c $<
 
circulararea.o: circulararea.c
        $(CC) $(CFLAGS) -o $@ -c $<

The line that begins with the character # is a comment, which make ignores. This makefile begins by defining some variables, which are used in the statements that follow. The rest of the file consists of rules, with the following general form:

target [target [...]] : [prerequisite[prerequisite[...]]]
        [command
        [command
        [...]]]

The first target must be placed at the beginning of the line, with no whitespace to the left of it. Moreover, each command line must start with a tab character. (It would be simpler if all whitespace characters were permissible here, but that’s not the case.)

Each rule in the makefile says, in effect: if any target is older than any prerequisite, execute the command script. More importantly, make also checks whether the prerequisites have other prerequisites in turn before it starts executing commands.

Both the prerequisites and the command script are optional. A rule with no command script tells only make about a dependency relationship; and a rule with no prerequisites tells only how to build the target, not when to build it. You can also put the prerequisites for a given target in one rule, and the command script in another. For any target requested, whether on the make command line or as a prerequisite for another target, make collects all the pertinent information from all rules for that target before it acts on them.

Example 20-1 shows two different notations for variable references in the command script. Variable names that consist of more than one character—in this case, CC, CFLAGS, and LDFLAGS—must be prefixed with a dollar sign and enclosed in parentheses when referenced. Variables that consist of just one character—in our example, these happen to be the automatic variables ^, <, and @—need just the dollar sign, not the parentheses. We discuss variables in detail in a separate section later in this chapter. The following program output shows how make expands both kinds of variables to generate compiler commands:

$ make -n -f Makefile19-1 circle
gcc -Wall -g -std=c99 -o circle.o -c circle.c
gcc -Wall -g -std=c99 -o circulararea.o -c circulararea.c
gcc -lm -o circle circle.o circulararea.o

The command-line option -n instructs make to print the commands it would otherwise execute to build the specified targets. This option is indispensable when testing makefiles. (A complete reference list of make options is included at the end of this chapter.) The final line of output corresponds to the first rule contained in Example 20-1. It shows that make expands the variable reference $(CC) to the text gcc and $(LDFLAGS) to -lm. The automatic variables $@ and $^ expand to the target circle and the prerequisite list circle.o circulararea.o. In the first two output lines, the automatic variable $< is expanded to just one prerequisite, which is the name of the C source file to be compiled.

The Command Script

The command script for a rule can consist of several lines, each of which must begin with a tab. Comments and blank lines are ignored, so that the command script ends with the next target line or variable definition.

Furthermore, the first line of the command script may be placed after a semicolon at the end of the dependency line, as in the following syntax:

target_list : [prerequisite_list] ; [command
        [command
        [...]]]

This variant is rarely used today, however.

The important thing to remember about the command part of a make rule is that it is not a shell script. When make invokes a rule to build its target, each line in the rule’s command section is executed individually in a separate shell instance. For that reason, you must make sure that no command depends on the side effects of a preceding line. For example, the following commands will not run etags in the src/ subdirectory:

TAGS:
        cd src/
        etags *.c

In trying to build TAGS, make runs the shell command cd src/ in the current directory. When that command exits, make runs etags *.c in a new shell, again in the current directory.

There are two ways to cause several commands to run in the same shell: putting them on one line, separated by a semicolon, or adding a semicolon and a backslash to place them virtually on one line:

TAGS:
	    cd src/ ; etags *.c ;\
	    cd .. ; ls src/TAGS

Another reason for running multiple commands in the same shell could be to speed up processing, especially in large projects.

Pattern Rules

The last two rules in Example 20-1 show a repetitive pattern. Each of the two object files, circle.o and circulararea.o, depends on a source file with the same name and the suffix .c, and the commands to build them are the same. make lets you describe such cases economically using pattern rules. Here is a single rule that replaces the last two rules in Example 20-1:

circulararea.o circle.o: %.o: %.c
        $(CC) $(CFLAGS) -o $@ -c $<

The first line of this rule has three colon-separated parts rather than two. The first part is a list of the targets that the rule applies to. The rest of the line, %.o: %.c, is a pattern explaining how to derive a prerequisite name from each of the targets, using the percent sign (%) as a wildcard. When make matches each target in the list against the pattern %.o, the part of the target that corresponds to the wildcard % is called the stem. The stem is then substituted for the percent sign in %.c to yield the prerequisite.

The general syntax of such pattern rules is:

[target_list :] target_pattern : prerequisite_pattern
        [command-script]

You must make sure that each target in the list matches the target pattern. Otherwise, make issues an error message.

If you include an explicit target list, the rule is a static pattern rule. If you omit the target list, the rule is called an implicit rule, and applies to any target whose name matches the target pattern. For example, if you expect to add more modules as the circle program grows and evolves, you can make a rule for all present and future object files in the project like this:

%.o: %.c
        $(CC) $(CFLAGS) -o $@ -c $<

And if a certain object needs to be handled differently for some reason, you can put a static pattern rule for that object file in the makefile as well. make then applies the static rule for targets explicitly named in it, and the implicit rule for all other .o files. Also, make refrains from announcing an error if any object file’s implicit prerequisite does not exist.

The percent sign is usually used only once in each pattern. To represent a literal percent sign in a pattern, you must escape it with a backslash. For example, the filename app%3amodule.o matches the pattern app\%3a%.o, and the resulting stem is module. To use a literal backslash in a pattern without escaping a percent sign that happens to follow it, you need to escape the backslash itself. Thus, the filename app\module.o would match the pattern app\\%.o, yielding the stem module.

Suffix Rules

The kind of pattern rule in which the percent sign represents all but the filename’s suffix is the modern way of expressing a suffix rule. In older makefiles, you might see such a rule expressed in the following notation:

.c.o:
        $(CC) $(CFLAGS) ...

The “target” in this rule consists simply of the target and source filename suffixes—and in the opposite order; that is, with the source suffix first, followed by the target suffix. This example with the target .c.o: is equivalent to a pattern rule beginning with %o: %c. If a suffix rule target contains only one suffix, then that is the suffix for source filenames, and target filenames under that rule are assumed to have no suffix.

GNU make also supports suffix rules, but that notation is considered obsolete. Pattern rules using the % wildcard character are more readable, and more versatile.

Every suffix used in the target of a suffix rule must be a “known suffix.” make stores its list of known suffixes in the built-in variable SUFFIXES. You can add your own suffixes by declaring them as prerequisites of the built-in target .SUFFIXES (see “Special Targets Used as Runtime Options” for more about this technique).

Built-In Rules

You don’t have to tell make how to do standard operations like compiling an object file from C source; the program has a built-in default rule for that operation, and for many others. Example 20-2 shows a more elegant version of our sample makefile that takes advantage of built-in rules.

Example 20-2. A makefile using built-in rules
# A slightly more elegant makefile for "circle".
 
CC = gcc
CFLAGS = -Werror -std=c99
OBJS =  circle.o circulararea.o
 
circle: $(OBJS) -lm

This makefile does away with the rule for compiling source code into objects, depending instead on make’s built-in pattern rule. Furthermore, the rule that says the executable circle depends on the two object files has no command script. This is because make also has a built-in rule to link objects to build an executable. We will look at those built-in rules in a moment. First, suppose we enter this command:

$ touch *.c ; make circle

This produces roughly the same output as before:

gcc -Werror -std=c99   -c -o circle.o circle.c
gcc -Werror -std=c99   -c -o circulararea.o circulararea.c
gcc circle.o circulararea.o  /usr/lib/libm.so  -o circle

None of these commands is visible in the new makefile in Example 20-2, even if individual arguments are recognizable in the variable assignments. To display make’s built-in rules (as well as the variables at work), you can run the program with the command-line switch -p. The output is rather long. Here are the parts of it that are relevant to our example (including the comments that make generates to identify where each variable or rule definition originates):

# default
OUTPUT_OPTION = -o $@
 
# default
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
 
# default
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
 
%: %.o
#  commands to execute (built-in):
        $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
%.o: %.c
#  commands to execute (built-in):
        $(COMPILE.c) $(OUTPUT_OPTION) $<

Note that the linking step was handled by a combination of two rules: make automatically applied the command defined by the built-in rule using the information about the prerequisites provided by the dependency rule in the makefile.

Finally, the makefile in Example 20-2, unlike Example 20-1, does not define a variable for linker options. Instead, it correctly lists the C math library as a prerequisite of the executable circle, using the same -lm notation as the compiler’s command line. The output shown illustrates how make expands this notation to the full library filename.

Implicit Rule Chains

make tries to use implicit rules, whether built-in ones or pattern rules from the makefile, for any target that doesn’t have an explicit rule with a command script. There may be many implicit rules that match a given target. For example, make has built-in rules to generate an object file (matching the pattern %.o) from source code in C (%.c), C++ (%.cpp), or even assembler (%.s). Which rule does make use, then? It selects the first one in the list for which the prerequisites are available or can be made by applying appropriate rules. In this way, make can automatically apply a chain of implicit rules to generate a target. If make generates any intermediate files that are not mentioned in the makefile, it deletes them after they have served their purpose. For example, suppose that the current directory contains only the file square.c, and the makefile contains the following:

%: %.o
        cc -o $@ $^
 
%.o : %.c
        cc -c -o $@ $<

To disable all the built-in rules and use only the two implicit rules we can see in the makefile, we’ll run make with the -r option:

$ ls
Makefile  square.c
$ make -r square
cc -c -o square.o square.c
cc -o square square.o
rm square.o
$ ls
Makefile square  square.c

From the target, the two implicit rules in the makefile, and the available source file, make found the indirect way to build the target, and then automatically cleaned up the intermediate object file because it isn’t mentioned in the makefile or on the command line.

Double-Colon Rules

Before we move away from rules, another kind of rule that you should know about is the double-colon rule, so named because it has not one but two colons between the targets and the prerequisites:

target :: prerequisites
    commands

Double-colon rules are the same as single-colon rules unless your makefile contains multiple double-colon rules for the same target. In that case, make treats the rules as alternative rather than cumulative: instead of collating all the rules’ prerequisites into a single set of dependencies for the target, make tests the target against each rule’s prerequisites separately to decide whether to execute that rule’s script. Example 20-3 shows a makefile that uses double-colon rules.

Example 20-3. Double-colon rules
# A makefile for "circle" to demonstrate double-colon rules.
 
CC = gcc
RM = rm -f
CFLAGS = -Wall -std=c99
DBGFLAGS = -ggdb -pg
DEBUGFILE = ./debug
SRC = circle.c circulararea.c
 
circle :: $(SRC)
        $(CC) $(CFLAGS) -o $@ -lm $^
 
circle :: $(DEBUGFILE)
        $(CC) $(CFLAGS) $(DBGFLAGS) -o $@ -lm $(SRC)
 
.PHONY : clean
clean  :
        $(RM) circle

The makefile in Example 20-3 builds the target circle in either of two ways, with or without debugging options in the compiler command line. In the first rule for circle, the target depends on the source files. make runs the command for this rule if the source files are newer than the executable. In the second rule, circle depends on a file named debug in the current directory. The command for that rule doesn’t use the prerequisite debug at all. That file is empty; it just sits in the directory for the sake of its timestamp, which tells make whether to build a debugging version of the circle executable. The following sample session illustrates how make can alternate between the two rules:

$ make clean
rm -f circle
$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c circulararea.c
$ make circle
make: `circle' is up to date.
$ touch debug
$ make circle
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c circulararea.c
$ make circle
make: `circle' is up to date.
$ make clean
rm -f circle
$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c circulararea.c

As the output shows, make applies only one rule or the other, depending on which rule’s prerequisites are newer than the target. (If both rules’ prerequisites are newer than the target, make applies the rule that appears first in the makefile.)

Comments

In a makefile, a hash mark (#) anywhere in a line begins a comment, unless the line is a command. make ignores comments, as if the text from the hash mark to the end of its line did not exist. Comments (like blank lines) between the lines of a rule do not interrupt its continuity. Leading whitespace before a hash mark is ignored.

If a line containing a hash mark is a command—that is, if it begins with a tab character—then it cannot contain a make comment. If the corresponding target needs to be built, make passes the entire command line, minus the leading tab character, to the shell for execution. (Some shells, such as the Bourne shell, also interpret the hash mark as introducing a comment, but that is beyond make’s control.)

Variables

All variables in make are of the same type: they contain sequences of characters, never numeric values. Whenever make applies a rule, it evaluates all the variables contained in the targets, prerequisites, and commands. Variables in GNU make come in two “flavors,” called recursively expanded and simply expanded variables. Which flavor a given variable has is determined by the specific assignment operator used in its definition. In a recursively expanded variable, nested variable references are stored verbatim until the variable is evaluated. In a simply expanded variable, on the other hand, variable references in the value are expanded immediately on assignment, and their expanded values are stored, not their names.

Variable names can include any character except :, =, and #. However, for robust makefiles and compatibility with shell constraints, you should use only letters, digits, and the underscore character.

Assignment Operators

Which assignment operator you use in defining a variable determines whether it is a simply or a recursively expanded variable. The assignment operator = in the following example creates a recursively expanded variable:

DEBUGFLAGS = $(CFLAGS) -ggdb -DDEBUG -O0

make stores the character sequence to the right of the equals sign verbatim; the nested variable $(CFLAGS) is not expanded until $(DEBUGFLAGS) is used.

To create a simply expanded variable, use the assignment operator := as shown in the following example:

OBJ = circle.o circulararea.o
TESTOBJ := $(OBJ) profile.o

In this case, make stores the character sequence circle.o circulararea.o profile.o as the value of $(TESTOBJ). If a subsequent assignment modifies the value of $(OBJ), $(TESTOBJ) is not affected.

You can define both recursively expanded and simply expanded variables not only in the makefile, but also on the make command line, as in the following example:

$ make CFLAGS=-ffinite-math-only circulararea.o

Each such assignment must be contained in a single command-line argument. If the assignment contains spaces, you must escape them or enclose the entire assignment in quotation marks. Any variable defined on the command line, or in the shell environment, can be cancelled out by an assignment in the makefile that starts with the optional override keyword, as this one does:

override CPPLFAGS = -DDEBUG

Use override assignments with caution, unless you want to confuse and frustrate future users of your makefile.

make also provides two more assignment operators. Here is the complete list:

=

Defines a recursively expanded variable.

:=

Defines a simply expanded variable.

+=

Also called the append operator. Appends more characters to the existing value of a variable. If the left operand is not yet defined, the assignment defines a recursively expanded variable. Or, to put it another way, the result of the append operator is a recursively expanded variable, unless its left operand already exists as a simply expanded variable.

This operator provides the only way to append characters to the value of a recursively expanded variable. The following assignment is wrong, as recursive expansion would cause an infinite loop:

OBJ = $(OBJ) profile.o

Here is the right way to do it:

OBJ += profile.o

The += operator automatically inserts a space before appending the new text to the variable’s previous value.

?=

The conditional assignment operator. Assigns a value to a variable, but only if the variable has no value.

The conditional assignment operator can only define recursively expanded variables. If its left operand already exists, it remains unaffected, regardless of whether it is a simply expanded or a recursively expanded variable.

In addition to these operations, there are two more ways to define make variables. One is the define directive, used to create variables of multiple lines; we will discuss this later in “Macros”. Another is by setting environment variables in the system shell before you invoke make. We will discuss make’s use of environment variables later in the chapter as well.

Variables and Whitespace

In a variable assignment, make ignores any whitespace between the assignment operator and the first non-whitespace character of the value. However, trailing whitespace up to the end of the line containing the variable assignment, or up to a comment that follows on the same line, becomes part of the variable’s value. Usually this behavior is unimportant because most references to make variables are options in shell command lines, where additional whitespace has no effect. However, if you use variable references to construct file or directory names, unintended whitespace at the end of an assignment line can be fatal.

On the other hand, if you develop complex makefiles, you might sometimes need a literal space that make does not ignore or interpret as a list separator. The easiest way is to use a variable whose value is a single space character, but defining such a variable is tricky. Simply enclosing a space in quotation marks does not have the same effect as in C. Consider the following assignment:

ONESPACE := ' '
TEST = Does$(ONESPACE)this$(ONESPACE)work?

In this case, a reference to $(TEST) would expand to the following text:

Does' 'this' 'work?

Double quotation marks are no different: they also become part of the variable’s value. To define a variable containing just the space and nothing else, you can use the following lines:

NOTHING :=
ONESPACE := $(NOTHING) # This comment terminates the variable's value.

The variable reference $(NOTHING) expands to zero characters, but it ends the leading whitespace that make trims off after the assignment operator. If you do not insert a comment after the space character that follows $(NOTHING), you may find it hard to tell when editing the makefile whether the single trailing space is present as desired.

Target-Specific Variable Assignments

You can make any of the assignment operations apply to only a specific target (or target pattern) by including a line in your makefile with the form:

target_list: [override]assignment

While make is building the given target—or its prerequisites—the target-specific or pattern-specific variable supersedes any other definition of the same variable name elsewhere in the makefile.

Example 20-4 shows a sample makefile illustrating different kinds of assignments.

Example 20-4. Variable assignments
# Tools and options:
CC = gcc
CFLAGS = -c -Wall -std=c99 $(ASMFLAGS)
DEBUGCFLAGS = -ggdb -O0
RM = rm -f
MKDIR = mkdir -p
 
# Filenames:
OBJ = circle.o circulararea.o
SYMTABS = $(OBJ:.o=.sym)
EXEC = circle
 
# The primary targets:
production: clean circle
 
testing: clean debug
 
symbols: $(SYMTABS)
 
clean:
        $(RM) $(OBJ) *.sym circle circle-dbg
 
# Rules to build prerequisites:
circle debug: $(OBJ) -lm
        $(CC) $(LDFLAGS) -o $(EXEC) $^
 
$(OBJ): %.o: %.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $<
 
$(SYMTABS): %.sym: %.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -o $*.o $<
 
# Target-specific options:
debug: CPPFLAGS += -DDEBUG
debug: EXEC = circle-dbg
debug symbols: CFLAGS += $(DEBUGCFLAGS)
symbols: ASMFLAGS = -Wa,-as=$*.sym,-L

For the targets debug and symbols, this makefile uses the append operator to add the value of DEBUGCFLAGS to the value of CFLAGS, while conserving any compiler flags already defined.

The assignment to SYMTABS illustrates another feature of make variables: you can perform substitutions when referencing them. As Example 20-4 illustrates, a substitution reference has this form:

$(name:ending=new_ending)

When you reference a variable in this way, make expands it, and then checks the end of each word in the value (where a word is a sequence of non-whitespace characters followed by a whitespace character, or by the end of the value) for the string ending. If the word ends with ending, make replaces that part with new_ending. In Example 20-4, the resulting value of $(SYMTABS) is circle.sym circulararea.sym.

The variable CFLAGS is defined near the top of the makefile, with an unconditional assignment. The expansion of the nested variable it contains, $(ASMFLAGS), is deferred until make expands $(CFLAGS) in order to execute the compiler command. The value of $(ASMFLAGS), for example, may be -Wa,-as=circle.sym,-L, or it may be nothing. When make builds the target symbols, the compiler command expands recursively to:

gcc -c -Wall -std=c99 -Wa,-as=circle.sym,-L -ggdb -O0
-o circle.o circle.c
gcc -c -Wall -std=c99 -Wa,-as=circulararea.sym,-L -ggdb -O0
-o circulararea.o circulararea.c

(Each of these two gcc commands is generated in a single line, which is split in two here to fit the page.) As you can see, if there is no variable defined with the name CPPFLAGS at the time of variable expansion, make simply replaces $(CPPFLAGS) with nothing.

Tip

Unlike C, make doesn’t balk at undefined variables. The only difference between an undefined variable and a variable whose value contains no characters is that a defined variable has a determined flavor: it is either simply expanded or recursively expanded, and cannot change its behavior, even if you assign it a new value.

Like many real-life makefiles, the one in Example 20-4 uses variables to store the names of common utilities like mkdir and rm together with the standard options that we want to use with them. This approach not only saves repetition in the makefile’s command scripts but also makes maintenance and porting easier.

The Automatic Variables

The command scripts in Example 20-4 also contain a number of single-character variables: $@, $<, $‸, and $*. These are automatic variables, which make defines and expands itself in carrying out each rule. Here is a complete list of the automatic variables and their meanings in a given rule:

$@

The target filename.

$*

The stem of the target filename—that is, the part represented by % in a pattern rule.

$<

The first prerequisite.

$‸

The list of prerequisites, excluding duplicate elements.

$?

The list of prerequisites that are newer than the target.

$+

The full list of prerequisites, including duplicates.

$%

If the target is an archive member, the variable $% yields the member name without the archive filename, and $@ supplies the filename of the archive.

The last of these automatic variables brings up a special target case. Because most programs depend not only on source code but also on library modules, make also provides a special notation for targets that are members of an archive:

archive_name(member_name): [prerequisites]
        [command_script]

The name of the archive member is enclosed in parentheses immediately after the filename of the archive itself. Here is an example:

AR = ar -rv
 
libcircularmath.a(circulararea.o): circulararea.o
      $(AR) $@ $%

This rule executes the following command to add or replace the object file in the archive:

ar -rv libcircularmath.a circulararea.o

In other make versions, these special variables also have long names that start with a dot, such as $(.TARGET) as a synonym for $@. Also, some make programs use the symbol $> for all prerequisites rather than GNU make’s $‸.

When an automatic variable expands to a list, such as a list of filenames, the elements are separated by spaces.

To separate filenames from directories, there are two more versions of each automatic variable in this list whose names are formed with the suffixes D and F. Because the resulting variable name is two characters, not one, parentheses are required. For example, $(@D) in any rule expands to the directory part of the target, without the actual filename, while $(@F) yields just the filename with no directory. (GNU make supports these forms for compatibility’s sake, but provides more flexible handling of filenames by means of functions; see “Built-In Functions”.)

Other Built-In Variables

The variables that make uses internally are described in the following list. You can also use them in makefiles. Remember that you can find out the sources of all variables in the output of make -p:

CURDIR

This variable holds the name of the current working directory after make has processed its -C or --directory command-line options. You can modify this variable, but doing so doesn’t change the working directory.

.LIBPATTERNS

A list of filename patterns that determines how make searches for libraries when a prerequisite starts with -l. The default value is lib%.so lib%.a. A prerequisite called -lncurses causes make to search for libncurses.so and libncurses.a, in that order.

MAKE

This variable holds the name of the make executable. When you use $(MAKE) in a command, make automatically expands it to the full path name of the program file so that all recursive instances of make are from the same executable.

MAKECMDGOALS

make stores any targets specified on the command line in this variable. You can modify this variable, but doing so doesn’t change the targets make builds.

MAKEFILES

A list of standard makefiles that make reads every time it starts.

MAKEFILE_LIST

A list of all the makefiles that the present invocation of make is using.

MAKEFLAGS

This variable contains the command-line options with which make was invoked, with some exceptions. Each instance of make reads this variable from the environment on starting, and exports it to the environment before spawning a recursive instance. You can modify this variable in the environment or in a makefile.

MAKELEVEL

When make invokes itself recursively, this variable holds the degree of recursion of the present instance. In exporting this variable to the environment, make increments its value. Child instances of make print this number in square brackets after the program name in their console output.

MAKESHELL

On Windows, this variable holds the name of the command interpreter for make to use in running command scripts. MAKESHELL overrides SHELL.

SHELL

The name of the shell that make invokes when it runs command scripts, usually /bin/sh. Unlike most variables, make doesn’t read the value of SHELL from the environment (except on Windows), as users’ shell preferences would make make’s results less consistent. If you want make to run commands using a specific shell, you must set this variable in your makefile.

SUFFIXES

make’s default list of known suffixes (see “Suffix Rules”). This variable contains the default list, which is not necessarily the list currently in effect; the value of this variable does not change when you clear the list or add your own known suffixes using the built-in target .SUFFIXES.

VPATH

The directory path that make uses to search for any files not found in the current working directory.

Environment Variables

If you want, you can set environment variables in the shell before starting make, and then reference them in the makefile using the same syntax as for other make variables. Furthermore, you can use the export directive in the makefile to copy any or all of make’s variables to the shell environment before invoking shell commands, as in the following example:

INCLUDE=/usr/include:/usr/local/include:~/include
export INCLUDE
export LIB := $(LIBS):/usr/lib:/usr/local/lib
 
%.o: %.c
        $(CC) $(CFLAGS) -o $@ -c $<

When the C compiler is invoked by the pattern rule in this example, it can obtain information defined in the makefile by reading the environment variables INCLUDE and LIB. Similarly, make automatically passes its command-line options to child instances by copying them to and then exporting the variable MAKEFLAGS. See “Recursive make Commands” for other examples.

The shell environment is more restrictive than make with regard to the characters that are permitted in variable names and values. It might be possible to trick your shell into propagating environment variables containing illegal characters, but the easiest thing by far is just to avoid special characters in any variables you want to export.

Phony Targets

The makefile in Example 20-4 also illustrates several different ways of using targets. The targets debug, testing, production, clean, and symbols are not names of files to be generated. Nonetheless, the rules clearly define the behavior of a command like make production or make clean symbols debug. Targets that are not the names of files to be generated are called phony targets.

In Example 20-4, the phony target clean has a command script but no prerequisites. Furthermore, its command script doesn’t actually build anything: on the contrary, it deletes files generated by other rules. We can use this target to clear the board before rebuilding the program from scratch. In this way, the phony targets testing and production ensure that the executable is linked from object files made with the desired compiler options by including clean as one of their prerequisites.

You can also think of a phony target as one that is never supposed to be up to date: its command script should be executed whenever the target is called for. This is the case with clean—as long as no file with the name clean happens to appear in the project directory.

Often, however, a phony target’s name might really appear as a filename in the project directory. For example, if your project’s products are built in subdirectories, such as bin and doc, you might want to use subdirectory names as targets. But you must make sure that make rebuilds the contents of a subdirectory when out of date, even if the subdirectory itself already exists.

For such cases, make lets you declare a target as phony regardless of whether a matching filename exists. The way to do so is to add a line like the following one to your makefile, making the target a prerequisite of the special built-in target .PHONY:

.PHONY: clean

Or, to use an example with a subdirectory name, suppose we added these lines to the makefile in Example 20-4:

.PHONY: bin
bin: circle
        $(MKDIR) $@
        $(CP) $< $@/
        $(CHMOD) 600 $@/$<

This rule for the target bin actually does create bin in the project directory. However, because bin is explicitly phony, it is never up to date. make puts an up-to-date copy of circle in the bin subdirectory even if bin is newer than its prerequisite, circle.

You should generally declare all phony targets explicitly, as doing so can also save time. For targets that are declared as phony, make does not bother looking for appropriately named source files that it could use with implicit rules to build a file with the target’s name. An old-fashioned, slightly less intuitive way of producing the same effect is to add another rule for the target with no prerequisites and no commands:

bin: circle
        $(MKDIR) $@
        $(CP) $< $@/
        $(CHMOD) 600 $@/$<
bin:

The .PHONY target is preferable if only because it is so explicit, but you may see the other technique in automatically generated dependency rules, for example.

Other Target Attributes

There are also other attributes that you can assign to certain targets in a makefile by making those targets prerequisites of other built-in targets like .PHONY. The most important of these built-in targets are listed here (other special built-in targets that can be used in makefiles to alter make’s runtime behavior in general are listed at the end of this chapter):

.IGNORE

For any target that is a prerequisite of .IGNORE, make ignores any errors that occur in executing the commands to build that target. .IGNORE itself does not take a command script.

You can also put .IGNORE in a makefile with no prerequisites at all, although it is probably not a good idea. If you do, make ignores all errors in running any command script.

.INTERMEDIATE

Ordinarily, when make needs to build a target whose prerequisites do not exist, it searches for an appropriate rule to build them first. If the absent prerequisites are not named anywhere in the makefile and make has to resort to implicit rules to build them, they are called intermediate files. make deletes any intermediate files after building its intended target (see “Implicit Rule Chains”). If you want certain files to be treated in this way even though they are mentioned in your makefile, declare them as prerequisites of .INTERMEDIATE.

.LOW_RESOLUTION_TIME

On some systems, the timestamps on files have resolution of less than a second, yet certain programs create timestamps that reflect only full seconds. If this behavior causes make to misjudge the relative ages of files on your system, you can declare any file with high-resolution timestamps as a prerequisite of .LOW_RESOLUTION_TIME. Then make considers the file up to date if its timestamp indicates the same whole second in which its prerequisite was stamped. Members of library archives are automatically treated as having low-resolution timestamps.

.PHONY

Any targets that are prerequisites of .PHONY are always treated as out of date.

.PRECIOUS

Normally, if you interrupt make while running a command script—if make receives any fatal signal, to be more precise—make deletes the target it was building before it exits. Any target you declare as a prerequisite of .PRECIOUS is not deleted in such cases, however.

Furthermore, when make builds a target by concatenating implicit rules, it normally deletes any intermediate files that it creates by one such rule as prerequisites for the next. However, if any such file is a prerequisite of .PRECIOUS (or matches a pattern that is a prerequisite of .PRECIOUS), make does not delete it.

.SECONDARY

Like .INTERMEDIATE, except that make does not automatically delete files that are prerequisites of .SECONDARY.

You can also put .SECONDARY in a makefile with no prerequisites at all. In this case, make treats all targets as prerequisites of .SECONDARY.

A few other built-in targets act like general runtime options, affecting make’s overall behavior just by appearing in a makefile. These are listed in “Running make”.

Macros

When we talk about macros in make, you should remember that there is really no difference between them and variables. Nonetheless, make provides a directive that allows you to define variables with both newline characters and references to other variables embedded in them. Programmers often use this capability to encapsulate multiline command sequences in a variable, so that the term macro is fairly appropriate. (The GNU make manual calls them “canned command sequences.”)

To define a variable containing multiple lines, you must use the define directive. Its syntax is:

define macro_name
macro_value
endef

The line breaks shown in the syntax are significant: define and endef both need to be placed at the beginning of a line, and nothing may follow define on its line except the name of the macro. Within the macro_value, though, any number of newline characters may also occur. These are included literally, along with all other characters between the define and endef lines, in the value of the variable you are defining. Here is a simple example:

define installtarget
 @echo Installing $@ in $(USRBINDIR) ... ;\
 $(MKDIR) -m 7700 $(USRBINDIR)           ;\
 $(CP) $@ $(USRBINDIR)/                  ;\
 @echo ... done.
endef

The variable references contained in the macro installtarget are stored literally as shown here, and expanded only when make expands $(installtarget) itself, in a rule like this, for example:

circle: $(OBJ) $(LIB)
        $(CC) $(LDFLAGS) -o $@ $^
ifdef INSTALLTOO
        $(installtarget)
endif

Functions

GNU make goes beyond simple macro expansion to provide functions—both built-in and user-defined functions. By using parameters, conditions, and built-in functions, you can define quite powerful functions and use them anywhere in your makefiles.

The syntax of function invocations in makefiles, like that of macro references, uses the dollar sign and parentheses:

$(function_name argument[,argument[,...]])
Tip

Whitespace in the argument list is significant. make ignores any whitespace before the first argument, but if you include any whitespace characters before or after a comma, make treats them as part of the adjacent argument value.

The arguments themselves can contain any characters, except for embedded commas. Parentheses must occur in matched pairs; otherwise, they will keep make from parsing the function call correctly. If necessary, you can avoid these restrictions by defining a variable to hold a comma or parenthesis character, and using a variable reference as the function argument.

Built-In Functions

GNU make provides more than 20 useful text-processing and flow-control functions, which are listed briefly in the following sections.

Text-processing functions

The text-processing functions listed here are useful in operating on the values of make variables, which are always sequences of characters:

$(subst find_text,replacement_text,original_text)

Expands to the value of original_text, except that each occurrence of find_text in it is changed to replacement_text.

$(patsubst find_pattern,replacement_pattern,original_text)

Expands to the value of original_text, except that each occurrence of find_pattern in it is changed to replacement_pattern. The find_pattern argument may contain a percent sign as a wildcard for any number of non-whitespace characters. If replacement_pattern also contains a percent sign, it is replaced with the characters represented by the wildcard in find_pattern. The patsubst function also collapses each unquoted whitespace sequence into a single space character.

$(strip original_text)

Removes leading and trailing whitespace, and collapses each unquoted internal whitespace sequence into a single space character.

$(findstring find_text,original_text)

Expands to the value of find_text, if it occurs in original_text; or to nothing if it does not.

$(filter find_patterns,original_text)

find_patterns is a whitespace-separated list of patterns like that in patsubst. The function call expands to a space-separated list of the words in original_text that match any of the words in find_patterns.

$(filter-out find_patterns,original_text)

Expands to a space-separated list of the words in original_text that do not match any of the words in find_patterns.

$(sort original_text)

Expands to a list of the words in original_text, in alphabetical order, without duplicates.

$(word n,original_text)

Expands to the nth word in original_text.

$(firstword original_text)

The same as $(word 1,original_text).

$(wordlist n,m,original_text)

Expands to a space-separated list of the nth through mth words in original_text.

$(words original_text)

Expands to the number of words in original_text.

Filename-manipulation functions

These functions operate on a whitespace-separated list of file or directory names, and expand to a space-separated list containing a processed element for each name in the argument:

$(dir filename_list)

Expands to a list of the directory parts of each filename in the argument.

$(notdir filename_list)

Expands to a list of the filenames in the argument with their directory parts removed.

$(suffix filename_list)

Expands to a list of the filename suffixes in the argument. Each suffix is the filename ending, beginning with the last period (.) in it; or nothing, if the filename contains no period.

$(basename filename_list)

Expands to a list of the filenames in the argument with their suffixes removed. Directory parts are unchanged.

$(addsuffix suffix,filename_list)

Expands to a list of the filenames in the argument with suffix appended to each one. (suffix is not treated as a list, even if it contains whitespace.)

$(addprefix prefix,filename_list)

Expands to a list of the filenames in the argument with prefix prefixed to each one. (prefix is not treated as a list, even if it contains whitespace.)

$(join prefix_list,suffix_list)

Expands to a list of filenames composed by concatenating each word in prefix_list with the corresponding word in suffix_list. If the lists have different numbers of elements, the excess elements are included unchanged in the result.

$(wildcard glob)

Expands to a list of existing filenames that match the pattern glob, which typically contains shell wildcards.

Conditions and flow control functions

The functions listed here allow you to perform operations conditionally, process lists iteratively, or execute the contents of a variable:

$(foreach name,list,replacement)

The argument name is a name for a temporary variable (without dollar sign and parentheses). The replacement text typically contains a reference to $(name). The result of the function is a list of expansions of replacement, using successive elements of list as the value of $(name).

$(if condition,then_text[,else_text])

Expands to the value of then_text if condition, stripped of leading and trailing spaces, expands to a nonempty text. Otherwise, the function expands to the value of else_text, if present.

$(eval text)

Treats the expansion of text as included makefile text.

Operations on variables

The argument variable_name in the descriptions that follow is just the name of a variable (without dollar sign and parentheses), not a reference to it. (Of course, you may use a variable reference to obtain the name of another variable.)

$(value variable_name)

Expands to the “raw” value of the variable named, without further expansion of any variable references it may contain.

$(origin variable_name)

Expands to one of the following values to indicate how the variable named was defined:

undefined
default
environment
environment override
file
command line
override
automatic
$(call variable_name,argument[,argument[,…]])

Expands the variable named, replacing numbered parameters in its expansion ($1, $2, etc.) with the remaining arguments. In effect, this built-in function allows you to create user-defined function-like macros. See “User-Defined Functions”.

System functions

The functions in the following list interact with make’s environment:

$(shell text)

Passes the expansion of text to the shell. The function expands to the standard output of the resulting shell command.

$(error text)

make prints the expansion of text as an error message and exits.

$(warning text)

Like the error command except that make doesn’t exit. The function expands to nothing.

User-Defined Functions

You can define functions in the same way as simply expanded variables or macros, using the define directive or the := assignment operator. Functions in make are simply variables that contain numbered parameter references ($1, $2, $3, etc.) to represent arguments that you provide when you use the built-in function call to expand the variable.

In order for these parameters to be replaced with the arguments when make expands your user-defined function, you have to pass the function name and arguments to the built-in make function call.

Example 20-5 defines the macro getmodulename to return a filename for a program module depending on whether the flag STATIC has been set, to indicate a statically linked executable, or left undefined, to indicate dynamic object linking.

Example 20-5. The user-defined function getmodulename
# A conditional assignment, just as a reminder that
# the user may define STATIC=1 or STATIC=yes on the command line.
STATIC ?=
 
# A function to generate the "library" module name:
# Syntax: $(call getmodulename, objectname, isstatic)
define getmodulename
  $(if $2,$1,$(addsuffix .so,$(basename $1)))
endef
 
all: circle
 
circle: circle.o $(call getmodulename,circulararea.o,$(STATIC))
        $(CC) -o $@ $^
 
ifndef STATIC
%.so: %.o
      $(CC) -shared -o $@ $<
endif

The $(call ) function expands the macro getmodulename either to the text circulararea.o, or, if the variable STATIC is not defined, to circulararea.so.

The rule to build the object file circulararea.o in Example 20-5 brings us to our next topic, as it illustrates another way to query the STATIC flag: by means of the conditional directive ifndef.

Directives

We have already introduced the define directive, which produces a simply expanded variable or a function. Other make directives allow you to influence the effective contents of your makefiles dynamically by making certain lines in a makefile dependent on variable conditions, or by inserting additional makefiles on the fly.

Conditionals

You can also make part of your makefile conditional upon the existence of a variable by using the ifdef or ifndef directive. They work the same as the C preprocessor directives of the same names, except that in make, an undefined variable is the same as one whose value is empty. Here is an example:

OBJ = circle.o
LIB = -lm
 
ifdef SHAREDLIBS
  LIB += circulararea.so
else
  OBJ += circulararea.o
endif
 
circle: $(OBJ) $(LIB)
        $(CC) -o $@ $^
 
%.so : %.o
       $(CC) -shared -o $@ $<

As the example shows, the variable name follows ifdef or ifndef without a dollar sign or parentheses. The makefile excerpt shown here defines a rule to link object files into a shared library if the variable SHAREDLIBS has been defined. You might define such a general build option in an environment variable, or on the command line, for example.

You can also make certain lines of the makefile conditional upon whether two expressions—usually the value of a variable and a literal string—are equal. The ifeq and ifneq directives test this condition. The two operands whose equality is the condition to test are either enclosed together in parentheses and separated by a comma, or enclosed individually in quotation marks and separated by whitespace. Here is an example:

ifeq ($(MATHLIB), /usr/lib/libm.so)
  # ... Special provisions for this particular math library ...
endif

That conditional directive, with parentheses, is equivalent to this one with quotation marks:

ifeq "$(MATHLIB)" "/usr/lib/libm.so"
  # ... Special provisions for this particular math library ...
endif

The second version has one strong advantage: the quotation marks make it quite clear where each of the operands begins and ends. In the first version, you must remember that whitespace within the parentheses is significant, except immediately before and after the comma (see also “Variables and Whitespace”).

Tip

make’s handling of whitespace in the ifeq and ifneq directives is not the same as in function calls!

Includes

The include directive serves the same purpose as its C preprocessor counterpart but works slightly differently. To start with an example, you might write a makefile named defaults.mk with a set of standard variables for your environment, containing something like this:

BINDIR = /usr/bin
HOMEBINDIR = ~/bin
SRCDIR = project/src
BUILDDIR = project/obj
 
RM = rm -f
MKDIR = mkdir -p
# ... etc. ...

Then you could add these variables to any makefile by inserting this line:

include defaults.mk

The include keyword may be followed by more than one filename. You can also use shell wildcards like * and ?, and reference make variables to form filenames:

include $(HOMEBINDIR)/myutils.mk $(SRCDIR)/*.mk

For included files without an absolute path, make searches in the current working directory first, then in any directories specified with the -I option on the command line, and then in standard directories determined when make was compiled.

If make fails to find a file named in an include directive, it continues reading the makefile, and then checks to see whether there is a rule that will build the missing file. If so, make rereads the whole makefile after building the included file. If not, make exits with an error. The -include directive (or its synonym sinclude) is more tolerant: it works the same as include except that make ignores the error and goes on working if it can’t find or build an included file.

Other Directives

Of the other four make directives, three are used to control the interplay between make’s internal variables and the shell environment, while the fourth instructs make where to look for specific kinds of files. These directives are:

override variable_assignment

Ordinarily, variables defined on the command line take precedence over definitions or assignments with the same name in a makefile. Prefixing the override keyword makes an assignment in a makefile take precedence over the command line. The variable_assignment may use the =, :=, or += operator, or the define directive.

export [variable_name|variable_assignment]

You can prefix export to a variable assignment or to the name of a variable that has been defined to export that variable to the environment, so that programs invoked by command scripts (including recursive invocations of make) can read it.

The export directive by itself on a line exports all make variables to the environment.

Tip

make does not export variables whose names contain any characters other than letters, digits, and underscores. The values of variables you export from makefiles may contain characters that are not allowed in shell environment variables. Such values will probably not be accessible by ordinary shell commands. Nonetheless, child instances of make itself can inherit and use them.

The make variables SHELL and MAKEFLAGS, and also MAKEFILES if you have assigned it a value, are exported by default. Any variables that the current instance of make acquired from the environment are also passed on to child processes.

unexport variable_name

Use the unexport directive to prevent a variable from being exported to the environment. The unexport directive always overrides export.

vpath pattern directory[:directory[:]]

The pattern in this directive is formed in the same way as in make pattern rules, using one percent sign (%) as a wildcard character. Whenever make needs a file that matches the pattern, it looks for it in the directories indicated, in the order of their appearance. Here is an example:

vpath  %.c  $(MYPROJECTDIR)/src
vpath  %.h  $(MYPROJECTDIR)/include:/usr/include

On Windows, the separator character in the directory list is a semicolon, not a colon.

Running make

This section explains how to add dependency information to the makefile automatically, and how to use make recursively. These two ways of using make are common and basic, but they do involve multiple features of the program. Finally, the remainder of this section is devoted to a reference list of GNU make’s command-line options and the special pseudotargets that also function as runtime options.

The command-line syntax of make is as follows:

 make [options] [variable_assignments] [target [target [...]]]

If you don’t specify any target on the command line, make behaves as though you had specified the default target; that is, whichever target is named first in the makefile. make builds other targets named in the makefile only if you request them on the command line or if they need to be built as prerequisites of any target requested.

Generating Header Dependencies

Our program executable circle depends on more files than those we have named in the sample makefile up to now. To begin with, just think of the standard headers included in our source code—not to mention the implementation-specific header files they include in turn.

Most C source files include both standard and user-defined header files, and the compiled program should be considered out of date whenever any header file has been changed. Because you cannot reasonably be expected to know the full list of header files involved, the standard make technique to account for these dependencies is to let the C preprocessor analyze the #include directives in your C source and write the appropriate make rules. The makefile lines in Example 20-6 fulfill this purpose.

Example 20-6. Generating header dependencies
CC = gcc
OBJ = circle.o circulararea.o
LIB = -lm
 
circle: $(OBJ) $(LIB)
        $(CC) $(LDFLAGS) -o $@ $^
 
%.o: %.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $<
 
dependencies: $(OBJ:.o=.c)
        $(CC) -M $^ > $@
 
include dependencies

The third rule uses a special kind of make variable reference, called a substitution reference, to declare that the target dependencies depend on files like those named in the value of $(OBJ) but with the ending .c instead of .o. The command to build dependencies runs the compiler with the preprocessor option -M, which instructs it to collate dependency information from source files. (The GCC compiler permits fine control of the dependency output by means of more preprocessor options that start with -M, which are listed in “GCC Options for Generating Makefile Rules”.)

The first time you use this makefile, make prints an error message about the include directive because no file named dependencies exists. When this happens, however, make automatically treats the missing file named in the include directive as a target, and looks for a rule to build it. The include directive itself is placed below the target rules to prevent the included file’s contents from defining a new default target.

Recursive make Commands

Your makefile rules can include any command that is executable on your system. This includes the make command itself, and recursive invocation of make is in fact a frequently used technique, especially to process source code in subdirectories. make is designed to be aware of such recursive invocation, and incorporates certain features that help it work smoothly when you use it in this way. This section summarizes the special features of “recursive make.”

The most typical recursive use of make is in building projects that are organized in subdirectories with a makefile in each one. The following snippet illustrates how a top-level makefile can invoke recursive instances of make in three subdirectories named utils, drivers, and doc:

.PHONY: utils drivers doc
 
utils drivers doc:
    $(MAKE) -C $@

The variable MAKE is not defined in the makefile; it is defined internally to yield the full pathname of the currently running program file. Your makefiles should always invoke make in this way to ensure consistent program behavior.

The command-line option -C, or its long form, --directory, causes make to change to the specified working directory on startup, before it even looks for a makefile. This is how make “passes control” to the makefile in a subdirectory when used recursively. In this example, the command does not name a target, so the child make will build the first target named in the default makefile in the given subdirectory.

The subdirectories themselves are declared as prerequisites of the special target .PHONY so that make never considers them up to date (see “Phony Targets” for more details). However, if files in one subdirectory depend on files in a parallel subdirectory, you must account for these dependencies in the makefile of a higher-level directory that contains both subdirectories.

There are a few things to remember about command-line options and special variables when you use make recursively. A more complete list of make options and environment variables appears in the following section. The following list merely summarizes those with a special relevance to the recursive use of make:

  • Some of make’s command-line options instruct it not to execute commands but to only print them (-n), touch the files (-t), or indicate whether the targets are up to date (-q). In these cases, if the subordinate make command were not executed, then these options would be incompatible with the recursive use of make. To ensure recursion, when you run make with one of the -t, -n, or -q options, commands containing the variable reference $(MAKE) are executed even though other commands are not. You can also extend this special treatment to other commands individually by prefixing a plus sign (+) to the command line as a command modifier.

  • The variable MAKELEVEL automatically contains a numeral indicating the recursion depth of the current make instance, starting with 0 for a make invoked from the console.

  • The parent instance of make passes its command-line options to child instances by copying them to the environment variable MAKEFLAGS. However, the options -C, -f, -o, and -W are exceptions: these options, which take a file or directory name as their argument, do not appear in MAKEFLAGS.

  • The -j option, whose argument tells make how many commands it can spawn for parallel processing, is passed on to child instances of make but with the parallel job limit decreased by one.

  • By default, a child instance of make inherits those of its parent’s variables that were defined on the command line or in the environment. You can use the export directive to pass on variables defined in a makefile.

Like any other shell command in a makefile rule, a recursive instance of make can exit with an error status. If this happens, the parent make also exits with an error (unless it was started with the -k or --keep-going option), so that the error cascades up the chain of recursive make instances.

When using make recursively with multiple makefiles in subdirectories, you should use the include directive to avoid duplicating common definitions, implicit rules, and so on. See “Includes” for more information.

Command-Line Options

The following is a brief summary of the command-line options supported by GNU make. Some of these options can also be enabled by including special targets in the makefile. These targets are described in “Special Targets Used as Runtime Options”.

-B, --always-make

Build unconditionally. In other words, make considers all targets out of date.

-C dir, --directory=dir

make changes the current working directory to dir before it does anything else. If the command line includes multiple -C options (which is often the case when make invokes itself recursively), each directory specified builds on the previous one. Here is an example:

$ make -C src -C common -C libs

These options would have the same effect as -C src/common/libs.

-d

Print debugging information.

-e, --environment-overrides

In the case of multiple definitions of a given variable name, variables defined on the make command line or in makefiles normally have precedence over environment variables. This command-line option makes environment variables take precedence over variable assignments in makefiles (except for variables specified in override directives).

-f filename, --file=filename, --makefile=filename

Use the makefile filename.

-h, --help

Print make’s command-line options.

-i, --ignore-errors

Ignore any errors that occur when executing command scripts.

-I dir, --include-dir=dir

If a makefile contains include directives that specify files without absolute paths, search for such files in the directory dir (in addition to the current directory). If the command line includes several -I options, the directories are searched in the order of their occurrence.

-j [number], --jobs[=number]

Run multiple commands in parallel. The optional integer argument number specifies the maximum number of simultaneous jobs. The -j argument by itself causes make to run as many simultaneous commands as possible. (Naturally, make is smart enough not to start building any target before its prerequisites have been completed.) If the command line includes several -j options, the last one overrides all others.

Warning

Parallel jobs spawned by make do not share the standard streams elegantly. Console output from different jobs can appear in random order, and only one job can inherit the stdin stream from make. If you use the -j option, make sure none of the commands in your makefiles read from stdin.

-k, --keep-going

This option tells make not to exit after a command has returned a nonzero exit status. Instead, make abandons the failed target and any other targets that depend on it but continues working on any other goals in progress.

-l [number], --load-average[=number], --max-load[=number]

In conjunction with the -j option, -l (that’s a lowercase L) prevents make from executing more simultaneous commands whenever the system load is greater than or equal to the floating-point value number. The -l option with no argument cancels any load limit imposed by previous -l options.

-n, --just-print, --dry-run, --recon

make prints the commands it would otherwise run, but doesn’t actually execute them.

-o filename, --old-file=filename, --assume-old=filename__

make treats the specified file as if it were up to date, and yet older than any file that depends on it.

-p, --print-data-base

Before executing any commands, make prints its version information and all its rules and variables, including built-ins and those acquired from makefiles.

-q, --question

make builds nothing and prints nothing, but returns an exit status as follows:

Exit status Meaning

0

All specified targets are up to date.

1

At least one target is out of date.

2

An error occurred.

-r, --no-builtin-rules

This option disables make’s built-in implicit rules, as well as the default list of suffixes for old-style suffix rules. Pattern rules, user-defined suffixes, and suffix rules that you have defined in makefiles still apply, as do built-in variables.

-R, --no-builtin-variables

Like -r, but also disables make’s built-in rule-specific variables. Variables you define in makefiles are unaffected.

-s, --silent, --quiet

Ordinarily, make echoes each command on standard output before executing it. This option suppresses such output.

-S, --no-keep-going, --stop

This option causes a recursive instance of make to ignore a -k or --keep-going option inherited from its parent make.

-t, --touch

make simply touches target files—that is, it updates their timestamps—instead of rebuilding them.

-v, --version

make prints its version and copyright information.

-w, --print-directory

make prints a line indicating the working directory before and after processing the makefile. This output can be useful in debugging recursive make applications. This option is enabled by default for recursive instances of make, and whenever you use the -C option.

--no-print-directory

Disable the working directory output in cases where -w is automatically activated.

-W filename, --what-if=filename, --new-file=<filename,
--assume-new=filename

make treats the file filename as if it were brand new.

--warn-undefined-variables

Normally, make takes references to undefined variables in its stride, treating them like references to variables with empty values. This option provides warnings about undefined variables to help you debug makefiles.

Special Targets Used as Runtime Options

The built-in targets listed in this section are ordinarily used in makefiles to alter make’s runtime behavior in general. Other built-in targets are used primarily to assign attributes to certain targets in a makefile, and are listed in “Other Target Attributes”.

.DEFAULT

You can use the built-in target .DEFAULT to introduce a command script that you want make to execute for any target that is not covered by any other explicit or implicit rule. make also executes the .DEFAULT command script for every prerequisite that is not a target in some rule.

.DELETE_ON_ERROR

You can include the built-in target .DELETE_ON_ERROR anywhere in a makefile to instruct make to delete any target that has been changed by its command script if the script returns a nonzero value on exiting.

.SILENT

Normally, make prints each command to standard output before executing it. However, if a given target is a prerequisite of .SILENT, then make does not print the rules when building that target.

If you include .SILENT with no prerequisites in a makefile, it applies to all targets, like the command-line options -s or --silent.

.EXPORT_ALL_VARIABLES

This target acts as an option telling make to export all the currently defined variables before spawning child processes (see “Recursive make Commands”).

.NOTPARALLEL

This built-in target is a general option; any prerequisites are ignored. The target .NOTPARALLEL in a makefile overrides the command-line option -j for the current instance of make, so that targets are built in sequence. If make invokes itself, however, the new instance of make still executes commands in parallel, unless its makefile also contains .NOTPARALLEL.

.SUFFIXES

This built-in target defines the list of suffixes that make recognizes for use in old-style suffix rules (see “Suffix Rules”). You can add suffixes to the built-in list by naming them as prerequisites of .SUFFIXES, or clear the list by declaring the target .SUFFIXES with no prerequisites.

GCC Options for Generating Makefile Rules

-M

Generate a rule showing the prerequisites for the object file that would result from compiling a given source file. The -M option implies the -E option (preprocess only; don’t compile), but the -MD and -MMD variants do not. By default, the dependency rules are written to standard output.

-MD

Like -M, but allows GCC to compile source files (unless -E is also present) in addition to running the preprocessor. The dependency output is written to a file whose name is taken from the -o argument, if any, but with the filename ending .d.

-MM

Like -M, but omit header files located in system header directories (and any files they depend on in turn) from the dependency list.

-MMD

Combines the effects of -MM and -MD.

The following options are modifiers used in addition to -M, -MD, -MM, or -MMD:

-MF filename

Writes the dependency information to filename rather than to standard output or to a preprocessor output file.

-MG

Include nonexistent header files in the dependency list.

-MP

Include a phony target for each header file in the dependency output. The effect is that make doesn’t complain about header files that have been removed from the project but not from the dependency list.

-MT target

Substitute target for the actual target in generating dependency rules.

-MQ target

Like -MT, but quote any special characters.

1 Before makefile or Makefile, GNU make without the -f option first looks for a file named GNUmakefile.