makefile misc

@$ 规则的目标文件名。
make 支持3各通配符:"*","?","…"
支持特别符号:"%":匹配零或多个字符,如 %.c 表示任何以 .c 结尾的文档
$ 表示执行一个Makefile函数
$@ 表示目标集合,相当于从一个数组中依次取出目标

@表示在make时不输出make的信息(类似Windows下的echo off)。

– 不检查返回值

Makefile中的变量

在Makefile中,变量就是个名字(像是C语言中的宏),代表一个文本字符串(变量的值)。在Makefile的目标、依赖、命令中引用一个变量的地方,变量会被他的值所取代(和C语言中宏引用的方式相同,因此其他版本的make也把变量称之为"宏")。

当我们定义了一个变量之后,就能够在Makefile的很多地方使用这个变量。变量的引用方式是:使用"$(VARIABLE_NAME)"或"${
VARIABLE_NAME }"来引用一个变量的定义。

美元符号"$"在Makefile中有特别的含义,任何在命令或文档名中使用"$"时需要用两个美元符号"$$"来表示。

对一个变量的引用能够在Makefile的任何上下文中,目标、依赖、命令、绝大多数指示符和新变量的赋值中。

变量引用的展开过程是严格的文本替换过程,就是说变量值的字符串被精确的展开在此变量被引用的地方。

Makefile中在对一些简单变量的应用,我们也能够不使用"()"和"{}"来标记变量名,而直接使用"$x"的格式来实现,此种用法仅限于变量名为单字符的情况。另外自动化变量也使用这种格式。

两种变量定义(赋值)

变量的这两种不同的风格的区别在于:1. 定义方式;2. 展开时机。

一 递归展开式变量

这一类型的变量的定义是通过"="或使用指示符"define"定义的变量。

这种变量的引用,在引用的地方是严格的文本替换过程,此变量值的字符串原模原样的出现在引用他的地方。

假如此变量定义中存在对其他变量的引用,这些被引用的变量会在他被展开的同时被展开。就是说在变量定义时,变量值中对其他变量的引用不会被替换展开,而是,变量在引用他的地方进行替换展开的同时,他所引用的其他变量才会被替换展开。
看一个例子:
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:;echo $(foo)
执行"make"将会打印出"Huh?"。整个变量的替换过程时这样的:首先"$(foo)"被替换为"$(bar)",接下来"$(bar)"被替换为"$(ugh)",最后"$(ugh)"被替换为"Hug?"。整个替换的过程是在执行"echo
$(foo)"是进行的。

其长处是: 这种类型变量的定义时,能够引用其他的之前没有定义的变量(可能在后续部分定义,或是通过make的命令行选项传递的变量)。看一个这样的例子:
CFLAGS = $(include_dirs) -O
include_dirs = -Ifoo -Ibar
"CFLAGS"会在命令中被展开为"-Ifoo -Ibar -O"。我们能够看到在"CFLAGS"定义中使用到了之后定义的变量"include_dirs"。

其缺点是:
(1). 使用此风格的变量定义,可能会由于出现变量的递归定义而导致make陷入到无限的变量展开过程中,最终使make执行失败。
CFLAGS = $(CFLAGS) –O
他将会导致make进入对变量"CFLAGS"的无限展过程中去(这种定义就是变量的递归定义)。
x = $(y)
y = $(x) $(z)
这种情况下同样会导致make陷入到无限的变量展开过程中。

(2). 这种风格变量的定义中假如使引用了某一个函数,那么函数总会在其被引用的地方被执行。

二 直接展开式变量

这种风格的变量使用":="来定义变量。

在使用":="定义变量时,变量值中对另外变量的引用或函数的引用在定义时被展开(对变量进行替换)。所以在变量被定义以后就是个实际所需要定义的文本串,其中不再包含任何对其他变量的引用。
CFLAGS := $(include_dirs) -O
include_dirs := -Ifoo -Ibar
由于在变量"include_dirs"的定义出现在"CFLAGS"定义之后。因此在"CFLAGS"的定义中,"include_dirs"的值为空。"CFLAGS"的值为"-O"而不是"-Ifoo
-Ibar -O"。

