linux下的makefile教程(5)

2019-05-17 16:34

―$$‖来表示。

变量可以使用在许多地方,如规则中的―目标‖、―依赖‖、―命令‖以及新的变量中。 先看一个例子:

objects = program.o foo.o utils.o program : $(objects) cc -o program $(objects)

$(objects) : defs.h

变量会在使用它的地方精确地展开,就像C/C++中的宏一样,例如: foo = c

prog.o : prog.$(foo)

$(foo)$(foo) -$(foo) prog.$(foo)

展开后得到:

prog.o : prog.c cc -c prog.c

当然,千万不要在你的Makefile中这样干,这里只是举个例子来表明Makefile中的变量在

使用处展开的真实样子。可见其就是一个―替代‖的原理。

另外,给变量加上括号完全是为了更加安全地使用这个变量,在上面的例子中,如果你不

想给变量加上括号,那也可以,但我还是强烈建议你给变量加上括号。

二、变量中的变量

在定义变量的值时,我们可以使用其它变量来构造变量的值,在Makefile中有两种方式来

在用变量定义变量的值。

先看第一种方式,也就是简单的使用―=‖号,在―=‖左侧是变量,右侧是变量的值,右

侧变量的值可以定义在文件的任何一处,也就是说,右侧中的变量不一定非要是已定义好

的值,其也可以使用后面定义的值。如:

foo = $(bar) bar = $(ugh) ugh = Huh? all:

echo $(foo)

我们执行―make all‖将会打出变量$(foo)的值是―Huh?‖( $(foo)的值是$(bar),$(b

ar)的值是$(ugh),$(ugh)的值是―Huh?‖)可见,变量是可以使用后面的变量来定义的。

这个功能有好的地方,也有不好的地方,好的地方是,我们可以把变量的真实值推到后面 来定义,如:

CFLAGS = $(include_dirs) -O include_dirs = -Ifoo -Ibar

当―CFLAGS‖在命令中被展开时,会是―-Ifoo -Ibar -O‖。但这种形式也有不好的地方

,那就是递归定义,如:

CFLAGS = $(CFLAGS) -O 或:

A = $(B) B = $(A)

这会让make陷入无限的变量展开过程中去,当然,我们的make是有能力检测这样的定义,

并会报错。还有就是如果在变量中使用函数,那么,这种方式会让我们的make运行时非常

慢,更糟糕的是,他会使用得两个make的函数―wildcard‖和―shell‖发生不可预知的错

误。因为你不会知道这两个函数会被调用多少次。

为了避免上面的这种方法,我们可以使用make中的另一种用变量来定义变量的方法。这种

方法使用的是―:=‖操作符,如:

x := foo

y := $(x) bar x := later

其等价于:

y := foo bar x := later

值得一提的是,这种方法,前面的变量不能使用后面的变量,只能使用前面已定义好了的

变量。如果是这样:

y := $(x) bar x := foo

那么,y的值是―bar‖,而不是―foo bar‖。

上面都是一些比较简单的变量使用了,让我们来看一个复杂的例子,其中包括了make的函

数、条件表达式和一个系统变量―MAKELEVEL‖的使用:

ifeq (0,${MAKELEVEL}) cur-dir := $(shell pwd) whoami := $(shell whoami) host-type := $(shell arch)

MAKE := ${MAKE} host-type=${host-type} whoami=${whoami} endif

关于条件表达式和函数,我们在后面再说,对于系统变量―MAKELEVEL‖,其意思是,如果

我们的make有一个嵌套执行的动作(参见前面的―嵌套使用make‖),那么,这个变量会

记录了我们的当前Makefile的调用层数。

下面再介绍两个定义变量时我们需要知道的,请先看一个例子,如果我们要定义一个变量

,其值是一个空格,那么我们可以这样来:

nullstring :=

space := $(nullstring) # end of the line

nullstring 是一个Empty变量,其中什么也没有,而我们的space的值是一个空格。因为在

操作符的右边是很难描述一个空格的,这里采用的技术很管用,先用一个 Empty

变量来标

明变量的值开始了,而后面采用―#‖注释符来表示变量定义的终止,这样,我们可以定义

出其值是一个空格的变量。请注意这里关于―#‖的使用,注释符―#‖的这种特性值得我

们注意,如果我们这样定义一个变量:

dir := /foo/bar # directory to put the frobs in

dir这个变量的值是―/foo/bar‖,后面还跟了4个空格,如果我们这样使用这样变量来指

定别的目录——―$(dir)/file‖那么就完蛋了。

还有一个比较有用的操作符是―?=‖,先看示例:

FOO ?= bar

其含义是,如果FOO没有被定义过,那么变量FOO的值就是―bar‖,如果FOO先前被定义过

,那么这条语将什么也不做,其等价于:

ifeq ($(origin FOO), undefined) FOO = bar endif

三、变量高级用法

这里介绍两种变量的高级使用方法,第一种是变量值的替换。

我们可以替换变量中的共有的部分,其格式是―$(var:a=b)‖或是―${var:a=b}‖,其意

