1.2.2 Makefile变量
1.变量的引用方式
使用“$(OBJTREE)”或者“${ OBJTREE }”来引用OBJTREE这个变量的定义。这个引用方式似乎很像C语言中的指针变量,使用*p来取存放在指针p中的值。
obj := $(OBJTREE)/ OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) export BUILD_DIR=/tmp/build
$(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))的含义:如果“BUILD_DIR”变量值不为空,则将变量“BUILD_DIR”指定的目录作为一个子目录;否则将目录“CURDIR”作为一个子目录。
2.递归展开式变量
这类变量的定义是通过“=”和“define”来定义的。
student = lilei CLASS = $(student) $(teacher) teacher = yang all: @echo $(CLASS)
其优点是:这种类型递归展开式的变量在定义时,可以引用其他之前没有定义过的变量,这个变量可能在后续部分定义,或者是通过make的命令行选项传递的变量来定义。
其缺点是:其一,使用此风格的变量定义,可能会由于出现变量的递归定义而导致 make 陷入到无限的变量展开过程中,最终使make执行失败。
x = $(y) y = $(z) z = $(x)
这样的话会使得Makefile出错,因为到最终引用了自己。
其二,这种风格的变量定义中如果使用了函数,那么包含在变量值中的函数总会在变量被引用的地方执行。
3.直接展开式变量
为了避免递归展开式变量存在的问题和不方便,GNU make支持另外一种风格的变量,称为直接展开式变量。这种风格的变量使用“:=”定义。在使用“:=”定义变量时,变量值中对其他变量或者函数的引用在定义变量时被展开,也就是对变量进行替换。
X := student Y := $(X) X := teacher all: @echo $(X) $(Y)
这里的输出是:teacher student。
这个直接展开式变量在定义时就完成了对所引用变量和函数的展开,因此不能实现对其后定义变量的引用。
4.条件赋值
在对变量进行赋值之前,会对其进行判断,只有在这个变量之前没有进行赋值的情况下才会对这个变量进行赋值。
X := student X ?= teacher all: @echo $(X)
由于X在之前被赋值了,所以这里的输出是student。
5.变量的替换引用
对于一个已经定义的变量,可以使用变量的替换引用将变量中的后缀字符使用指定的字符替换。格式为“$(X:a=b)”(或者“${X:a=b}”),即将变量“X”中所有以“a”字符结尾的字替换为以“b”结尾的字。
X := fun.o main.o Y := $(X: .o=.c) all: @echo $(X) $(Y)
特别注意的是,$(X: .o=.c)的“=”两边不能有空格。这里的输出是:fun.o main.o fun.c main.c。
6.追加变量值
追加变量值是指一个通用变量在定义之后的其他一个地方,可以对其值进行追加。也就是说可以在定义时(也可以不定义而直接追加)给它赋一个基本值,后续根据需要可随时对它的值进行追加(增加它的值)。在Makefile中使用“+=”(追加方式)来实现对一个变量值的追加操作。
X = fun.o main.o X += sub.o all: @echo $(x)
这里的输出是:fun.o main.o sub.o。