makefile变量

举报
yd_221104950 发表于 2020/12/02 23:19:15 2020/12/02
【摘要】 在声明变量时需要初始化。通过在变量名前加上 $ 符号引用变量,最好用上小括号 () 或 大括号 {} 把变量括起来。变量是大小写敏感的。 如果需要用 $ 字符,那么需要用 $$ 来表示。 变量可以使用在规则中的“目标”、“依赖”、“命令”中及新的变量中。如: CC = gcc OBJS = program.o foo.o utils.o program : $(OB...

在声明变量时需要初始化。通过在变量名前加上 $ 符号引用变量,最好用上小括号 () 或
大括号 {} 把变量括起来。变量是大小写敏感的。

如果需要用 $ 字符,那么需要用 $$ 来表示。 变量可以使用在规则中的“目标”、“依赖”、“命令”中及新的变量中。如:

CC = gcc
OBJS = program.o foo.o utils.o
program : $(OBJS)
	$(CC) -o program $(OBJS)
$(OBJS) : defs.h

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

注:强烈建议在引用变量时,加下小括号或大括号,这样可以更安全地引用变量。

变量会在引用它的地方展开,如:

foo = c
prog.o : prog.$(foo)
	$(foo)$(foo) -$(foo) prog.$(foo)

  
 
  • 1
  • 2
  • 3

展开后得到:

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

  
 
  • 1
  • 2

上面这个例子的用法,在实际生产,强烈不建议这么使用。

在 Makefile 中有两种方式来在用变量定义变量的值

  • 使用 = 号,右侧变量的值可以定义在文件的任何一处,即不需要定义在引用变量处之前,执行make时,会在引用的地方展开。
CC = gcc

  
 
  • 1
  • 使用 := 号
CC := gcc

  
 
  • 1

第一种=号方式,因为引用它时,不用先定义(即可先引用后定义,或者反过来),这将导致递归定义,如:

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

  
 
  • 1
  • 2
  • 3

CFLAGS = $(CFLAGS) -o在命令中被展开时会形成递归定义,这会让 make 陷入无限的变量展开过程中去。虽然,make有能力检测出这样的定义,并会报错。如果在变量中使用函数的话,这种递归让make 运行得非常慢,甚至可能发生不可预知的错误。

使用:= 操作符可以解决这个问题。而且使用这个操作符的话,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。
如:

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

  
 
  • 1
  • 2
  • 3

等价于:

y := foo bar
x := later

  
 
  • 1
  • 2

特别强调,如果是这样:

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

  
 
  • 1
  • 2

那么,y 的值是“bar”,而不是“foo bar”。

?=操作符

FOO ?= bar

  
 
  • 1

含义:如果 FOO 没有被定义过,那么将“bar”赋给它。如果 FOO 先前被定义过,那么这条语将什么也不做。上面这条语句等价于:

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

  
 
  • 1
  • 2
  • 3

变量高级用法

  • 第一种是变量值的替换
    可以替换变量中的公共部分,格式:$(var:a=b) 或 ${var:a=b} ,表示把变量“var”中所有以“a”结尾的“a”替换成“b”,如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)

  
 
  • 1
  • 2

这个例子中,定义了变量foo。$(foo:.o=.c)就是把 $(foo) 中所有以 .o结
尾的.o全部替换成 .c ,所以$(bar) 的值是“a.c b.c c.c”。
另外一种变量替换的技术是以“静态模式”定义的,如:

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

  
 
  • 1
  • 2

这依赖于被替换字符串中的有相同的模式,%是一个通配符,而且静态模式中必须包含一个 % 字符,这个例子同样让 $(bar) 变量的值变为“a.c b.c c.c”。

- 第二种是“把变量的值再当成变量”

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

  
 
  • 1
  • 2
  • 3

在这个例子中,$(x) 的值是“y”,所以 $($(x)) 就是 $(y),于是 $(a) 的值就是“z”。还可以使用更多的层次,如:

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

  
 
  • 1
  • 2
  • 3
  • 4

这里的 $(a) 的值是“u”。

+= 操作符给变量追加值
如:

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

  
 
  • 1
  • 2

$(objects) 值变成:“main.o foo.o bar.o utils.o another.o”

使用 += 操作符也可以写成下面的样子:

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

  
 
  • 1
  • 2

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

variable := value
variable += more

  
 
  • 1
  • 2

等价于:

variable := value
variable := $(variable) more

  
 
  • 1
  • 2

但如果是:

variable = value
variable += more

  
 
  • 1
  • 2

由于前次的赋值符是 = ,所以 += 也会以 = 来做为赋值,那么就会发生变量的递归定义,很不好,幸好 make 会自动解决这个问题。

多行变量
使用 define 关键字设置变量值的方法。使用 define 关键字设置变量的值可以有换行,有利于定义一系列的命令。define 指示符后面跟的是变量的名字,然后重起一行定义变量的值,定义是以 endef 关键字结束。其工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字,或是其它变量。因为命令需要以[Tab] 键开头,所以如果你用 define 定义的命令变量中没有以 Tab 键开头,那么 make 就不会把其认为是命令。
下面的这个示例展示了 define 的用法:

define two-lines
echo foo
echo $(bar)
endef

  
 
  • 1
  • 2
  • 3
  • 4

谢谢阅读

文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40763897/article/details/103241807

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。