|
通过 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)"
运行输出:参数 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) 分别为 k 和 are 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 这些函数应用时,一定要注意空格,如果不小心多了空格,看到的结果基本上不是你所期望的。 |
|