• make is sort of two languages in one:
    • The first language describes dependency graphs consisting of targets and prerequisites.
    • The second language is a macro language for performing textual substitution.
  • The only characters actually disallowed in a variable name are :, #, and =.
  • To get the value of a variable, enclose the variable name in $() or ${}, but single-letter variable names can omit the parentheses.
  • The value of a variable consists of all the words to the right of the assignment symbol with leading space trimmed. Trailing spaces are not trimmed.
3.1 What Variables Are Used For
  • In general it is a good idea to use variables to represent external programs. This allows users of the makefile to more easily adapt the makefile to their specific environment.
  • Variables can also store user-defined command sequences.
3.2 Variable Types
  • A simply expanded variable (or a simple variable) is defined using the := assignment operator:
MAKE_DEPEND := $(CC) –M
  • It is called "simply expanded" because its righthand side is expanded immediately upon reading the line from the makefile. Any make variable references in the righthand side are expanded and the resulting text saved as the value of the variable.
  • If CC above had not yet been set, then the value of the above assignment would be:
<space>-M
  • A recursively expanded variable (or a recursive variable, lazily expanded variable) is defined using the = assignment operator:
MAKE_DEPEND = $(CC) –M
  • It is called "recursively expanded" because its righthand side is simply stored as the value of the variable without evaluating or expanding it in any way, the expansion is performed when the variable is used.
  • One surprising effect of this style of expansion is that assignments can be performed "out of order".
  • Each time the recursive variable is used, its righthand side is re-evaluated.
  • The ?= operator is called the conditional variable assignment operator (conditional assignment) This operator will perform the requested variable assignment only if the variable does not yet have a value:
OUTPUT_DIR ?= $(PROJECT_DIR)/out
  • Here we set the output directory variable, OUTPUT_DIR, only if it hasn't been set earlier.
  • The append operator (+=) appends text to a variable.
  • The += operator might be implemented like this:
simple := $(simple) new stuff
    • make can expand $(simple), append the text, and finish the assignment.
3.3 Macros
  • A macro is just another way of defining a variable in make.
  • GNU make uses define directive to define a macro.
  • The GNU make manual seems to use the words variable and macro interchangeably.
  • An example:
define create-jar  /* The define directive is followed by the variable name and a newline. */
           @echo Creating $@...
           $(RM) $(TMP_JAR_DIR)        /* rm -f */
           $(MKDIR) $(TMP_JAR_DIR) /* mkdir -p */
           $(CP) -r $^ $(TMP_JAR_DIR)
           cd $(TMP_JAR_DIR) && $(JAR) $(JARFLAGS) $@ .
           $(JAR) -ufm $@ $(MANIFEST)
           $(RM) $(TMP_JAR_DIR)
endef
  • Command lines prefixed with an @ character are not echoed by make when the command is executed.
