makefile自动化变量

15.5.3、自动化变量
在上述的模式规则中,目标和依赖文件都是一系例的文件,那么我们如何书写一个命令来完成从不同的依赖文件生成相应的目标?因为在每一次的对模式规则的解析时,都会是不同的目标和依赖文件。
自动化变量就是完成这个功能的。在前面,我们已经对自动化变量有所提涉,相信你看到这里已对它有一个感性认识了。所谓自动化变量,就是这种变量会把模式中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。
下面是所有的自动化变量及其说明:
$@
    表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。
$%
    仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是"bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
$ <
    依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$?
    所有比目标新的依赖目标的集合。以空格分隔。
$^
    所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
$+
    这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。
$*
   这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。这个变量对于构造有关联的文件名是比较有较。如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的后缀是make所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因为".c"是make所能识别的后缀名,所以,"$*"的值就是"foo"。这个特性是GNU make的,很有可能不兼容于其它版本的make,所以,你应该尽量避免使用"$*",除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的,那么"$*"就是空值。
当你希望只对更新过的依赖文件进行操作时,"$?"在显式规则中很有用,例如,假设有一个函数库文件叫"lib",其由其它几个object文件更新。那么把object文件打包的比较有效率的Makefile规则是:
    lib : foo.o bar.o lose.o win.o
            ar r lib $?
在上述所列出来的自动量变量中。四个变量($@、$、$%、$*)在扩展时只会有一个文件,而另三个的值是一个文件列表。这七个自动化变量还可以取得文件的目录名或是在当前目录下的符合模式的文件名,只需要搭配上"D"或"F"字样。这是GNU make中老版本的特性,在新版本中,我们使用函数"dir"或"notdir"就可以做到了。"D"的含义就是Directory,就是目录,"F"的含义就是File,就是文件。
下面是对于上面的七个变量分别加上"D"或是"F"的含义:
$(@D)
    表示"$@"的目录部分(不以斜杠作为结尾),如果"$@"值是"dir/foo.o",那么"$(@D)"就是"dir",而如果"$@"中没有包含斜杠的话,其值就是"."(当前目录)。
$(@F)
    表示"$@"的文件部分,如果"$@"值是"dir/foo.o",那么"$(@F)"就是"foo.o","$(@F)"相当于函数"$(notdir $@)"。
"$(*D)"
"$(*F)"

    和上面所述的同理,也是取文件的目录部分和文件部分。对于上面的那个例子,"$(*D)"返回"dir",而"$(*F)"返回"foo"
"$(%D)"
"$(%F)"

    分别表示了函数包文件成员的目录部分和文件部分。这对于形同"archive(member)"形式的目标中的"member"中包含了不同的目录很有用。
"$(
"$(

    分别表示依赖文件的目录部分和文件部分。
"$(^D)"
"$(^F)"

    分别表示所有依赖文件的目录部分和文件部分。(无相同的)
"$(+D)"
"$(+F)"

    分别表示所有依赖文件的目录部分和文件部分。(可以有相同的)
"$(?D)"
"$(?F)"

    分别表示被更新的依赖文件的目录部分和文件部分。
最后想提醒一下的是,对于"$<,为了避免产生不必要的麻烦,我们最好给$后面的那个特定字符都加上圆括号,比如,"$(<)“就要比"$”要好一些。
还得要注意的是,这些变量只使用在规则的命令中,而且一般都是"显式规则"和"静态模式规则"(参见前面"书写规则"一章)。其在隐含规则中并没有意义。

来自:http://linux.chinaunix.net/techdoc/develop/2006/11/29/945016.shtml

 

补充:

Makefile Automatic Variable

在规则被执行时,规则的目标文件和依赖文件和书写 makefile 时可能存在不一致,有两种情况:目标文件和依赖文件可能不是存在于当前工作目录(通过指定目录搜索目录,make 可以在其它目录下找到指定的文件);在模式规则中,规则的目标文件和依赖文件都是代表一类文件。对于这两种情况,在命令中显然不能指定文件名,否则 make 将提示错误(找不到指定的文件)或者失去模式规则存在的意义。为了在命令中解决通过指定文件名而带来的错误,需要在命令中使用自动化变量。

makefile 的自动化变量(automatic variable)的值由具体的规则来决定。不同的规则其所代表的目标文件名、依赖文件名不同,在 make 执行过程中,自动化变量获取的值根据规则的目标文件和依赖文件的不同而不同。

注意:自动化变量常用在规则中,用在其它地方时,其值是不确定值。故建议仅用于规则中。

自动化变量列表

 自动化变量
 自动化变量的目标部分
 自动化变量的文件名部分
 @ @D @F
 % %D %F
 < <D <F
 ? ?D ?F
 ^ ^D ^F
 + +D +F
     注释1
 |D
 |F
 * *D *F

注释 1 :如果没有特别说明,依赖通常指 normal 依赖,不包括 order-only 依赖。order-only 依赖使用管道字符(|)和 normal 依赖分隔。

$@
1 代表规则的目标文件名。
2 在模式规则、多目标规则中,它表示的是触发规则被执行的目标文件名。
3 如果目标文件是一个文档文件(.a),代表文档文件名(非文档文件的成员名)。

