Makefile学习笔记(6)——变量中的变量,变量的高级用法,追加变量值,override指示符

本文介绍了Makefile中变量的高级用法,包括变量中的变量(=和:=的区别)、变量替换($(var:a=b)和静态模式替换)、通过变量名组合取值以及追加变量值的+=操作符。此外,还详细讲解了override指示符的用途,用于在Makefile中覆盖命令行参数设置,确保关键编译选项生效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6.1变量中的变量

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

先看第一种方式,也就是简单的使用“=”号,在“=”左侧是变量,右侧是变量的值,右侧变量的值可以定义在
文件的任何一处,也就是说,右侧中的变量不一定非要是已定义好的值,其也可以使用后面定义的值。如:

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

此时输出的值为“Huh?”可见,变量是可以使用后面的变量来定义的。

这个方法的好处是可以把变量的真实值推到后面来定义,但是不好的地方是当被递归定义时会反复调用例如:

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

这会让 make 陷入无限的变量展开过程中去。

 

第二种方法是使用“:=”,操作符这种方法,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。

x:=foo
y:=$(x)bar
x:=later
其等价于:
y:=foobar
x:=later
值得一提的是,这种方法,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。如果是这样:
y:=$(x)bar
x:=foo
那么,y 的值是“bar”,而不是“foobar”。 

当需要定义一个空格时

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

采用“#”注释符来表示变量定义的终止,这样,我们可以定义出其值是一个空格的变量。

注意这个特性以避免自己所定义的变量与想要的不符合。

还有一个比较有用的操作符是“?=”

FOO?=bar

其含义是,如果 FOO 没有被定义过,那么变量 FOO 的值就是“bar”,如果 FOO 先前被定义过,那么这条语将什么也不做

6.2变量的高级用法

两种高级变量使用方法,一种是变量值的替换,适用于类似变量的重命名

格式是“$(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)

这依赖于被替换字串中的有相同的模式,模式中必须包含一个“%”字符,效果与前一种相同。

第二种是将变量的值当成变量

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

在这个例子中,$(x)的值是“y”,所以$($(x))就是$(y),于是$(a)的值就是“z”。(注意,是“x=y”,而不是“x=$(y)”),类似于c语言多重指针的解引用。

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

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

$(all)的值就是“Hello”。

当两种技术结合在一起的时候

a_objects:=a.o b.o c.o
1_objects:=1.o 2.o 3.o
sources:=$($(a1)_objects:.o=.c)

其中变量$(a1)值待定,如果$(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  d g q”,而如果没有定义“do_sort”,那么:foo:=$(sort a d b g q c),调用的就是 strip 函数。

关于sort函数的用法见https://blog.youkuaiyun.com/zhoudengqing/article/details/41778007

函数的用法见striphttps://www.jianshu.com/p/b587652bcb44

6.3追加变量值

可以使用“+=”操作符给变量追加值,如:

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

$(objects)值变成:“main.o foo.o bar.o utils.o another.o”(another.o 被追加进去了)

如果变量之前没有定义过,那么,“+=”会自动变成“=”,如果前面有变量定义,那么“+=”会继承于前次操作的赋值符。如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符,如

variable:=value
variable+=more
等价于:
variable:=value
variable:=$(variable) more

6.4 override指示符

参考了https://blog.youkuaiyun.com/wh_19910525/article/details/41279909博客的内容,比较详细,这里拿过来总结一下:

    如果有变量是通常 make 的命令行参数设置的,那么 Makefile 中对这个变量的赋值会被忽略。如果你想在Makefile 中设置这类参数的值不被命令行参数覆盖,那么,你可以使用“override”指示符。其语法是:

override <variable>=<value>
override <variable>:=<value>
当然,你还可以追加:
override <variable>+=<moretext>

        对于追加方式需要说明的是:变量在定义时使用了“override”,则后续对它值进行追加时,也需要使用带有“override”指示符的追加方式。否则对此变量值的追加不会生效。

     override指示符的作用是用于实现makefile增加或者修改命令行参数的一种机制。我们可能会有这样的需求;可以通过命令行来指定一些附加的编译参数,对一些通用的参数或者必需的编译参数在Makefile中指定,而在命令行中指定一些特殊的参数。对于这种需求,我们就需要使用指示符“override”来实现。

例如:无论命令行指定那些编译参数,编译时必须打开“-g”选项,那么在Makefile中编译选项“CFLAGS”应该这样定义:

override CFLAGS += -g

这样,在执行make时无论在命令行中指定了那些编译选项(“指定CFLAGS”的值),编译时“-g”参数始终存在。

最后我们来看一个例子:

# sample Makefile

EXEF = foo

override CFLAGS += -Wall –g

.PHONY : all debug test

all : $(EXEF)

foo : foo.c

………..

……….. 

$(EXEF) : debug.h

$(CC) $(CFLAGS) $(addsuffix .c,$@) –o $@

debug :

       @echo ”CFLAGS = $(CFLAGS)”

执行:make CFLAGS=-O2 将显式编译“foo”的过程是“cc –O2 –Wall –g foo.c –o foo”。执行“make CFLAGS=-O2 debug”可以查看到变量“CFLAGS”的值为“–O2 –Wall –g”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值