Makefile学习(一)变量
鉴于之前有一些了解,还有自己的学习习惯,我一上来就看Makefile的变量这一章。主要脉络是根据GNU make中文手册。
第六章:Makefile中的变量
6使用变量
定义:变量是一个名字,代表一个文本字符串;类似C语言中的宏
区别在于这个变量在Makefile的目标、依赖、命令中引用的地方会被它的值所取代;
特征:1.Makefile中变量和函数的展开(除了规则命令行)是在make读取makefile文件时进行的;
2.变量可用于代表:一个文件名列表、编译选项列表、程序运行的选项参数列表(CFLAGS,LDFLAGS等等)、搜索源文件的目录列表、编译输出的目录列表以及任何能想象出的数据;
3.变量名不包括“:”“#”“=”、前置空白和尾空白的任何字符串。注意:尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的字符可能会在make后续版本中被赋予特殊含义,并且这样命名的变量对于一些shell来说是不能被作为环境变量来使用的。
4.变量名大小写敏感;推荐的做法是在对于内部定义定义的一般变量(例如:目标文件列表 objects)使用小写方式,而对于一些参数列表(例如:编译选项 CFLAGS )采用大写方式,但这并不是要求的。需要强调一点:对于一个工程,所有Makefile 中的变量命名应保持一种风格,否则会显得你是一个蹩脚的程序员(就像代码的变量命名风格一样)。
5.另外有一些变量名只包含了一个或者很少几个特殊字符,称为自动化变量,$<,$@,$?,$*
6.1变量的引用
引用方式:$(变量名),${变量名}
例子:objects = program.o foo.o utils.o
program : $(objects)
cc -o program $(objects)
$(objects):defs.h
一般在我们书写Makefile 时,各部分变量引用的格式我们建议如下:
1. make变量(Makefile 中定义的或者是make的环境变量)的引用使用“$(VAR)”
格式,无论“VAR ”是单字符变量名还是多字符变量名。
2. 出现在规则命令行中shell变量(一般为执行命令过程中的临时变量,它不属于
Makefile 变量,而是一个shell变量)引用使用shell的“$tmp”格式。
3. 对出现在命令行中的make变量我们同样使用“$(CMDVAR)” 格式来引用。
例子:
SUBDIRS:=src foo
.PHONY:subdir
Subdir:
@for dir in $(SUBDIRS);do\
$(MAKE) -C $$dir || exit 1;
done
这里的MAKE就是引用
6.2两种变量定义(赋值)
这两种风格的区别:1.定义方式2.展开时机
6.2.1递归展开式变量
使用”=“或者”define“定义,这种变量的引用是严格的文本替换过程,如果此变量定义中存在对其他变量的引用,这些被引用的变量会在它被展开的同时被展开;
例子:
foo=$(bar)
bar=$(ugh)
ugh=Huh?
all:;echo $(foo)
执行make将会打印HUh?
优点是:这种类型变量在定义时,可以引用其他之前没有定义的变量;
缺点是:由于出现变量的递归定义导致make陷入到无限的变量展开中,最终使make执行失败;
如果使用了函数,在包含在变量值中的函数总会在变量被引用的地方执行:使make执行 效率降低,如果引用了”shell“”wildcard“函数,可能出现不可控制和难以预料的错误;
6.2.2直接展开式变量
这种风格的变量使用”:=“定义,这种方法使用中对其他变量或者函数的引用在定义变量时才被展开,因此例子如下:
x:=foo
y:=$(x) bar
x:=later
就等价于:
y:=foo bar
x:=later
不能实现对其后定义变量的引用。
6.2.3定义一个空格
一般变量值中的前导空格字符在变量引用和函数调用时被丢弃。
例子:
nullstring:=
space:=$(nullstring) #end of the line
在space定义行中的注释使得我们的目的更清晰,注释和变量引用之间存在一个空格。
以”nullstring“开始,采用”#“注释来结束,中间是一个空格字符;
因此在定义变量时也要注意,没有空格的变量就不要把空格包含进去;
例子:
dir :=/foo/bar #...
这个变量本身没有空格,你把它包含空格了。
6.2.4”?=“操作符
这是条件赋值。
FOO?=bar
等价于:
ifeq($(origin FOO),undefined)
FOO =bar
endif
含义:如果FOO在之前没有定义,就给他赋值,否则不改变它的值;
6.3变量的高级用法
6.3.1变量的替换引用
$(VAR:A=B),将VAR变量中所有A字符结尾的字替换为B结尾的字,对于其他部分的A不进行替换
例子:foo:=a.o b.o c.o
bar:=$(foo:.o=.c)
变量的替换引用其实是函数”patsubst“的一个简化实现。另一种引用替换使用功能更强的函数。
例子:foo:=a.o b.o c.o
bar:=$(foo:%.o=%.c)
和第一种实现功能一样,但是更通用。
6.3.2变量的嵌套引用
一个变量名之中可以包含对其他变量的引用,这就是”变量的嵌套引用“
例子:
x=y
y=z
a:=$($(x))
6.4变量取值
override
赋值方式
将变量设置为系统环境变量
自动化变量
隐含变量
6.5如何设置变量
就是定义,注意一些情况;
6.6追加变量值
使用”+=“来实现对一个变量值的追加操作。
6.7override指示符
执行make时,如果通过命令行定义了一个变量,则它将替代Makefile中出现的同名变量的定义。
如果不希望命令行指定的变量值替代在Makefile中的变量定义,则需要使用override来对变量进行声明。
override VARIABLE:=VALUE
例子:
无论命令行指定哪些编译参数,编译时必须打开-g,那么在在Makefile中bCFLAGS应该定义为:override CFLAGS+=-g
6.8多行定义
define 。。
。。
。。
endif
6.9系统环境变量
make在运行时,系统中的所有环境变量对它都是可见的。在 Makefile 中,可以引
用任何已定义的系统环境变量。
例如CFLAGS,SHELL
我们不推荐使用环境变量的方式来完成普通变量的工作,特别是在make 的递归调用
中。任何一个环境变量的错误定义都对系统上的所有make产生影响,甚至是毁坏性的。
6.10目标指定变量
设置一个目标指定变量的语法为:
TARGET ... : VARIABLE-ASSIGNMENT
或者:
TARGET ... : override VARIABLE-ASSIGNMENT
另外当使用make的“-e ”选项时,同名的环境变量
也将覆盖目标指定的变量定义
6.11模式指定变量
设置一个模式指定变量的语法和设置目标变量的语法相似:
PATTERN ... : VARIABLE-ASSIGNMENT
或者:
PATTERN ... : override VARIABLE-ASSIGNMENT
Makefile学习(一)变量的更多相关文章
- [转]Windows平台下Makefile学习笔记
Windows平台下Makefile学习笔记(一) 作者:朱金灿 来源:http://blog.csdn.net/clever101 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译 ...
- makefile 学习归纳
makefile 学习归纳 一直希望 好好整理下 makefile的写法,这在linux编程界是必备技能.下面就好好的说道说道. 可以参考的大神总结 整理 makefile是供make命令执行的 脚本 ...
- makefile学习(1)
GNU Make / Makefile 学习资料 GNU Make学习总结(一) GNU Make学习总结(二) 这篇学习总结,从一个简单的小例子开始,逐步加深,来讲解Makefile的用法. 最后用 ...
- Makefile学习一
上次随着信号学习告一段落,也标志着linux系统编程相关的知识学完了,而学了这么多知识点,是需要用一个综合的项目来将其进行串起来的,这样学习的技术才会不那么空洞,所以接下来会以一个实际例子来综合运用下 ...
- js学习之变量、作用域和内存问题
js学习之变量.作用域和内存问题 标签(空格分隔): javascript 变量 1.基本类型和引用类型: 基本类型值:Undefined, Null, Boolean, Number, String ...
- makefile学习小结
=============2016/08/15================ 上午完成makefile的试验,缩短了代码量,现在make强大,有缺省的变量,能自己推导关系,不需要gcc –MM -M ...
- makefile中使用变量
makefile里的变量就像一个变量,变量的作用主要如下: (1)保存文件名列表. (2)保存编译器的参数. makefile中的变量是用一个字符串在makefile中定义的,这个文本串就是变量的值. ...
- Makefile学习与进阶之Makefile.am和$$(M)的意思
(1)makefile 中,出现$$(M) 是什么意思,发现还是看实际的Makefile长知识啊 在makefile中,会经常使用shell命令,也经常见到$var 和 $$var的情况,有什么区别呢 ...
- PHP学习(变量)
PHP学习(变量) 1. PHP属于松散类型,创建变量时不用指定类型. 2.变量命名规范: 1)第一个字符必须是$ 2)$后的第一个字符必须是 字母 或 下划线 3)其他字符可以是 字母, 数字, 下 ...
随机推荐
- [Angular 2] Refactoring mutations to enforce immutable data in Angular 2
When a Todo property updates, you still must create a new Array of Todos and assign a new reference. ...
- gcc -L -l的使用
-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so ...
- 好的android编码习惯
上一期分享了android内存优化的一些总结,这一期说说我认为的好的编码习惯,然后下一期会做安卓数据库优化的一些总结,逐渐的会将一些性能优化点总结分享出来,肯定是不够全面的希望不足的地方欢迎指出. 良 ...
- Sql 2012 OFFSET / FETCH NEXT BUG
上个星期,测试发现了一个分页的bug--- 无论怎么分页数据的一样.我们所有的分页都是用EF 分页,为什么只有一个模块的分页有问题呢? 后来跟了下sql语句,发现用到是sql2012的新分页方式 OF ...
- 重新认识Intent
相信android开发工程师,对Intent一定不陌生,在整个开发中随时都用到了,今天我们总结一下Intent. 1. 为什么需要Intent? 在android Intent机制是协助应用间的交互与 ...
- ORA-04021
编译或删除存储过程的时候,系统会卡住,一段时间后出现ora-04021错误. 1.可能被锁住查看v$locked select b.sid,b.serial#,b.machine,b.terminal ...
- ORACLE之SQL语句内部解析过程【weber出品】
一.客户端通过监听连接到数据库,数据库开启一个server process进程来接收客户端传过来的sql. 1.这条sql语句从来都没有被执行过.(硬解析) 2.这条sql语句被执行过.(软解析) 二 ...
- Linux 定时执行shell脚本_crontab
1.查看任务[oracle@XXXXX OracleBackA]$ crontab -l 2.新增任务[oracle@XXXXX OracleBackA]$ crontab -e 3.每天14点40执 ...
- javascript:Array.slice.call 到Array.prototype.slice.call
举个从对象到数组的例子: var obj={}; obj[1]=1; obj[2]=2; obj.length=2; var arr =Array.prototype.slice.call(obj); ...
- asp.net运行机制图
(郑重提示:此图版权归广州传智播客老邹所有啊!!!!) 详细版