makefile变量

makefile 变量与宏

变量和宏其实说的是同一东西。一个变量的内容是一个字符串,从一个变量名得到变量内容的过程叫作变量的扩展,用$()或者${}扩住变量名便可。而不想编程语言那样,使用变量名就能引用变量的值。shell

变量的类型

make的变量有两种:简易变量和递归扩展的变量。变量的定义是一个赋值动做,把等号右边的内容赋给左边。这里等号能够有多种::=、=、?=,他们决定了怎样赋值。等号两边的东西能够只是字面值,或者含有变量。赋值时,变量名须要是明确的,等号左边的内容当即扩展(没有变量就保持不变),右边的内容根据赋值符号决定什么时候扩展。数据库

简易变量

:=或者::=赋值运算符定义的是一个简易扩展的变量。一旦make读入该变量的定义语句,赋值运算符右边部分会马上扩展,而扩展后的文本会被存储成该变量的值。变量名和变量内容加入到数据库。
MAKE_DEPEND := $(CC) -M
此变量通常被扩展为
gcc -M
然而,若是CC变量还没有定义,则扩展为:
<space>-M
变量没有定义不算错误。编程

递归变量

=定义的变量。或者define定义的变量。
make只会读进赋值运算符后边的部分,并将之存储成该变量的值,但不会进行任何扩展的动做,扩展的动做会被延迟到该变量被使用的时候进行。编程语言

其余赋值类型

make还提供了另外两种赋值运算符:?=+=ide

?= 运算符称为附带条件的变量赋值运算符。此运算符只会在变量的值尚不存在是进行复制动做。
+= 运算符称为附加运算符。此运算符会将文本附加到变量里。对递归变量仍有用。
对于简单变量,等效于
simple := $(simple) new stuff
然而,对于递归变量
recursive = $(recursive) new stuff
这种表达式是非法的,会被无限扩展。要想将某段文本附加到递归变量上,就须要附加运算符了。ui

工做目标与模式的专属变量

make提供了工做目标的专属变量。这些变量的定义会附加在工做目标上,且只有在该工做目标以及相应的必要条件被处理的时候,他们才会发生做用spa

工做目标的专属变量语法以下:命令行

target...: variable = value
target...: variable := value
target...: variable ?= value
target...: variable += value

若是在编译某个源文件的时候须要单独指定一个宏定义,然而该文件又在某个模式规则中:code

gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1
gui.o: gui.h

当make处理gui.o这个工做目标时,CPPFLAGS这个变量会附加-DUSE_NEW_MALLOC=1,当处理完gui.o这个目标以后,CPPFLAGS会恢复它原来的值。递归

变量的来源

文件

变量能够被定义在makefile中,或是被makefile引入(include指令)

命令行

能够直接在make命令行上定义或者从新定义变量: $ make CFLAG=-g CPPFLAGS='DBSD -DDEBUG'
每一个命令行参数中所包含的等号,都是一个变量赋值运算符。在命令行上,每一个变量赋值运算符的右边部分必须是一个单独的shell参数。若是变量的值含有空格,则必须为参数加上括号或是引号。
命令行上变量的赋值将会覆盖掉环境变量以及makefile中的赋值结果。若是要使makefile中的变量覆盖命令行中的变量,能够在makefile中的变量前加override指令。

环境

当make启动时,全部来自环境的变量都会被定义为make的变量。这些变量具备很是低的优先级,makefile文件或命令行参数的赋值结果都会覆盖环境变量的值。可是,可使用--environment-overrides(或-e)命令行选项,让环境变量覆盖相应的makefile变量。
当make被递归调用时,有若干来自上层make的变量会经过环境传递给下层的make。默认只有原来就来自环境的变量会被导出到下层的环境中。可使用export指令导出任何变量。

自动建立

make会在执行一个规则的命令脚本以前当即建立自动变量。注意自动变量建立的时机。

在makefile中定义变量

variable := value

variable = value

variable ?= value

define variable =
...
...
endef
define variable :=
...
...
endef

define的特长是能够定义多行内容的变量。

一个变量的值由赋值符号右边除去前导空格的全部字符组成。跟在全部字以后的空格不会被删除。这有时会致使问题。