需要注意的是对于不包含尾空格的变量的定义,就不能随便使用几个空格之后,在同行中放置他的注释内容。这是千万需要注意的。
例如下边的做法就是不正确的:
dir := /foo/bar #directory to put the frobs in
变量"dir"的值是"/foo/bar "(后面有4个空格)。
注释内容推荐书写在单独的一行或多行,这样就能够防止出现这种意外情况的发生。

三 "?="操作符

GNU make中,有一个被称为条件赋值的赋值操作符"?="。
被称为条件赋值是因为:只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。

四 变量的替换引用

格式为"$(VAR:A=B)"(或"${VAR:A=B}"),意思是,将变量"VAR"中任何"A"字符结尾的字替换为"B"结尾的字。"结尾"的含义是空格之前(变量值的多个字以空格分开)。而对于变量其他部分的"A"字符不进行替换。

例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
在这个定义中,变量"bar"的值就为"a.c b.c
c.c"。使用变量的替换引用将变量"foo"以空格分开的值中的任何的字的尾字符"o"替换为"c",其他部分不变。而且假如在变量"foo"中假如存在"o.o"时,那么变量"bar"的值为"a.c
b.c c.c o.c"而不是"a.c b.c c.c c.c"。这一点需要明确。
另外一种引用替换的技术使用功能更强大的"patsubst"函数的任何功能。例如:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
这个例子同样使变量"bar"的值为"a.c b.c c.c"。

五 变量的套嵌引用

一个变量名(文本串)之中能够包含对其他变量的引用。这种情况我们称之为"变量的套嵌引用"或"计算的变量名"。
例如:
x = y
y = z
a := $($(x))
这个例子中,最终定义了"a"的值为"z"。来看一下变量的引用过程:首先最里边的变量引用"$(x)"被替换为变量名"y"(就是"$($(x))"被替换为了"$(y)"),之后"$(y)"被替换为"z"(就是a
:= z)。
看一个这样一个例子:
x = $(y)
y = z
z = Hello
a := $($(x))
这里的$($(x))被替换成了$($(y)),因为$(y)值是"z",所以,最终结果是:a:=$(z),也就是"Hello"。

递归变量的套嵌引用过程,也能够包含变量的修改引用和函数调用。看下边的例子,使用了make的文本处理函数:
x = variable1
variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
此例同样的实现"a:=Hello"。"$($($(z)))"替换为"$($(y))",之后再次被替换为"$($(subst
1,2,$(x)))"("$(x)"的值是"variable1",所以有"$($(subst
1,2,$(variable1)))")。函数处理之后为"$(variable2)"
之后对他在进行替换展开。最终,变量"a"的值就是"Hello"。
计算变量的名字能够由一个或多个变量引用同时加上字符串混合组成。例如:
a_dirs := dira dirb
1_dirs := dir1 dir2
a_files := filea fileb
1_files := file1 file2

ifeq "$(use_a)" "yes"
a1 := a
else
a1 := 1
endif

ifeq "$(use_dirs)" "yes"
df := dirs
else
df := files
endif

dirs := $($(a1)_$(df))
这个例子实现对变量"dirs"的定义,他的可能取值为"a_dirs"、"1_dirs"、"a_files"或"a_files"四个值其中之一,具体依赖于"use_a"和"use_dirs"的定义。

六 如何配置变量

makefile中变量的配置(也能够称之为定义)是通过"="(递归方式)或":="(静态方式)来实现的。

定义一个变量时需要明确以下几点:
(1)变量名之中能够包含函数或其他变量的引用,make在读入此行时根据已定义情况进行替换展开而产生实际的变量名。
(2)变量的定义值在长度上没有限制。变量定义较长时,一个好的做法就是将比较长的行分多个行来书写,除最后一行外行和行之间使用反斜杠(\)连接,表示一个完整的行。
(3)当引用一个没有定义的变量时,make默认他的值为空。
(4)一些特别的变量在make中有内嵌固定的值,但是这些变量允许我们在Makefile中显式得重新给他赋值。

六 追加变量值

我们能够在开始给变量定义一个基本的值,后续能够不断地根据需要给他增加一些必要值。在Makefile中使用"+="(追加方式)来实现对一个变量值的追加操作。

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s