Unlike most variables, the variable SHELL is never set from the environment. This is
because the SHELL environment variable is used to specify your personal choice of shell
program for interactive use. It would be very bad for personal choices like this to aﬀect the
functioning of makeﬁles. SeeSection6.10[VariablesfromtheEnvironment],page70.
Furthermore, when you do set SHELL in your makeﬁle that value is not exported in the
environment to recipe lines that make invokes. Instead, the value inherited from the user’s
environment, if any, is exported. You can override this behavior by explicitly exporting
SHELL (seeSection5.7.2[CommunicatingVariablestoaSub-make],page52), forcing it to
be passed in the environment to recipe lines.
However, on MS-DOS and MS-Windows the value of SHELL in the environment is used,
since on those systems most users do not set this variable, and therefore it is most likely
set speciﬁcally to be used by make. On MS-DOS, if the setting of SHELL is not suitable for
make, you can set the variable MAKESHELL to the shell that make should use; if set it will be
used as the shell instead of the value of SHELL.
Choosing a Shell in DOS and Windows
Choosing a shellin MS-DOS andMS-Windows is much morecomplex thanonother systems.
On MS-DOS, if SHELL is not set, the value of the variable COMSPEC (which is always set)
is used instead.
The processing of lines that set the variable SHELL in Makeﬁles is diﬀerent on MS-DOS.
The stock shell, command.com, is ridiculously limited in its functionality and many users of
make tend to install a replacement shell. Therefore, on MS-DOS, make examines the value
of SHELL, and changes its behavior based on whether it points to a Unix-style or DOS-style
shell. This allows reasonable functionality even if SHELL points to command.com.
If SHELL points to a Unix-style shell, make on MS-DOS additionally checks whether that
shell can indeed be found; if not, it ignores the line that sets SHELL. In MS-DOS, GNU
make searches for the shell in the following places:
1. In the precise place pointed to by the value of SHELL. For example, if the makeﬁle
speciﬁes ‘SHELL = /bin/sh’, make will look in the directory /bin on the current drive.
2. In the current directory.
3. In each of the directories in the PATH variable, in order.
In every directory it examines, make will ﬁrst look for the speciﬁc ﬁle (sh in the example
above). If this is not found, it will also look in that directory for that ﬁle with one of the
known extensions which identify executable ﬁles. For example .exe, .com, .bat, .btm, .sh,
and some others.
If any of these attempts is successful, the value of SHELL will be set to the full pathname
of the shell as found. However, if none of these is found, the value of SHELL will not be
changed, and thus the line that sets it will be eﬀectively ignored. This is so make will only
support features speciﬁc to a Unix-style shell if such a shell is actually installed on the
system where make runs.
Note that this extended search for the shell is limited to the cases where SHELL is set
from the Makeﬁle; if it is set in the environment or command line, you are expected to set
it to the full pathname of the shell, exactly as things are on Unix.
Chapter 5: Writing Recipes in Rules
The eﬀect of the above DOS-speciﬁc processing is that a Makeﬁle that contains ‘SHELL
=/bin/sh’ (as many Unix makeﬁles do), will work on MS-DOS unaltered if you have e.g.
sh.exe installed in some directory along your PATH.
5.4 Parallel Execution
GNU make knows how to execute several recipes at once. Normally, make will execute
only one recipe at a time, waiting for it to ﬁnish before executing the next. However, the
‘-j’ or ‘--jobs’ option tells make to execute many recipes simultaneously. You can inhibit
parallelism in a particular makeﬁle with the .NOTPARALLEL pseudo-target (seeSection4.8
[Special Targets], page 32).
On MS-DOS, the ‘-j’ option has no eﬀect, since that system doesn’t support multi-
If the ‘-j’ option is followed by an integer, this is the number of recipes to execute at
once; this is called the number of job slots. If there is nothing looking like an integer after
the ‘-j’ option, there is no limit on the number of job slots. The default number of job
slots is one, which means serial execution (one thing at a time).
Handling recursive make invocations raises issues for parallel execution. For more infor-
mation on this, seeSection5.7.3[CommunicatingOptionstoaSub-make],page54.
If a recipe fails (is killed by a signal or exits with a nonzero status), and errors are
not ignored for that recipe (seeSection 5.5 [Errors s inRecipes], , page49), the remaining
recipe lines to remake the same target will not be run. If a recipe fails and the ‘-k’ or
‘--keep-going’ option was not given (see e Section 9.7[Summary y ofOptions],page104),
make aborts execution. If make terminates for any reason (including a signal) with child
processes running, it waits for them to ﬁnish before actually exiting.
When the system is heavily loaded, you will probably want to run fewer jobs than when
it is lightly loaded. You can use the ‘-l’ option to tell make to limit the number of jobs to
run at once, based on the load average. The ‘-l’ or ‘--max-load’ option is followed by a
ﬂoating-point number. For example,
will not let make start more than one job if the load average is above 2.5. The ‘-l’ option
with no following number removes the load limit, if one was given with a previous ‘-l’
More precisely, when make goes to start up a job, and it already has at least one job
running, it checks the current load average; if it is not lower than the limit given with ‘-l’,
make waits until the load average goes below that limit, or until all the other jobs ﬁnish.
By default, there is no load limit.
5.4.1 Output During Parallel Execution
When running several recipes in parallel the output from each recipe appears as soon as
it is generated, with the result that messages from diﬀerent recipes may be interspersed,
sometimes even appearing on the same line. This can make reading the output very diﬃcult.
To avoid this you can use the ‘--output-sync’ (‘-O’) option. This option instructs make
to save the output from the commands it invokes and print it all once the commands are
completed. Additionally,if there are multiple recursive make invocations running in parallel,
they will communicate so that only one of them is generating output at a time.
If working directory printing is enabled (see Section5.7.4 [The ‘--print-directory’
Option], page 55),theenter/leavemessagesareprintedaroundeachoutputgrouping. If
youprefer not to see these messages add the ‘--no-print-directory’ option to MAKEFLAGS.
There are four levels of granularity when synchronizing output, speciﬁed by giving an
argument to the option (e.g., ‘-Oline’ or ‘--output-sync=recurse’).
This is the default: all output is sent directly as it is generated and no synchro-
nization is performed.
Output from each individual line of the recipe is grouped and printed as soon
as that line is complete. If a recipe consists of multiple lines, they may be
interspersed with lines from other recipes.
Output from the entire recipe for each target is grouped and printed once the
target is complete. This is the default if the --output-sync or -O option is
given with no argument.
Output from each recursive invocation of make is grouped and printed once the
recursive invocation is complete.
Regardless of the mode chosen, the totalbuildtime will be the same. The only diﬀerence
is in how the output appears.
The ‘target’and ‘recurse’ modes both collect the output of the entire recipe of a target
and display it uninterrupted when the recipe completes. The diﬀerence between them is in
how recipes that contain recursive invocations of make are treated(seeSection5.7[Recursive
Use of make], page 50). For r all l recipes which have no recursive lines, the ‘target’ and
‘recurse’ modes behave identically.
If the ‘recurse’ mode is chosen, recipes that contain recursive make invocations are
treated the same as other targets: the output from the recipe, including the output from
the recursive make, is saved and printed after the entire recipe is complete. This ensures
output from all the targets built by a given recursive make instance are grouped together,
which may make the output easier to understand. However it also leads to long periods of
time during the build where no output is seen, followed by large bursts of output. If you
are not watching the build as it proceeds, but instead viewing a log of the build after the
fact, this may be the best option for you.
If you are watching the output, the long gaps of quiet during the build can be frustrat-
ing. The ‘target’ output synchronization mode detects when make is going to be invoked
recursively, using the standard methods, and it will not synchronize the output of those
lines. The recursive make will perform the synchronization for its targets and the output
from each will be displayed immediately when it completes. Be aware that output from
recursive lines of the recipe are not synchronized (for example if the recursive line prints a
message before running make, that message will not be synchronized).
The ‘line’ mode can be useful for front-ends that are watching the output of make to
track when recipes are started and completed.
Some programs invokedby make may behave diﬀerently if they determine they’re writing
output to a terminal versus a ﬁle (often described as “interactive” vs. “non-interactive”
Chapter 5: Writing Recipes in Rules
modes). For example, many programs that can display colorized output will not do so
if they determine they are not writing to a terminal. If your makeﬁle invokes a program
like this then using the output synchronization options will cause the program to believe
it’s running in “non-interactive” mode even though the output will ultimately go to the
5.4.2 Input During Parallel Execution
Two processes cannot both take input from the same device at the same time. To make
sure that only one recipe tries to take input from the terminal at once, make will invalidate
the standard input streams of all but one running recipe. If another recipe attempts to read
from standard input it will usually incur a fatal error (a ‘Broken pipe’ signal).
It is unpredictable which recipe will have a valid standard input stream (which will come
from the terminal, or wherever you redirect the standard input of make). The ﬁrst recipe
run will always get it ﬁrst, and the ﬁrst recipe started after that one ﬁnishes will get it next,
and so on.
We will change how this aspect of make works if we ﬁnd a better alternative. In the
mean time, you should not rely on any recipe using standard input at all if you are using
the parallel execution feature; but if you are not using this feature, then standard input
works normally in all recipes.
5.5 Errors in Recipes
After each shell invocation returns, make looks at its exit status. If the shell completed
successfully (the exit status is zero), the next line in the recipe is executed in a new shell;
after the last line is ﬁnished, the rule is ﬁnished.
If there is an error (the exit status is nonzero), make gives up on the current rule, and
perhaps on all rules.
Sometimes the failure of a certain recipe line does not indicate a problem. For example,
you may use the mkdir command to ensure that a directory exists. If the directory already
exists, mkdir will report an error, but you probably want make to continue regardless.
To ignore errors in a recipe line, write a ‘-’ at the beginning of the line’s text (after the
initial tab). The ‘-’ is discarded before the line is passed to the shell for execution.
-rm -f *.o
This causes make to continue even if rm is unable to remove a ﬁle.
When you run make with the ‘-i’ or ‘--ignore-errors’ ﬂag, errors are ignored in all
recipes of all rules. A rule in the makeﬁle for the special target .IGNORE has the same eﬀect,
if there are no prerequisites. These ways of ignoring errors are obsolete because ‘-’ is more
When errors are to be ignored, because of either a ‘-’ or the ‘-i’ ﬂag, make treats an
error return just like success, except that it prints out a message that tells you the status
code the shell exited with, and says that the error has been ignored.
When an error happens that make has not been told to ignore, it implies that the
current target cannot be correctly remade, and neither can any other that depends on it
either directly or indirectly. No further recipes will be executed for these targets, since their
preconditions have not been achieved.
Normally make gives up immediately in this circumstance, returning a nonzero status.
However, if the ‘-k’ or ‘--keep-going’ ﬂag is speciﬁed, make continues to consider the
other prerequisites of the pending targets, remaking them if necessary, before it gives up
and returns nonzero status. For example, after an error in compiling one object ﬁle, ‘make
-k’ willcontinue compiling other object ﬁles eventhough it already knows that linking them
will be impossible. SeeSection9.7[SummaryofOptions],page104.
The usual behavior assumes that your purpose is to get the speciﬁed targets up to date;
once make learns that this is impossible, it might as well report the failure immediately.
The ‘-k’ option says that the real purpose is to test as many of the changes made in the
program as possible, perhaps to ﬁnd several independent problems so that you can correct
them all before the next attempt to compile. This is why Emacs’ compile command passes
the ‘-k’ ﬂag by default.
Usually when a recipe line fails, if it has changed the target ﬁle at all, the ﬁle is corrupted
and cannot be used—or at least it is not completely updated. Yet the ﬁle’s time stamp says
that it is now up to date, so the next time make runs, it will not try to update that ﬁle. The
situation is just the same as when the shell is killed by a signal; seeSection5.6[Interrupts],
beginning to change the ﬁle. make will do this if .DELETE_ON_ERROR appears as a target.
This is almost always what you want make to do, but it is not historical practice; so for
compatibility, you must explicitly request it.
5.6 Interrupting or Killing make
If make gets a fatal signal while a shell is executing, it may delete the target ﬁle that the
recipe was supposed to update. This is done if the target ﬁle’s last-modiﬁcation time has
changed since make ﬁrst checked it.
The purpose of deleting the target is to make sure that it is remade from scratch when
make is next run. Why is this? Suppose you type Ctrl-c while a compiler is running, and
it has begun to write an object ﬁle foo.o. The Ctrl-c kills the compiler, resulting in an
incomplete ﬁle whose last-modiﬁcation time is newer than the source ﬁle foo.c. But make
also receives the Ctrl-c signal and deletes this incomplete ﬁle. If make did not do this, the
next invocation of make would think that foo.o did not require updating—resulting in a
strange error message from the linker when it tries to link an object ﬁle half of which is
You can prevent the deletion of a target ﬁle in this way by making the special target
.PRECIOUS depend on it. Before remaking a target, make checks to see whether it appears
on the prerequisites of .PRECIOUS, and thereby decides whether the target should be deleted
if a signal happens. Some reasons why you might do this are that the target is updated
in some atomic fashion, or exists only to record a modiﬁcation-time (its contents do not
matter), or must exist at all times to prevent other sorts of trouble.
5.7 Recursive Use of make
Recursive use of make means using make as a command in a makeﬁle. This technique
is useful when you want separate makeﬁles for various subsystems that compose a larger
Documents you may be interested
Documents you may be interested