3.4 When Variables Are Expanded

     

3.4 When Variables Are Expanded

In the previous sections, we began to get a taste of some of the subtleties of variable expansion. Results depend a lot on what was previously defined, and where. You could easily get results you don't want, even if make fails to find any error. So what are the rules for expanding variables? How does this really work?

When make runs, it performs its job in two phases. In the first phase, make reads the makefile and any included makefile s. At this time, variables and rules are loaded into make 's internal database and the dependency graph is created. In the second phase, make analyzes the dependency graph and determines the targets that need to be updated, then executes command scripts to perform the required updates.

When a recursive variable or define directive is processed by make , the lines in the variable or body of the macro are stored, including the newlines without being expanded. The very last newline of a macro definition is not stored as part of the macro. Otherwise, when the macro was expanded an extra newline would be read by make .

When a macro is expanded, the expanded text is then immediately scanned for further macro or variable references and those are expanded and so on, recursively. If the macro is expanded in the context of an action, each line of the macro is inserted with a leading tab character.

To summarize, here are the rules for when elements of a makefile are expanded:

  • For variable assignments, the lefthand side of the assignment is always expanded immediately when make reads the line during its first phase.

  • The righthand side of = and ?= are deferred until they are used in the second phase.

  • The righthand side of := is expanded immediately.

  • The righthand side of += is expanded immediately if the lefthand side was originally defined as a simple variable. Otherwise, its evaluation is deferred.

  • For macro definitions (those using define ), the macro variable name is immediately expanded and the body of the macro is deferred until used.

  • For rules, the targets and prerequisites are always immediately expanded while the commands are always deferred.

Chapter 3 summarizes what occurs when variables are expanded.

Table 3-1. Rules for immediate and deferred expansion

Definition

Expansion of a

Expansion of b

  a  =  b  

Immediate

Deferred

  a  ?=  b  

Immediate

Deferred

  a  :=  b  

Immediate

Immediate

  a  +=  b  

Immediate

Deferred or immediate

 define  ab  . . .  b  . . .  b  . . .  endef 

Immediate

Deferred


As a general rule, always define variables and macros before they are used. In particular, it is required that a variable used in a target or prerequisite be defined before its use.

An example will make all this clearer. Suppose we reimplement our free-space macro. We'll go over the example a piece at a time, then put them all together at the end.

 BIN    := /usr/bin PRINTF := $(BIN)/printf DF     := $(BIN)/df AWK    := $(BIN)/awk 

We define three variables to hold the names of the programs we use in our macro. To avoid code duplication we factor out the bin directory into a fourth variable. The four variable definitions are read and their righthand sides are immediately expanded because they are simple variables. Because BIN is defined before the others, its value can be plugged into their values.

Next, we define the free-space macro.

 define free-space   $(PRINTF) "Free disk space "   $(DF) .  $(AWK) 'NR =  = 2 { print $ }' endef 

The define directive is followed by a variable name that is immediately expanded. In this case, no expansion is necessary. The body of the macro is read and stored unexpanded.

Finally, we use our macro in a rule.

 OUTPUT_DIR := /tmp $(OUTPUT_DIR)/very_big_file:         $(free-space) 

When $(OUTPUT_DIR)/very_big_file is read, any variables used in the targets and prerequisites are immediately expanded. Here, $(OUTPUT_DIR) is expanded to /tmp to form the /tmp/very_big_file target. Next, the command script for this target is read. Command lines are recognized by the leading tab character and are read and stored, but not expanded.

Here is the entire example makefile . The order of elements in the file has been scrambled intentionally to illustrate make 's evaluation algorithm.

 OUTPUT_DIR := /tmp $(OUTPUT_DIR)/very_big_file:         $(free-space) define free-space   $(PRINTF) "Free disk space "   $(DF) .  $(AWK) 'NR =  = 2 { print $ }' endef BIN    := /usr/bin PRINTF := $(BIN)/printf DF     := $(BIN)/df AWK    := $(BIN)/awk 

Notice that although the order of lines in the makefile seems backward, it executes just fine. This is one of the surprising effects of recursive variables. It can be immensely useful and confusing at the same time. The reason this makefile works is that expansion of the command script and the body of the macro are deferred until they are actually used. Therefore, the relative order in which they occur is immaterial to the execution of the makefile .

In the second phase of processing, after the makefile is read, make identifies the targets, performs dependency analysis, and executes the actions for each rule. Here the only target, $(OUTPUT_DIR)/very_big_file , has no prerequisites, so make will simply execute the actions ( assuming the file doesn't exist). The command is $(free-space) . So make expands this as if the programmer had written:

 /tmp/very_big_file:         /usr/bin/printf "Free disk space "         /usr/bin/df .  /usr/bin/awk 'NR =  = 2 { print $ }' 

Once all variables are expanded, it begins executing commands one at a time.

Let's look at the two parts of the makefile where the order is important. As explained earlier, the target $(OUTPUT_DIR)/very_big_file is expanded immediately. If the definition of the variable OUTPUT_DIR had followed the rule, the expansion of the target would have yielded /very_big_file . Probably not what the user wanted. Similarly, if the definition of BIN had been moved after AWK , those three variables would have expanded to /printf , /df , and /awk because the use of := causes immediate evaluation of the righthand side of the assignment. However, in this case, we could avoid the problem for PRINTF , DF , and AWK by changing := to = , making them recursive variables.

One last detail. Notice that changing the definitions of OUTPUT_DIR and BIN to recursive variables would not change the effect of the previous ordering problems. The important issue is that when $(OUTPUT_DIR)/very_big_file and the righthand sides of PRINTF , DF , and AWK are expanded, their expansion happens immediately, so the variables they refer to must be already defined.



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

Similar book on Amazon

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