Kbuild.include中提供了内核编译时基础函数,其中echo-cmd变量的功能让我一直能疑惑。其定义如下:
echo-cmd = $(if $($(quiet)cmd_$(1)),\
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
从字面理解,应该是回显命令,而且初看也是打印命令到终端。但是,事实上,那只是他一半的功能,另一半是执行命令。空口无凭,来试一下
squote := '
escsq = $(subst $(squote),'\$(squote)',$1)
echo-cmd = $(echo ' $(call escsq,ls)';)
vmlinux:FORCE
$(echo-cmd) ls
FORCE:
root@ubuntu:~/Desktop# make -f echo-cmd.mk
ls
39-usb-reboot.rules linux-3.7.4.tar.xz udev
展开这个规则,首先escsq = $(subst $(squote),'\$(squote)',$1)是一个表达式,call函数除了可以调用函数,还可以调用表达式,形如下面的规则:
reverse = $(2) $(1)
squeue=$(1) $(2)
__all:
@echo foo=$(call reverse,a,b)
@echo foo=$(call squeue,a,b)
执行的结果是:
root@ubuntu:~/Desktop# make -f call.mk
foo=b a
foo=a b
因此不用怀疑$(call escsq,ls)这句的正确性,call传递给escsq的参数1是ls,因此,表达式escsq = $(subst $(squote),'\$(squote)',$1)的结果为 echo ls。最终echo-cmd变量的值是echo 'ls';。把这个变量在vmlinux目标中扩展开,就是
vmlinux:FORCE
echo 'ls';ls
这个规则中有两条命令,makefile规定,命令间用分号分割,因此这个规则做了两件事:1.显示命令,2.执行命令
最后,看下Kbuild.include中完整的echo-cmd命令
echo-cmd = $(if $($(quiet)cmd_$(1)),\
echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
这里可以分别用@和空带入到$(quiet)和$(echo-why)中。一般cmd_$(1)会对应一个变量,如cmd_ls=ls,这样应该可以理解这个变量的作用了~