3.6 Where Variables Come From


3.6 Where Variables Come From

So far, most variables have been defined explicitly in our own makefile s, but variables can have a more complex ancestry. For instance, we have seen that variables can be defined on the make command line. In fact, make variables can come from these sources:


Of course, variables can be defined in the makefile or a file included by the makefile (we'll cover the include directive shortly).

Command line

Variables can be defined or redefined directly from the make command line:


A command-line argument containing an = is a variable assignment. Each variable assignment on the command line must be a single-shell argument. If the value of the variable (or heaven forbid , the variable itself) contains spaces, the argument must be surrounded by quotes or the spaces must be escaped.

An assignment of a variable on the command line overrides any value from the environment and any assignment in the makefile . Command-line assignments can set either simple or recursive variables by using := or = , respectively. It is possible using the override directive to allow a makefile assignment to be used instead of a command-line assignment.

 # Use big-endian objects or the program crashes! override LDFLAGS = -EB 

Of course, you should ignore a user 's explicit assignment request only under the most urgent circumstances (unless you just want to irritate your users).


All the variables from your environment are automatically defined as make variables when make starts. These variables have very low precedence, so assignments within the makefile or command-line arguments will override the value of an environment variable. You can cause environment variables to override makefile variables using the ”environment-overrides (or -e ) command-line option.

When make is invoked recursively, some variables from the parent make are passed through the environment to the child make . By default, only those variables that originally came from the environment are exported to the child's environment, but any variable can be exported to the environment by using the export directive:

 export CLASSPATH := $(HOME)/classes:$(PROJECT)/classes SHELLOPTS = -x export SHELLOPTS 

You can cause all variables to be exported with:


Note that make will export even those variables whose names contain invalid shell variable characters . For example:

 export valid-variable-in-make = Neat! show-vars:         env  grep '^valid-'         valid_variable_in_shell=Great         invalid-variable-in-shell=Sorry $ make env  grep '^valid-' valid-variable-in-make=Neat! valid_variable_in_shell=Great invalid-variable-in-shell=Sorry /bin/sh: line 1: invalid-variable-in-shell=Sorry: command not found make: *** [show-vars] Error 127 

An "invalid" shell variable was created by exporting valid-variable-in-make . This variable is not accessible through normal shell syntax, only through trickery such as running grep over the environment. Nevertheless, this variable is inherited by any sub- make where it is valid and accessible. We will cover use of "recursive" make in Part II.

You can also prevent an environment variable from being exported to the sub-process:

 unexport DISPLAY 

The export and unexport directives work the same way their counterparts in sh work.

The conditional assignment operator interacts very nicely with environment variables. Suppose you have a default output directory set in your makefile , but you want users to be able to override the default easily. Conditional assignment is perfect for this situation:

 # Assume the output directory $(PROJECT_DIR)/out. OUTPUT_DIR ?= $(PROJECT_DIR)/out 

Here the assignment is performed only if OUTPUT_DIR has never been set. We can get nearly the same effect more verbosely with:

 ifndef OUTPUT_DIR   # Assume the output directory $(PROJECT_DIR)/out.   OUTPUT_DIR = $(PROJECT_DIR)/out endif 

The difference is that the conditional assignment operator will skip the assignment if the variable has been set in any way, even to the empty value, while the ifdef and ifndef operators test for a nonempty value. Thus, OUTPUT_DIR= is considered set by the conditional operator but not defined by ifdef .

It is important to note that excessive use of environment variables makes your makefile s much less portable, since other users are not likely to have the same set of environment variables. In fact, I rarely use this feature for precisely that reason.


Finally, make creates automatic variables immediately before executing the command script of a rule.

Traditionally, environment variables are used to help manage the differences between developer machines. For instance, it is common to create a development environment (source code, compiled output tree, and tools) based on environment variables referenced in the makefile . The makefile would refer to one environment variable for the root of each tree. If the source file tree is referenced from a variable PROJECT_SRC , binary output files from PROJECT_BIN , and libraries from PROJECT_LIB , then developers are free to place these trees wherever is appropriate.

A potential problem with this approach (and with the use of environment variables in general) occurs when these "root" variables are not set. One solution is to provide default values in the makefile using the $? form of assignment:

 PROJECT_SRC ?= /dev/$(USER)/src PROJECT_BIN ?= $(patsubst %/src,%/bin,$(PROJECT_SRC)) PROJECT_LIB ?= /net/server/project/lib 

By using these variables to access project components , you can create a development environment that is adaptable to varying machine layouts. (We will see more comprehensive examples of this in Part II.) Beware of overreliance on environment variables, however. Generally, a makefile should be able to run with a minimum of support from the developer's environment so be sure to provide reasonable defaults and check for the existence of critical components.

Managing Projects with GNU make
Managing Projects with GNU Make (Nutshell Handbooks)
ISBN: 0596006101
EAN: 2147483647
Year: 2003
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net