鉴于之前有一些了解,还有自己的学习习惯,我一上来就看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学习(一)变量的更多相关文章

  1. [转]Windows平台下Makefile学习笔记

    Windows平台下Makefile学习笔记(一) 作者:朱金灿 来源:http://blog.csdn.net/clever101 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译 ...

  2. js学习之变量、作用域和内存问题

    js学习之变量.作用域和内存问题 标签(空格分隔): javascript 变量 1.基本类型和引用类型: 基本类型值:Undefined, Null, Boolean, Number, String ...

  3. makefile学习小结

    =============2016/08/15================ 上午完成makefile的试验,缩短了代码量,现在make强大,有缺省的变量,能自己推导关系,不需要gcc –MM -M ...

  4. makefile中使用变量

    makefile里的变量就像一个变量,变量的作用主要如下: (1)保存文件名列表. (2)保存编译器的参数. makefile中的变量是用一个字符串在makefile中定义的,这个文本串就是变量的值. ...

  5. Makefile学习与进阶之Makefile.am和$$(M)的意思

    (1)makefile 中,出现$$(M) 是什么意思,发现还是看实际的Makefile长知识啊 在makefile中,会经常使用shell命令,也经常见到$var 和 $$var的情况,有什么区别呢 ...

  6. PHP学习(变量)

    PHP学习(变量) 1. PHP属于松散类型,创建变量时不用指定类型. 2.变量命名规范: 1)第一个字符必须是$ 2)$后的第一个字符必须是 字母 或 下划线 3)其他字符可以是 字母, 数字, 下 ...

  7. Makefile中的变量和shell变量

    我们在写makefile时 多多少少会用到shell脚本, 对于变量的在shell中的使用有一些要注意的细节.让我们从一个简单的makefile来看看. 注意makefile中一定要有一个目标,且一定 ...

  8. makefile学习笔记(多目录嵌套调用、变量使用)

    http://blog.csdn.net/leexiang_han/article/details/9274229   学习了几天的makefile的嵌套调用编写也有一些心得,先声明,我也是初学者写文 ...

  9. Makefile学习笔记

    ls -l 查看文件详细信息 1.gcc -E test.c -o test.i//预编译gedit test.i //查看:高级C 2.gcc -Wall -S test.i -o test.s// ...

随机推荐

  1. [python面向对象]--基础篇

    1.#类 #类就是一个模板,模板里可以包含多个函数,函数里实现一些功能 #定义一个类 class bar: def foo(self,agr): print(self,agr) obj = bar() ...

  2. Activity的Launch Mode

    ANDROID四种启动模式: 1.standard:默认的启动模式,每次新建一个实例对象. 2.singleTop:如果在任务栈顶发现了相同的实例则复用该实例,否则新建一个实例并压入栈顶. 3.sin ...

  3. .NET面试题解析(06)-GC与内存管理

      系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 GC作为.NET的重要核心基础,是必须要了解的.本文主要侧重于GC内存管理中的一些关键点,如要要全面深入了 ...

  4. 编译hadoop-2.5.2总结

    原文:http://www.cnblogs.com/qigang/p/4194728.html 一.准备的资料 64位linux系统.我使用的是 CentOS JDK 1.7+.注:使用1.7即可,如 ...

  5. jBPM4.3+ssh+会签 整合配置及完整实例

    大佬们的项目里有用到会签,所以趁双休日研究了下. 其实也是简单的会签情况,不过开始的时候研究了4.4,(因为先前研究的都是4.4),发现4.4跟4.3的处理方法完全不一样,搞的我比较郁闷……弄了一天, ...

  6. UINavigationController 子控制器管理原理

    UINavigationController 显示在导航控制器上的控制器 永远是栈顶控制器 后进先出  先进后出原则 /** * 程序获得焦点才能获取触摸事件 * */- (void)applicat ...

  7. line-height的小技巧

    CSS中的line-height属性控制着文字的行间距离.通常被设置为一个无单位的值(例如:line-height:1.4),与文字尺寸是成比例的.它是排版中的一个重要的属性.太低了文字会挤在一起,太 ...

  8. iOS 数据库持久化

    Java代码 -(void) addObserver{ //当程序进入后台时执行操作 UIApplication *app = [UIApplication sharedApplication]; [ ...

  9. 【Linux/Ubuntu学习3】解决ubuntu解压windows生成的zip文件时乱码问题

    在windows上压缩的文件,是以系统默认编码中文来压缩文件.由于zip文件中没有声明其编码,所以linux上的unzip一般以默认编码解压,中文文件名会出现乱码. 虽然2005年就有人把这报告为bu ...

  10. .NET中数据集的强类型化

    我们知道,每一种程序设计语言都提供一定的类型检查,类型检查可以在编译时进行,也可以在运行时进行,分别称做静态类型检查和动态类型检查.由于静态类型的检查是在编译时进行,实现比较容易,能提高程序的运行效率 ...