Programming Utilities Guide

Passing Parameters to Nested make Commands

With the exception of MAKEFLAGS, make imports variables from the environment and treats them as if they were defined macros. In turn, make propagates those environment variables and their values to commands it invokes, including nested make commands.


Note -

The SHELL environment variable is neither imported nor exported to this version of make.


Macros can be defined as command-line arguments, as well as the makefile. This can lead to name-value conflicts when a macro is defined in more than one place, and make has a fairly complicated precedence rule for resolving them.

First, conditional macro definitions always take effect within the targets (and their dependencies) for which they are defined.

If make is invoked with a macro-definition argument, that definition takes precedence over definitions given either within the makefile, or imported from the environment. (This does not necessarily hold true for nested make commands, however.) Otherwise, if you define (or redefine) a macro within the makefile, the most recent definition applies. The latest definition normally overrides the environment.

Lastly, if the macro is defined in the default file and nowhere else, that value is used.

With nested make commands, definitions made in the makefile normally override the environment, but only for the makefile in which each definition occurs; the value of the corresponding environment variable is propagated regardless.

Command-line definitions override both environment and makefile definitions, but only in the make run for which they are supplied. Although values from the command line are propagated to nested make commands, they are overridden both by definitions in the nested makefiles, and by environment variables imported by the nested make commands.

The -e option behaves more consistently. The environment overrides macro definitions made in any makefile, and command-line definitions are always used ahead of definitions in the makefile and the environment. One drawback to -e is that it introduces a situation in which information that is not contained in the makefile can be critical to the success or failure of a build.

To avoid these complications, when you want to pass a specific value to an entire hierarchy of make commands, run make -e in a subshell with the environment set properly (in the C shell):

% (unsetenv MAKEFLAGS LDFLAGS; setenv CFLAGS -g; make -e)

If you want to test the cases yourself, you can use the following makefiles to illustrate the various cases.

# top.mk 

MACRO= "Correct but unexpected." 

top: 
     	@echo "------------------------------ top"   
     	echo $(MACRO) 
     	@echo "------------------------------"  
   	  $(MAKE) -f nested.mk 
     	@echo "------------------------------ clean" 
clean: 
     	rm nested
# nested.mk 

MACRO=nested 

nested: 
        	@echo "------------------------------ nested" 
        	touch nested 
        	echo $(MACRO) 
        	$(MAKE) -f top.mk 
        	$(MAKE) -f top.mk clean

The following is a summary of macro assignment orders:

Table 4-16 Summary of Macro Assignment Order

Without -e 

With -e in effect 

top-level make commands: 

Conditional definitions  

Conditional definitions  

Make command line 

Make command line 

Latest makefile definition 

Environment value  

Environment value  

Latest makefile definition  

Predefined value, if any 

Predefined value, if any  

nested make commands: 

Conditional definitions  

Conditional definitions  

Make command line  

Make command line  

Latest makefile definition 

Parent make cmd. line  

Environment variable  

Environment value  

Predefined value, if any 

Latest makefile definition  

Parent make cmd. line 

Predefined value, if any