[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7 Recursive Use of make

Recursive use of make means using make as a command in a makefile. This technique is useful when you want separate makefiles for various subsystems that compose a larger system. For example, suppose you have a subdirectory ‘subdir’ which has its own makefile, and you would like the containing directory’s makefile to run make on the subdirectory. You can do it by writing this:

 
subsystem:
        cd subdir && $(MAKE)

or, equivalently, this (see section Summary of Options):

 
subsystem:
        $(MAKE) -C subdir

You can write recursive make commands just by copying this example, but there are many things to know about how they work and why, and about how the sub-make relates to the top-level make. You may also find it useful to declare targets that invoke recursive make commands as ‘.PHONY’ (for more discussion on when this is useful, see Phony Targets).

For your convenience, when GNU make starts (after it has processed any -C options) it sets the variable CURDIR to the pathname of the current working directory. This value is never touched by make again: in particular note that if you include files from other directories the value of CURDIR does not change. The value has the same precedence it would have if it were set in the makefile (by default, an environment variable CURDIR will not override this value). Note that setting this variable has no impact on the operation of make (it does not cause make to change its working directory, for example).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7.1 How the MAKE Variable Works

Recursive make commands should always use the variable MAKE, not the explicit command name ‘make’, as shown here:

 
subsystem:
        cd subdir && $(MAKE)

The value of this variable is the file name with which make was invoked. If this file name was ‘/bin/make’, then the recipe executed is ‘cd subdir && /bin/make’. If you use a special version of make to run the top-level makefile, the same special version will be executed for recursive invocations.

As a special feature, using the variable MAKE in the recipe of a rule alters the effects of the ‘-t’ (‘--touch’), ‘-n’ (‘--just-print’), or ‘-q’ (‘--question’) option. Using the MAKE variable has the same effect as using a ‘+’ character at the beginning of the recipe line. See section Instead of Executing the Recipes. This special feature is only enabled if the MAKE variable appears directly in the recipe: it does not apply if the MAKE variable is referenced through expansion of another variable. In the latter case you must use the ‘+’ token to get these special effects.

Consider the command ‘make -t’ in the above example. (The ‘-t’ option marks targets as up to date without actually running any recipes; see Instead of Executing Recipes.) Following the usual definition of ‘-t’, a ‘make -t’ command in the example would create a file named ‘subsystem’ and do nothing else. What you really want it to do is run ‘cd subdir && make -t’; but that would require executing the recipe, and ‘-t’ says not to execute recipes.

The special feature makes this do what you want: whenever a recipe line of a rule contains the variable MAKE, the flags ‘-t’, ‘-n’ and ‘-q’ do not apply to that line. Recipe lines containing MAKE are executed normally despite the presence of a flag that causes most recipes not to be run. The usual MAKEFLAGS mechanism passes the flags to the sub-make (see section Communicating Options to a Sub-make), so your request to touch the files, or print the recipes, is propagated to the subsystem.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7.2 Communicating Variables to a Sub-make

Variable values of the top-level make can be passed to the sub-make through the environment by explicit request. These variables are defined in the sub-make as defaults, but do not override what is specified in the makefile used by the sub-make makefile unless you use the ‘-e’ switch (see section Summary of Options).

To pass down, or export, a variable, make adds the variable and its value to the environment for running each line of the recipe. The sub-make, in turn, uses the environment to initialize its table of variable values. See section Variables from the Environment.

Except by explicit request, make exports a variable only if it is either defined in the environment initially or set on the command line, and if its name consists only of letters, numbers, and underscores. Some shells cannot cope with environment variable names consisting of characters other than letters, numbers, and underscores.

The value of the make variable SHELL is not exported. Instead, the value of the SHELL variable from the invoking environment is passed to the sub-make. You can force make to export its value for SHELL by using the export directive, described below. See section Choosing the Shell.

The special variable MAKEFLAGS is always exported (unless you unexport it). MAKEFILES is exported if you set it to anything.

make automatically passes down variable values that were defined on the command line, by putting them in the MAKEFLAGS variable. See section Communicating Options to a Sub-make.

Variables are not normally passed down if they were created by default by make (see section Variables Used by Implicit Rules). The sub-make will define these for itself.

If you want to export specific variables to a sub-make, use the export directive, like this:

 
export variable

If you want to prevent a variable from being exported, use the unexport directive, like this:

 
unexport variable

In both of these forms, the arguments to export and unexport are expanded, and so could be variables or functions which expand to a (list of) variable names to be (un)exported.

As a convenience, you can define a variable and export it at the same time by doing:

 
export variable = value

has the same result as:

 
variable = value
export variable

and

 
export variable := value

has the same result as:

 
variable := value
export variable

Likewise,

 
export variable += value

is just like:

 
variable += value
export variable

See section Appending More Text to Variables.

You may notice that the export and unexport directives work in make in the same way they work in the shell, sh.

If you want all variables to be exported by default, you can use export by itself:

 
export

This tells make that variables which are not explicitly mentioned in an export or unexport directive should be exported. Any variable given in an unexport directive will still not be exported. If you use export by itself to export variables by default, variables whose names contain characters other than alphanumerics and underscores will not be exported unless specifically mentioned in an export directive.

The behavior elicited by an export directive by itself was the default in older versions of GNU make. If your makefiles depend on this behavior and you want to be compatible with old versions of make, you can write a rule for the special target .EXPORT_ALL_VARIABLES instead of using the export directive. This will be ignored by old makes, while the export directive will cause a syntax error.

Likewise, you can use unexport by itself to tell make not to export variables by default. Since this is the default behavior, you would only need to do this if export had been used by itself earlier (in an included makefile, perhaps). You cannot use export and unexport by themselves to have variables exported for some recipes and not for others. The last export or unexport directive that appears by itself determines the behavior for the entire run of make.

As a special feature, the variable MAKELEVEL is changed when it is passed down from level to level. This variable’s value is a string which is the depth of the level as a decimal number. The value is ‘0’ for the top-level make; ‘1’ for a sub-make, ‘2’ for a sub-sub-make, and so on. The incrementation happens when make sets up the environment for a recipe.

The main use of MAKELEVEL is to test it in a conditional directive (see section Conditional Parts of Makefiles); this way you can write a makefile that behaves one way if run recursively and another way if run directly by you.

You can use the variable MAKEFILES to cause all sub-make commands to use additional makefiles. The value of MAKEFILES is a whitespace-separated list of file names. This variable, if defined in the outer-level makefile, is passed down through the environment; then it serves as a list of extra makefiles for the sub-make to read before the usual or specified ones. See section The Variable MAKEFILES.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7.3 Communicating Options to a Sub-make

Flags such as ‘-s’ and ‘-k’ are passed automatically to the sub-make through the variable MAKEFLAGS. This variable is set up automatically by make to contain the flag letters that make received. Thus, if you do ‘make -ks’ then MAKEFLAGS gets the value ‘ks’.

As a consequence, every sub-make gets a value for MAKEFLAGS in its environment. In response, it takes the flags from that value and processes them as if they had been given as arguments. See section Summary of Options.

Likewise variables defined on the command line are passed to the sub-make through MAKEFLAGS. Words in the value of MAKEFLAGS that contain ‘=’, make treats as variable definitions just as if they appeared on the command line. See section Overriding Variables.

The options ‘-C’, ‘-f’, ‘-o’, and ‘-W’ are not put into MAKEFLAGS; these options are not passed down.

The ‘-j’ option is a special case (see section Parallel Execution). If you set it to some numeric value ‘N’ and your operating system supports it (most any UNIX system will; others typically won’t), the parent make and all the sub-makes will communicate to ensure that there are only ‘N’ jobs running at the same time between them all. Note that any job that is marked recursive (see section Instead of Executing Recipes) doesn’t count against the total jobs (otherwise we could get ‘N’ sub-makes running and have no slots left over for any real work!)

If your operating system doesn’t support the above communication, then ‘-j 1’ is always put into MAKEFLAGS instead of the value you specified. This is because if the ‘-j’ option were passed down to sub-makes, you would get many more jobs running in parallel than you asked for. If you give ‘-j’ with no numeric argument, meaning to run as many jobs as possible in parallel, this is passed down, since multiple infinities are no more than one.

If you do not want to pass the other flags down, you must change the value of MAKEFLAGS, like this:

 
subsystem:
        cd subdir && $(MAKE) MAKEFLAGS=

The command line variable definitions really appear in the variable MAKEOVERRIDES, and MAKEFLAGS contains a reference to this variable. If you do want to pass flags down normally, but don’t want to pass down the command line variable definitions, you can reset MAKEOVERRIDES to empty, like this:

 
MAKEOVERRIDES =

This is not usually useful to do. However, some systems have a small fixed limit on the size of the environment, and putting so much information into the value of MAKEFLAGS can exceed it. If you see the error message ‘Arg list too long’, this may be the problem. (For strict compliance with POSIX.2, changing MAKEOVERRIDES does not affect MAKEFLAGS if the special target ‘.POSIX’ appears in the makefile. You probably do not care about this.)

A similar variable MFLAGS exists also, for historical compatibility. It has the same value as MAKEFLAGS except that it does not contain the command line variable definitions, and it always begins with a hyphen unless it is empty (MAKEFLAGS begins with a hyphen only when it begins with an option that has no single-letter version, such as ‘--warn-undefined-variables’). MFLAGS was traditionally used explicitly in the recursive make command, like this:

 
subsystem:
        cd subdir && $(MAKE) $(MFLAGS)

but now MAKEFLAGS makes this usage redundant. If you want your makefiles to be compatible with old make programs, use this technique; it will work fine with more modern make versions too.

The MAKEFLAGS variable can also be useful if you want to have certain options, such as ‘-k’ (see section Summary of Options), set each time you run make. You simply put a value for MAKEFLAGS in your environment. You can also set MAKEFLAGS in a makefile, to specify additional flags that should also be in effect for that makefile. (Note that you cannot use MFLAGS this way. That variable is set only for compatibility; make does not interpret a value you set for it in any way.)

When make interprets the value of MAKEFLAGS (either from the environment or from a makefile), it first prepends a hyphen if the value does not already begin with one. Then it chops the value into words separated by blanks, and parses these words as if they were options given on the command line (except that ‘-C’, ‘-f’, ‘-h’, ‘-o’, ‘-W’, and their long-named versions are ignored; and there is no error for an invalid option).

If you do put MAKEFLAGS in your environment, you should be sure not to include any options that will drastically affect the actions of make and undermine the purpose of makefiles and of make itself. For instance, the ‘-t’, ‘-n’, and ‘-q’ options, if put in one of these variables, could have disastrous consequences and would certainly have at least surprising and probably annoying effects.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7.4 The ‘--print-directory’ Option

If you use several levels of recursive make invocations, the ‘-w’ or ‘--print-directory’ option can make the output a lot easier to understand by showing each directory as make starts processing it and as make finishes processing it. For example, if ‘make -w’ is run in the directory ‘/u/gnu/make’, make will print a line of the form:

 
make: Entering directory `/u/gnu/make'.

before doing anything else, and a line of the form:

 
make: Leaving directory `/u/gnu/make'.

when processing is completed.

Normally, you do not need to specify this option because ‘make’ does it for you: ‘-w’ is turned on automatically when you use the ‘-C’ option, and in sub-makes. make will not automatically turn on ‘-w’ if you also use ‘-s’, which says to be silent, or if you use ‘--no-print-directory’ to explicitly disable it.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Davide Tacchella on November 3, 2010 using texi2html 1.82.