linux make xxxconfig执行过程
Linux kernel之make xxxconfig
Linux kernel编译之前需要做裁剪配置,即需要生成一个.config文件,这个文件定义了很多内核feature或module等配置信息,下图展示了一个示例部分:
那么,如何来生成这个.config配置文件?
常用的主要方式:
make config;
make menuconfig;
make defconfig;
make xconfig;
本文,就来说说这个make xxxconfig是怎么run的。
首先要读取的就是顶层的Makefile文件,我们找到这个xxxconfig.
linux/Makefile
74-80行,我们执行的命令是make xxxconfig,故变量M没有在命令行command line中定义,也没有使用SUBDIRS。故KBUILD_EXTMOD为空。这里的命令行参数M=<dir>以及SUBDIRS=<dir>用于去编译其他的额外模块。
486-493行,由于KBUILD_EXTMOD为空,程序跑到这里,然后再487行判断make命令的target是否是config或通配%config, 如果是,则设置config-targets为1. 这里$(MAKECMDGOALS)为make内置变量,其值为make时指定的target,比如make all,那这个值就是all。很显然,我们的target是xxxconfig, 会通配%config, 故config-targets为1.
504-523行,由于config-targets为1,故程序会跑504-523这些行代码。从这里,我们可以看出来,无论是make config,还是make xxxconfig,都是在当前目录中先创建目录include/linux和include/config, 然后执行命令 $(MAKE) $(build)=scripts/kconfig [email protected]
$(MAKE)是make内置变脸,代表make命令本身。那么这个$(build)在哪里定义?
Linux/Makefile
Linux/scripts/Kbuild.include
在linux/Makefile的335行include了scripts/Kbuild.include文件,在这个Kbuild.include文件的164行定义了build变量。
所以$(MAKE) $(build)=scripts/kconfig [email protected],就展开为
$(MAKE) -f scripts/Makefile.build obj=scripts/kconfig [email protected]
即程序调用子make程序,指定的makefile文件为scripts/Makefile.build, target不变,还是为config或xxxconfig,并且还定义了一个命令行变量obj,其值为scripts/kconfig.
我们接着看这个子make程序
Linux/scripts/Makefile.build
5行,设置变量src的值为$(obj),即src := scripts/kconfig.
42行,设置变量kbuild-dir := $(src), 即kbuild-dir := scripts/kconfig.
43行,wildcard函数为获取当前目录下匹配$(kbuild-dir)/Kbuild的所有文件,如果为空,则设置$(kbuild-dir)/Makefile为kbuild-file的值。实际上,在这个目录scripts/kconfig/下,并没有Kbuild文件,故kbuild-file为scripts/kconfig/Makefile.
44行,include文件scripts/kconfig/Makefile.
Linux/scripts/kconfig/Makefile
从上面的代码片段可以看出来,所有的config target是怎么处理的了。比如,make menuconfig,最终的执行是scripts/kconfig/mconf $(Kconfig), $(Kconfig)就是Kconfig。
下面列了一下几个target和最终处理的程序的对照:
‘make menuconfig’ scripts/kconfig/mconf Kconfig
‘make config’ scripts/kconfig/conf --oldaskconfig Kconfig
‘make xconfig’ scripts/kconfig/qconf Kconfig
那这里的mconf, conf, qconf是如何生成的呢?
我们接着看这个文件linux/scripts/kconfig/Makefile
Linux/scripts/kconfig/Makefile
这里hostprogs-y就对应这我们的target所使用的程序*conf,故 make config对应的conf是一定包含的(160行),其他的就得看make的target是什么了,比如make menuconfig,那么其对应的mconf就会被包含进hostprogs-y(167行)。
这里又引出一个问题,就是这个hostprogs-y变量怎么处理这些个conf, mconf?
我们先来看看到目前位置的make的调用关系:
Linux/Makefile ---> Linux/scripts/Kbuild.include
---> Linux/scripts/Makefile.build ---> Linux/scripts/kconfig/Makefile
hostprogs-y在Linux/scripts/Makefile.build中有如下信息:
Linux/scripts/Makefile.build
由于hostprogs-y和hostprogs-m值不相等(make xxxconfig),故这里又include了文件scripts/Makefile.host
Linux/scripts/Makefile.host
33行先将$(hostprogs-y)赋值给__hostprogs。此时__hostprogs就等于conf mconf(或qconf)
44行设置host-cobjs为__hostprogs列表中的对象,每个对象加后缀-objs,即host-cobjs为conf-objs mconf-objs(或qconf-objs)
接着看这个文件Makefile.host
Linux/scripts/Makefile.host
81行给host-cobjs添加前缀scripts/kconfig/, 此时host-cobjs为scripts/kconfig/conf-objs scripts/kconfig/mconf-objs(或scripts/kconfig/qconf-objs)
133-134行给出了host-cobjs的依赖和命令。if_changed_dep定义在linux/scripts/Kbuild.include
Linux/scripts/Kbuild.include
上面这段代码中的$(1)为参数host-cobjs,228行的cmd_$(1)即为linux/scripts/Makefile.host中定义的cmd_host-cobjs,即: $(HOSTCC) $(hostc_flags) -c -o [email protected] $<
229行的scripts/basic/fixdep程序,参考其对应的c文件scripts/basic/fixdep.c,主要是将参数等信息写入到文件scripts/kconfig/.$(host-cobjs).tmp, 即.conf.tmp以及.mconf.tmp(或.qconf.tmp)
231行重命名文件为.conf.cmd以及.mconf.cmd(或.qconf.cmd)
调用完if_changed_dep后(准确地说,这不叫调用,只是展开了if_changed_dep表达式),回到上一级linux/scripts/Makefile.host
Linux/scripts/Makefile.host
在Makefile.host的最后(168行), 将host-cobjs加入到targets中。
我们再来完善下makefile的调用层级关系:
Linux/Makefile ---> Linux/scripts/Kbuild.include
---> Linux/scripts/Makefile.build ---> Linux/scripts/kconfig/Makefile
---> Linux/scripts/Makefile.host
在linux/scripts/Makefile.host设置完targets后,我们回到linux/scripts/Makefile.build的最后:
Linux/scripts/Makefile.build
469-473行就是在解析targets的值,这个值有对应的cmd文件,并且Include了这个cmd文件。
这里targets包含了host-cobjs,即包含了conf, mconf(或qconf), 而.conf.cmd, mconf.cmd(活.qconf.cmd)在Makefile.host的133行通过Kbuild.include的if_changed_dep生成了。
说到现在,我们貌似还没有看到scripts/kconfig/conf, scripts/kconfig/mconf这个对象怎么生成。
其实,这两个对象已经生成了,生成的方式在Linux/scripts/Makefile.build的473行include的cmd文件中。
我们来看看这个include的cmd文件的内容就清楚了。
Linux/scripts/kconfig/.conf.cmd
Linux/scripts/kconfig/.mconf.cmd
看到了吧,这两个cmd文件给出了conf, mconf生成的命令。
至此, make config, make meconfig之类的配置命令就转为调用的相应的scripts/kconfig/*conf来配置了。
对于scripts/kconfig/conf程序,对应的c文件为conf.c zconf.tab.c
对于scripts/kconfig/mconf程序,对应的c文件为 mconf.c, zconf.tab.c, lxdialog/checklist.c, lxdialog/util.c, lxdialog/inputbox.c, lxdialog/textbox.c, lxdialog/yesno.c, lxdialog/menubox.c
Linux/scripts/kconfig/Makefile