Makefile call函数

8.6 call函数


“ call”函数是唯一一个可以创建定制化参数函数的引用函数。使用这个函数可以
实现对用户自己定义函数引用。我们可以将一个变量定义为一个复杂的表达式,用“ call”
函数根据不同的参数对它进行展开来获得不同的结果。
¾ 函数语法:
$(call VARIABLE,PARAM,PARAM,...)


¾ 函数功能:在执行时,将它的参数“ PARAM”依次赋值给临时变量“ $(1)”、“ $(2)”
(这些临时变量定义在“ VARIABLE”的值中,参考下边的例子)…… call 函
数对参数的数目没有限制,也可以没有参数值,没有参数值的“ call”没有任何
实际存在的意义
。执行时变量“ VARIABLE”被展开为在函数上下文有效的临时
变量,变量定义中的“ $(1)”作为第一个参数,并将函数参数值中的第一个参数
赋值给它;变量中的“ $(2)”一样被赋值为函数的第二个参数值;依此类推(变
量$(0)代表变量“ VARIABLE”本身)。之后对变量“ VARIABLE” 表达式的计
算值。

¾ 返回值:参数值“ PARAM”依次替换“ $(1)”、“ $(2)”…… 之后变量“ VARIABLE”
定义的表达式的计算值。


¾ 函数说明: 1. 函数中“ VARIBLE”是一个变量名,而不是变量引用。因此,通
常“ call”函数中的“ VARIABLE”中不包含“ $”(当然,除非此变量名是一个
计算的变量名)。 2. 当变量“ VARIBLE”是一个 make 内嵌的函数名时(如“ if”、
“ foreach”、“ strip”等),对“ PARAM”参数的使用需要注意,因为不合适或
者不正确的参数将会导致函数的返回值难以预料。 3. 函数中多个“ PARAM”之
间使用逗号分割。 4. 变量“ VARIABLE”在定义时不能定义为直接展开式!只
能定义为递归展开式。

¾ 函数示例:
首先,来看一个简单的例子。
示例 1:
reverse = $(2) $(1)  #注意此处不能定义为直接展开式(“:=”)!只能定义为递归展开式(“=”)。
foo = $(call reverse,a,b)
变量“ foo”的值为“ ba”。这里变量“ reverse”中的参数定义顺序可以根据需
要来调整,并不是需要按照“ $(1)”、“ $(2)”、“ $(3)”…… 这样的顺序来定义。

 

看一个稍微复杂一些的例子。我们定义了一个宏“ pathsearch”来在“ PATH”
路径中搜索第一个指定的程序。
示例 2:
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
LS := $(call pathsearch,ls)
变量“ LS”的结果为“ /bin/sh”。执行过程:函数“ subst”将环境变量“ PATH”
转换为空格分割的搜索路径列表;“ addsuffix”构造出可能的可执行程序“ $(1)”
(这里是“ ls”)带路径的完整文件名(如:“ /bin/$(1)”),之后使用函数“ wildcard”
匹配,最后“ firstword”函数取第一个文件名。


函数“ call”以可以套嵌使用。每一层“ call”函数的调用都为它自己的局部变量
“ $(1)”等赋值,覆盖上一层函数为它所赋的值。
示例 3:
map = $(foreach a,$(2),$(call $(1),$(a))) #将下方call函数传入的参数 $(1) $(2)带入即可展开
o = $(call map,origin,o map MAKE)

那么变量“ o”的值就为“ file file default”。我们这里使用了“ origin”函数(查找变量的定义方式)。

我们分析函数的执行过程:首先,“ o=$(call map,origin, o map MAKE)”这个函数
调用使用了变量“ map”所定义的表达式;使用内嵌函数名“ origin”作为它的
第一个参数值,使用Makefile中的变量“ o map MAKE”作为他的第二个参数值。
当使用“ call”函数展开后等价于“ $(foreach a,o map MAKE,$(origin $(a)))”。
¾ 注意: 和其它函数一样,“ call”函数会保留出现在其参数值列表中的空字符。
因此在使用参数值时对空格处理要格外小心。如果参数中存在多余的空格,函
数可能会返回一个莫名奇妙的值。为了安全,在变量作为“ call”函数参数值之
前,应去掉其值中的多余空格(可以使用 “ strip”函数 )。

 

关于 origin 函数:

8.9 origin函数
函数“ origin”和其他函数不同,函数“ origin”的动作不是操作变量(它的参数)。
它只是获取此变量(参数)相关的信息,告诉我们这个变量的出处
(定义方式)。
¾ 函数语法:
$(origin VARIABLE)
¾ 函数功能: 函数“ origin”查询参数“ VARIABLE”(一个变量名)的出处。
¾ 函数说明:“ VARIABLE”是一个变量名而不是一个变量的引用。因此通常它不
包含“ $”(当然,计算的变量名例外)。

¾ 返回值: 返回“ VARIABLE”的定义方式。用字符串表示。
函数的返回情况有以下几种:
1. undefined
变量“ VARIABLE”没有被定义。
2. default
变量“ VARIABLE”是一个默认定义(内嵌变量)。如“ CC”、“ MAKE”、“ RM”
等变量(参考 10.3 隐含变量 一节)。如果在Makefile中重新定义这些变量,
函数返回值将相应发生变化。
3. environment
变量“ VARIABLE” 是一个系统环境变量, 并且make没有使用命令行选项“ -e”
( Makefile中不存在同名的变量定义,此变量没有被替代)。参考 10.7 make
的命令行选项 一节
4. environment override
变量“ VARIABLE”是一个系统环境变量,并且make使用了命令行选项“ -e”。
Makefile中存在一个同名的变量定义,使用“ make -e”时环境变量值替代了
文件中的变量定义。 参考 9.7 make的命令行选项 一节
5. file
变量“ VARIABLE”在某一个 makefile 文件中定义。
6. command line
变量“ VARIABLE”在命令行中定义。
7. override
变量“ VARIABLE”在 makefile 文件中定义并使用“ override”指示符声明。
8. automatic
变量“ VARIABLE”是自动化变量。参考 10.5.3 自动化变量 一节
函数“ origin”返回的变量信息对我们书写 Makefile 是相当有用的,可以使我们在
使用一个变量之前对它值的合法性进行判断。假设在 Makefile 其包了另外一个名为
bar.mk 的 makefile 文件。我们需要在 bar.mk 中定义变量“ bletch”(无论它是否是一
个环境变量),保证“ make –f bar.mk”能够正确执行。另外一种情况,当 Makefile 包
含 bar.mk,在 Makefile 包含 bar.mk 之前有同样的变量定义,但是我们不希望覆盖 bar.mk
中的“ bletch”的定义。一种方式是:我们在 bar.mk 中使用指示符“ override”声明这

个变量。但是它所存在的问题时,此变量不能被任何方式定义的同名变量覆盖,包括命
令行定义。另外一种比较灵活的实现就是在 bar.mk 中使用“ origin”函数,如下:
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
这里,如果存在环境变量“ bletch”,则对它进行重定义。
ifneq "$(findstring environment,$(origin bletch))" ""
bletch = barf, gag, etc.
endif
这个例子实现了:即使环境变量中已经存在变量“ bletch”,无论是否使用“ make -e”
来执行 Makefile,变量“ bletch”的值都是“ barf,gag,etc”(在 Makefile 中所定义的)。
环境变量不能替代文件中的定义。
如果“ $(origin bletch)”返回“ environment”或“ environment override”,都将对
变量“ bletch”重新定义。关于函数“ firststring”可参考 8.2 文本处理函数 一节
 

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值