宏是之前对变量的另外一种称呼。
能够经过define指令建立“封装命令序列”,称为宏。在make中,宏只是用来定义变量的另外一种形式,此变量还能够包含换行符。通常,将由define定义的变量称为宏,由赋值运算符定义的变量称为变量。

define后跟着变量名和换行,变量的主体是由跳格符开头的命令行,最后以endef结尾。

define create-jar
    @echo Creating $@...
    $(RM) $(TMP_JAR_DIR)
    $(MKDIR) $(TMP_JAR_DIR)
    $(CP) -r $^ $(TMP_JAR_DIR)
    cd $(TMP_JAR_DIR) && $(JAR) $(JARFLAGS) $@ .
    $(JAR) -ufm $@ $(MANIFEST)
    $(RM) $(TMP_JAR_DIR)
endef

@的做用:make将每条命令交给shell执行以前都会打印出此条命令,在该命令以前加@可使make不这样作。若是在命令中应用了一个宏,使用@将使整个宏扩展后的命令以前都加上@。

当make运行时,它会以两个阶段来完成他的工做。第一阶段,make读进makefile以及被引入的任何其余makefile。这时,其中所定义的变量会被加载到make的内部数据库,并创建依存图。第二阶段,make分析依存图并判断须要更新的目标,而后执行脚本。

当make在处理递归变量或者define指令的时候,会将变量里的每一行或宏的主体存储起来,包括换行符号,但不会予以扩展。宏定义的最后一个换行符不会做为宏的一部分,不然,宏被扩展时会多一个换行。
当宏被扩展时,make会当即扫描被扩展的文本中是否存在宏或变量的引用,若是存在就予以扩展,如此递归下去。若是宏是在命令脚本里被扩展的,则宏的主体的每一行都会被插入一个跳格符。

下面是makefile中的元素什么时候被扩展的原则:

  • 对于变量赋值,make会在第一阶段读取该行时,当即扩展赋值运算符左边的部分。
  • =?=的右边会被延后到他们被使用时扩展,而且在第二阶段运行。
  • :=右边的部分会被当即扩展
  • 若是+=的左边部分本来被定义成一个简单变量,+=的右边就会被当即扩展,不然,求值动做就会延后。
  • 对于宏定义,宏的变量名会被当即扩展,宏的主体延后扩展。
  • 对于规则,工做目标和必要条件老是被当即扩展,而命令老是延后扩展。

延后扩展发生在它所在的表达式须要被扩展时,好比在规则的目标和必要条件中、在一个将要执行的命令中或者出如今简易变量赋值的右边等等。

OUTPUT_DIR := /tmp

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

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

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

说明:

第一阶段:make逐行读取makefile并将变量加入内部数据库,创建依存图。
OUTPUT_DIR是简单变量,它的值就是普通的字面值(若是这里有$引用的变量,将会进行扩展动做),放到数据库中。
接下来是一条规则,规则的目标和条件都是当即扩展的,而命令是延后扩展的,保持不变。因此这条规则变为:

/tmp/very_big_file:
    $(free-space)

以后是一个宏定义,宏名是当即扩展的,这里只是字面值,不用扩展。宏体是延后扩展的,在使用该宏的时候才扩展。
最后4个简易变量都是直接扩展的,将变量值加入到数据库中。

第二阶段:
按照后序遍历规则树进行规则的执行动做。这时要使用规则中的命令部分,对命令中的变量和宏进行扩展,并执行命令。

自动变量

自动变量是一种make在处理规则时自动赋值的变量。

变量名 描述
$@ 工做目标的文件名
$% 档案文件成员结构中的文件名元素
$< 第一个必要条件的文件名
$? 时间戳在工做目标以后的全部必要条件,并以空格隔开。
$^ 全部必要条件的文件名,并以空格隔开。
$+ 如同$^,表明全部必要条件的文件名,并以空格隔开。不过$+包含重复的文件名。
$* 工做目标的主文件名。文件名由主文件名和扩展名构成。

说明: 档案文件中个别的成员可做为工做目标或必要条件。能够经过archive(member)这样的语法在档案文件archive中指定名为member的成员。若工做目标是foo.a(bar.o),则$%bar.o$@foo.a。当工做目标不是一个档案文件时,$%是空的。

相关文章
相关标签/搜索