打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Makefile中的变量

2007-11-03 12:03

Makefile中变量有以下几个特征:

1. Makefile中变量和函数的展开(除规则命令行中的变量和函数以外),是在make读取makefile文件时进行的,这里的变量包括了使用“=”定义和使用指示符“define”定义的。

2. 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。

3. 变量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。

4. 变量名是大小写敏感的。推荐的做法是在对于内部定义定义的一般变量(例如:目标文件列表objects)使用小写方式,而对于一些参数列表(例如:编译选项CFLAGS)采用大写方式。

5. 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自动化变量。像“$<”、“$@”、“$?”、“$*”等。

(1) 变量的引用

      Makefile中在对一些简单变量的引用,我们也可以不使用“()”和“{}”来标记变量名,而直接使用“$x”的格式来实现,此种用法仅限于变量名为单字符的情况。另外自动化变量也使用这种格式。对于一般多字符变量的引用必须使用括号了标记,否则make将把变量名的首字母作为作为变量而不是整个字符串(“$PATH”在Makefile中实际上是“$(P)ATH”)。这一点和shell中变量的引用方式不同。shell中变量的引用可以是“${xx}”或者“$xx”格式。但在Makefile中多字符变量名的引用只能是“$(xx)”或者“${xx}”格式。

(2) 变量的定义

两种风格:递归展开式变量和直接展开式变量。前者前者在引用的地方是严格的文本替换,后者用:=定义,变量值中对其他量或者函数的引用在定义变量时被展开(对变量进行替换),此风格变量在定义时就完成了对所引用变量和函数的展开,因此不能实现对其后定义变量的引用(前者是嫩购实现这个功能的)。如:
CFLAGS := $(include_dirs) -O
include_dirs := -Ifoo -Ibar
由于变量“include_dirs”的定义出现在“CFLAGS”定义之后。因此在“CFLAGS”的定义中,“include_dirs”的值为空。“CFLAGS”的值为“-O”而不是“-Ifoo -Ibar -O”。这一点也是直接展开式和递归展开式变量的不同点。

    在复杂的Makefile中,推荐使用直接展开式变量。因为这种风格变量的使用方式和大多数编程语言中的变量使用方式基本上相同。它可以使一个比较复杂的Makefile在一定程度上具有可预测性。而且这种变量允许我们利用之前所定义的值来重新定义它(比如使用某一个函数来对它以前的值进行处理并重新赋值),此方式在Makefile中经常用到。尽量避免和减少递归式变量的使用。

         当定义不包含尾空格的变量时,就不能使用这种方式,将变量定义和注释书写在同一行并使用若干空格分开。否则,注释之前的空格会被作为变量值的一部分。例如下边的做法就是不正确的:
dir := /foo/bar # directory to put the frobs in
变量“dir”的值是“/foo/bar ”(后面有4个空格),这可能并不是想要实现的。如果一个文件以它作为路径来表示“$(dir)/file”,
那么大错特错了。

“?=”操作符
GNU make中,还有一个被称为条件赋值的赋值操作符“?=”。被称为条件赋值是因为:只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。例如:
FOO ?= bar
其等价于:
ifeq ($(origin FOO), undefined)
FOO = bar
endif
含义是:如果变量“FOO”在之前没有定义,就给它赋值“bar”。否则不改变它的值。

“+=”操作符

使用“+=”操作符,相当于:
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
相当于:
temp = value
variable = $(temp) more

(3) 变量的高级用法

1.   变量的替换引用

对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。

例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
在这个定义中,变量“bar”的值就为“a.c b.c c.c”。使用变量的替换引用将变量“foo”以空格分开的值中的所有的字的尾字符“o”替换为“c”,其他部分不变。

又如:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
这个例子同样使变量“bar”的值为“a.c b.c c.c”。这种格式的替换引用方式比第一种方式更通用。

使用环境变量需要注意以下几点:
1. 在Makefile中对一个变量的定义或者以make命令行形式对一个变量的定义,都将覆盖同名的环境变量(注意:它并不改变系统环境变量定义,被修改的环境变量只在make执行过程有效)。而make使用“-e”参数时,Makefile和命令行定义的变量不会覆盖同名的环境变量,make将使用系统环境变量中这些变量的定义值。
2. make的递归调用中,所有的系统环境变量会被传递给下一级make。默认情况下,只有环境变量和通过命令行方式定义的变量才会被传递给子make进程。在Makefile中定义的普通变量需要传递给子make时需要使用“export”指示符来对它声明。

3. 一个比较特殊的是环将变量“SHELL”。在系统中这个环境变量的用途是用来指定用户和系统的交互接口,显然对于make是不合适的。因此make的执行环境变量“SHELL”没有使用同名的环境变量定义,而是“/bin/sh”。make默认“/bin/sh”作为它的命令行解释程序(make在执行之前将变量“SHELL”设置为“/bin/sh”)。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Makefile中的命令和变量
Android.mk File
GNU make中文手册-第九章:执行make
GNU make中文手册-第八章:make的内嵌函数
Makefile详解(二)
Android NDK开发指南---Android.mk文件
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服