3.4 When Variables Are Expanded
  • When make runs, it performs its job in two phases.
    • In the first phase, make reads the makefile and any included makefiles. 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.
  • 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.
  • 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 (Command lines are recognized by the leading tab character and are read and stored, but not 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 of immediate

define ab…

b…

b…

endef

Immediate

Deferred

  • Always define variables and macros before they are used.
3.5 Target- and Pattern-Specific Variables
  • Variables usually have only one value during the execution of a makefile. This is ensured by the two-phase nature of makefile processing.
  • make provides target-specific variables, these are variable definitions attached to a target that are valid only during the processing of that target and any of its prerequisites.
gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1
gui.o: gui.h
    • While the gui.o target is being processed, the value of CPPFLAGS will contain -DUSE_NEW_MALLOC=1 in addition to its original contents. When the gui.o target is finished, CPPFLAGS will revert to its original value.
  • The general syntax for target-specific variables is:
    • target...: variable = value
    • target...: variable := value
    • target...: variable += value
    • target...: variable ?= value
  • The variable does not need to exist before the assignment.
  • The variable assignment is not actually performed until the processing of the target begins. So the righthand side of the assignment can itself be a value set in another target-specific variable.
  • The variable is valid during the processing of all prerequisites as well.
3.6 Where Variables Come From
  • make variables can come from these 4 sources:
    • File: variables can be defined in the makefile or a file included by the makefile.
    • Command line: Variables can be defined or redefined directly from the make command line:
$ make CFLAGS=-g CPPFLAGS='-DBSD -DDEBUG'
      • A command-line argument containing an = (or :=) is a variable assignment.
      • Each variable assignment on the command line must be a single-shell argument. If the value of the variable (or 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.
      • Use the override directive in the makefile can override the command-line assignment.
override LDFLAGS = -EB
    • Environment: 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.
      • Use --environment-overrides (or -e) can force environment variables override makefile variables.
      • 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
      • Export all variables:
export
      • make will export even those variables whose names contain invalid shell variable characters.
      • prevent an environment variable from being exported to the sub-process:
unexport DISPLAY
      • Compare 2 conditional assignment, 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.
        • OUTPUT_DIR ?= $(PROJECT_DIR)/out
        • ifndef OUTPUT_DIR
              
          OUTPUT_DIR = $(PROJECT_DIR)/out
          endif
    • Automatic: make creates automatic variables immediately before executing the command script of a rule.
3.7 Conditional and include Processing
  • Parts of a makefile can be omitted or selected while the makefile is being read using conditional processing directives.
if-condition                                            /* do not put a leading tab */
           text if the condition is true
else                                                        /* do not put a leading tab */
           text if the condition is false
endif                                                       /* do not put a leading tab */
  • The if-condition can be one of:
    • ifdef  variable-name
    • ifndef variable-name
    • ifeq  test
    • ifneq test
  • The variable-name should not be surrounded by $( ) for the ifdef/ifndef test.
  • The test can be expressed as either of:
    • "a" "b"          /* single or double quotes can be used interchangeably, but the quotes must match */
    • (a,b)
  • The conditional processing directives can be used within macro definitions and command scripts as well as at the top level of makefiles.
  • The ifeq and ifneq conditionals test if their arguments are equal or not equal, when using the parenthesis form of the test, whitespace after the comma is ignored, but all other whitespace is significant:
ifeq (a, a)    /* use “a” “a” or ‘a’ ‘a’ instead */
           # These are equal
endif
ifeq ( b, b )
           # These are not equal - ' b' != 'b '
endif
  • Or, use the strip function:
ifeq "$(strip $(OPTIONS)) "-d"
           COMPILATION_FLAGS += -DDEBUG
endif
  • A makefile can include other files. The directive can be given any number of files and shell wildcards and make variables are also allowed.
include definitions.mk
  • When make encounters an include directive, it expands the wildcards and variable references, then tries to read the include file.
  • If the file does not exist, however, make reports the problem and continues reading the rest of the makefile. When all reading is complete, make looks in the rules database for any rule to update the include files. If a match is found, make follows the normal process for updating a target. If any of the include files is updated by a rule, make then clears its internal database and rereads the entire makefile.
  • If, after completing the process of reading, updating, and rereading, there are still include directives that have failed due to missing files, make terminates with an error status.
  • make can treat the makefile itself as a possible target.
  • Where does make look for included files? the argument that include directive indicated, directories assigned on the command line by --include-dir (or -I) option, make’s compiled search path.
  • Add a leading dash to the include directive and make will ignore include files it cannot load.
-include i-may-not-exist.mk
  • For compatibility with other makes, the word sinclude is an alias for -include.
3.8 Standard make Variables
  • In addition to automatic variables, make maintains variables revealing bits and pieces of its own state as well as variables for customizing built-in rules.
  • MAKE_VERSION: the version number of GNU make.
  • CURDIR: This variable contains the current working directory (cwd) of the executing make process. This will be the same directory the make program was executed from (and it will be the same as the shell variable PWD), unless the --directory (-C) option is used.
  • The --directory=directory-name option instructs make to change to a different directory before searching for any makefile.
  • If --directory is used, CURDIR will contain the directory argument to --include-dir.
  • Within the makefile, all paths are relative to the makefile directory. Absolute paths are occasionally required and these are accessed using CURDIR.
  • MAKEFILE_LIST: This variable contains a list of each file make has read including the default makefile and makefiles specified on the command line or through include directives. Just before each file is read, the name is appended to the MAKEFILE_LIST variable.
  • MAKECMDGOALS: The MAKECMDGOALS variable contains a list of all the targets specified on the command line for the current execution of make. It does not include command-line options or variable assignments.
  • MAKECMDGOALS is typically used when a target requires special handling.
ifneq "$(MAKECMDGOALS)" "clean"
           -include $(subst .xml,.d,$(xml_src))
endif
  • .VARIABLES: This contains a list of the names of all the variables defined in makefiles read so far, with the exception of target-specific variables. The variable is read-only and any assignment to it is ignored.
  • Variables are also used to customize the implicit rules built in to make.
  • The variables have the basic form: ACTION.suffix. The ACTION is COMPILE for creating an object file, LINK for creating an executable, or the "special" operations PREPROCESS, YACC, LEX for running the C preprocessor, yacc, or lex, respectively.
  • The suffix indicates the source file type.
%.o: %.C
           $(COMPILE.C) $(OUTPUT_OPTION) $<
%: %.o
           $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
COMPILE.C = $(COMPILE.cc)
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) –c
CXX = g++
OUTPUT_OPTION = -o $@
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
CC = gcc
  • The variables CXXFLAGS, CPPFLAGS, and TARGET_ARCH have no default value. The LDFLAGS variable holds options for linking such as -L flags. The LOADLIBES and LDLIBS variables contain lists of libraries to link against. Two variables are included mostly for portability.














arrow
arrow
    全站熱搜

    nix 發表在 痞客邦 留言(0) 人氣()