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.
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 |