曲径通幽论坛

标题: call 函数 -- 传递参数到变量 [打印本页]

作者: beyes    时间: 2011-6-18 16:25
标题: call 函数 -- 传递参数到变量
通过 call 函数可以将一个变量定义为一个复杂的表达式,它的语法格式为:
$(call VAR, 参数1, 参数2,...)
call 函数可以将 "参数1“ ,”参数2“ 传递到 VAR 中,然后 VAR 根据传递进来的参数进行展开成一个完整的表达式。

在函数执行时,参数1,参数2, 参数3, ... 等等会依次赋值到临时变量 $(1), $(2), $(3) ... 上,而这些临时变量则是定义在 VAR 中的。看下面例子演示:
[Plain Text] 纯文本查看 复制代码
reverse = $(2)$(1)

foo = $(call reverse, a, b)

all:
    @echo "foo = $(foo)"

运行输出:
$ make
foo =  b a
参数 a 传递到 $(1) 中,参数 b 传递到 $(2) 中;而在变量 reverse 中并不要求 $(1) ,$(2) 这些变量有一定的顺序。也可以说,$(1), $(2) 这些是形参,而 a, b 这种是实参。

下面再演示一个复杂的例子:
[Plain Text] 纯文本查看 复制代码
lsfirstpath = $(subst /ls, ,$(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))

lsPath := $(call lsfirstpath,ls)

all:
    @echo "command 'ls' is in \"$(call lsfirstpath,ls)\""

运行输出:
[beyes@beyes exp2]$ make
command 'ls' is in "/bin "
在上面的 Makefile 代码中,$(PATH) 是共有的环境变量,它存放各种路径名,这些路径名用冒号隔开。

$(subst :, ,$(PATH)) 这句用来去掉 $(PATH) 中的冒号。

$(addsuffix /$(1),$(subst :, ,$(PATH))) 这句为每个路径名后面添加上 "/$(1)",因为这里的 $(1) 其实就是 $(call lsfirstpath,ls) 中传递过去的 ls,所以此举执行之后会变成:
/usr/lib/ccache/ls /usr/local/bin/ls /usr/binls  ... ...
等等。

$(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))) 这句中的 wildcard 函数是用来匹配文件是否存在,如果存在则保留下来,不存在就去掉。

$(subst /ls, ,$(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH))))) 最后当我们找到了 ls 所在的路径后,去掉 ”/ls“ 后就得出了它所在的目录。


另外,还有 $(0) 这个变量,它代表的是 VAR 本身。

call 函数还可以嵌套的调用。在嵌套调用时,每一层都有自己特定的局部变量($(1), $(2)...等),这些局部变量不会传递到下一层去,如:
[Plain Text] 纯文本查看 复制代码
k = $(2)$(1)

map = $(foreach a,$(2),$(call $(1),$(a),good-))

o = $(call map,k,are you ok)

all:
    @echo "$(o)"

运行输出:
[beyes@beyes exp3]$ make
good-are good-you good-ok
在上面的 Makefile 文件中,第 1 层 call 是 $(call map,k,are you ok) ,在这里 $(1) 和 $(2) 分别为 kare you ok ,所以对已经定义的表达式 map 进行展开后得:
$(foreach a,are you ok,$(call k,$(a),good-))
第二层 call 为 $(call k,$(a),good-),在这里,它有自己的 $(1) 和 $(2);$(1) 就是 $(a) -- 就是 foreach 函数捡取的值(依次为 are you ok),$(2) 为 good- 。

要非常小心的是,在对 call 和 foreach 这些函数应用时,一定要注意空格,如果不小心多了空格,看到的结果基本上不是你所期望的。




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2