$%
1 规则的目标文件是一个文档文件(.a)时,代表文档文件的第一个成员名。
2 如果目标文件没有指明文档文件的成员(指明的文档文件 1.a(1.o 2.o)),其值为空。

$<
1 规则的第一个依赖文件名。
2 如果是隐含规则,它代表通过目标指定的第一个依赖文件。

$?
1 所有比目标文件更新的依赖文件列表,使用空格分隔。
2 目标的依赖中可以有重复的依赖文件,变量 ? 的值会去掉重复的依赖文件。

$^
1 规则的所有依赖文件列表,使用空格分隔。
2 目标的依赖中可以有重复的依赖文件,变量 ^ 的值会去掉重复的依赖文件。

$+
1 规则的所有依赖文件列表,使用空格分隔。
2 目标的依赖中可以有重复的依赖文件,变量 + 的值会保留重复的依赖文件。

$|
1 规则的所有 order-only 依赖中存在,而 normal 依赖中不存在的依赖文件列表,使用空格分隔。
2 如果规则没有 order-only 依赖,变量 | 的值为空。
3 如果规则的order-only 依赖和 normal 依赖相同,变量 | 的值为空。

$*
1 在模式规则中,它代表目标文件的茎(stem),茎是模式字符(%)所代表的部分。
2 当目标文件名中存在目录时,茎包含目录部分和模式字符(%)所代表的部分。
3 假设文件名为 dir/a.foo.b,当目标文件的模式为 a.%.b 时,$* 的值为 dir/foo。

在自动化变量中,@、%、* 是对目标文件的操作;<、?、^、+、| 是对依赖文件的操作。
在自动化变量中,@、%、<、* 是代表一个文件名;?、^、+、| 是代表文件名列表。

make 提供的基本自动化变量获取的值是完整的文件名(包括目标部分和文件名部分),还可以通过在自动化变量后面加入 D(directory) 或者 F(file)字符,表示获取基本自动化变量的目标部分或者文件名部分。

在自动化变量的结尾加入 D 字符(@D、%D、<D、?D、^D、+D、|D、*D)
1 代表自动化变量值的目录部分,但不包含目标部分的最后一个斜线。
2 文件名不存在斜线,其值就是 .(表示当前目录 ./)。
3 通过 dir 函数获取的目录部分包含最后一个斜线。文件名如果不存在斜线,其值就是 ./(表示当前目录)。

在自动化变量的结尾加入 F 字符(@F、%F、<F、?F、^F、+F、|F、*F)
1 代表自动化变量值的非目录部分。
2 等同于函数 notdir 的功能。如 $(@F) 等同于 $(notdir $@)。

示例 1
Makefile 文件的内容如下
# 1.o 和 test.o 文件存在,但是修改了 1.c 文件
%.o : 1.c test.c 1.h 1.c | 1.c test.c 1.h 1.c 2.c
      @echo $$\@ = $@
      @echo $$\% = $%
      @echo $$\< = $<
      @echo $$\? = $?
      @echo $$\^ = $^
      @echo $$\+ = $+
      @echo $$\| = $|
      @echo $$\* = $*

在命令提示符下输入 “make -R 1.o”,执行结果如下:
$@ = 1.o
$% =
$< = 1.c
$? = 1.c
$^ = 1.c test.c 1.h
$+ = 1.c test.c 1.h 1.c
$| = 2.c
$* = 1

在命令提示符下输入 “make -R test.o”,执行结果如下:
$@ = test.o
$% =
$< = 1.c
$? = 1.c
$^ = 1.c test.c 1.h
$+ = 1.c test.c 1.h 1.c
$| = 2.c
$* = test

示例 2
Makefile 文件的内容如下
# 当前工作目录下存在文件 makefile
# /etc 目录下存在文件 issue
# /usr/bin 目录下存在文件 make print
VPATH = /etc /usr/bin
GPATH = $(VPATH)

print : issue make makefile
      @echo $$\@ = $@
      @echo $$\^ = $^
      @echo $$\^D = $(^D)
      @echo $$\^F = $(^F)
      @echo dir = $(dir $^)
      @echo notdir = $(notdir $^)

在命令提示符下输入 “make”,执行结果如下:
$@ = /usr/bin/print
$^ = /etc/issue /usr/bin/make makefile
$^D = /etc /usr/bin .
$^F = issue make makefile
dir = /etc/ /usr/bin/ ./
notdir = issue make makefile

示例 3
Makefile 文件的内容如下
1.a(1.o 2.o) : 1.o 2.o
      @echo $$\@ = $@
      @echo $$\% = $%
      @echo $$\^ = $^
      @echo $$\+ = $+

在命令提示符下输入 “make”,执行结果如下:
$@ = 1.a
$% = 1.o
$^ = 1.o 2.o
$+ = 1.o 2.o

示例 4
# 当前工作目录下不存在文件 1.o
# /home 目录存在文件 1.o
VPATH = /home
GPATH = $(VPATH)

%.o : 1.c test.c 1.h 1.c
      @echo $$\* = $*

在命令提示符下输入 “make 1.o”,执行结果如下:
$* = /home/1
来自: http://blog.sina.com.cn/s/blog_87edb13801012sz3.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值