思是,把变量―var‖中所有以―a‖字串―结尾‖的―a‖替换成―b‖字串。这里的―结 尾‖意思是―空格‖或是―结束符‖。

还是看一个示例吧:

foo := a.o b.o c.o bar := $(foo:.o=.c)

这个示例中,我们先定义了一个―$(foo)‖变量,而第二行的意思是把―$(foo)‖中所有

以―.o‖字串―结尾‖全部替换成―.c‖,所以我们的―$(bar)‖的值就是―a.c b.c c. c‖。

另外一种变量替换的技术是以―静态模式‖(参见前面章节)定义的,如:

foo := a.o b.o c.o bar := $(foo:%.o=%.c)

这依赖于被替换字串中的有相同的模式,模式中必须包含一个―%‖字符,这个例子同样让

$(bar)变量的值为―a.c b.c c.c‖。

第二种高级用法是——―把变量的值再当成变量‖。先看一个例子: x = y y = z a := $($(x))

在这个例子中,$(x)的值是―y‖,所以$($(x))就是$(y),于是$(a)的值就是―z‖。(注

意,是―x=y‖,而不是―x=$(y)‖)

我们还可以使用更多的层次: x = y y = z z = u

a := $($($(x)))

这里的$(a)的值是―u‖,相关的推导留给读者自己去做吧。

让我们再复杂一点,使用上―在变量定义中使用变量‖的第一个方式,来看一个例子:

x = $(y) y = z z = Hello a := $($(x))

这里的$($(x))被替换成了$($(y)),因为$(y)值是―z‖,所以,最终结果是:a:=$(z), 也就是―Hello‖。

再复杂一点,我们再加上函数:

x = variable1 variable2 := Hello y = $(subst 1,2,$(x)) z = y

a := $($($(z)))

这个例子中,―$($($(z)))‖扩展为―$($(y))‖,而其再次被扩展为―$($(subst 1,2,$

(x)))‖。$(x)的值是―variable1‖,subst函数把―variable1‖中的所有―1‖字串替换

成―2‖字串,于是,―variable1‖变成―variable2‖,再取其值,所以,最终,$(a)的

值就是$(variable2)的值—— ―Hello‖。(喔,好不容易)

在这种方式中,或要可以使用多个变量来组成一个变量的名字,然后再取其值:

first_second = Hello a = first b = second all = $($a_$b)

这里的―$a_$b‖组成了―first_second‖,于是,$(all)的值就是―Hello‖。

再来看看结合第一种技术的例子:

a_objects := a.o b.o c.o 1_objects := 1.o 2.o 3.o

sources := $($(a1)_objects:.o=.c)

这个例子中,如果$(a1)的值是―a‖的话,那么,$(sources)的值就是―a.c b.c c.c‖;

如果$(a1)的值是―1‖,那么$(sources)的值是―1.c 2.c 3.c‖。

再来看一个这种技术和―函数‖与―条件语句‖一同使用的例子:

ifdef do_sort func := sort else

func := strip endif

bar := a d b g q c

foo := $($(func) $(bar))

这个示例中,如果定义了―do_sort‖,那么:foo := $(sort a d b g q c),于是$(foo

)的值就是―a b c d g q‖,而如果没有定义―do_sort‖,那么:foo := $(sort a d b

g q c),调用的就是strip函数。

当然,―把变量的值再当成变量‖这种技术,同样可以用在操作符的左边:

dir = foo

$(dir)_sources := $(wildcard $(dir)/*.c) define $(dir)_print lpr $($(dir)_sources) endef

这个例子中定义了三个变量:―dir‖,―foo_sources‖和―foo_print‖。

四、追加变量值

我们可以使用―+=‖操作符给变量追加值,如:

objects = main.o foo.o bar.o utils.o objects += another.o

于是,我们的$(objects)值变成:―main.o foo.o bar.o utils.o another.o‖(anothe

r.o被追加进去了)

使用―+=‖操作符,可以模拟为下面的这种例子:

objects = main.o foo.o bar.o utils.o objects := $(objects) another.o

所不同的是,用―+=‖更为简洁。

如果变量之前没有定义过,那么,―+=‖会自动变成―=‖,如果前面有变量定义,那么―

+=‖会继承于前次操作的赋值符。如果前一次的是―:=‖,那么―+=‖会以―:=‖作为其

赋值符,如:

variable := value

variable += more

等价于:

variable := value

variable := $(variable) more

但如果是这种情况:

variable = value variable += more

由于前次的赋值符是―=‖,所以―+=‖也会以―=‖来做为赋值,那么岂不会发生变量的

递补归定义,这是很不好的,所以make会自动为我们解决这个问题,我们不必担心这个问 题。

五、override 指示符

如果有变量是通常make的命令行参数设置的,那么Makefile中对这个变量的赋值会被忽略

。如果你想在Makefile中设置这类参数的值,那么,你可以使用―override‖指


linux下的makefile教程(5).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:木素提取制备及应用工艺技术

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: