linux make xxxconfig执行过程

Linux kernel之make xxxconfig

Linux kernel编译之前需要做裁剪配置,即需要生成一个.config文件,这个文件定义了很多内核feature或module等配置信息,下图展示了一个示例部分:

linux make xxxconfig执行过程

linux make xxxconfig执行过程

那么,如何来生成这个.config配置文件?

常用的主要方式:

make config;

make menuconfig;

make defconfig;

make xconfig;

本文,就来说说这个make xxxconfig是怎么run的。

首先要读取的就是顶层的Makefile文件,我们找到这个xxxconfig.

linux/Makefile

linux make xxxconfig执行过程

linux make xxxconfig执行过程

linux make xxxconfig执行过程

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 make xxxconfig执行过程

Linux/scripts/Kbuild.include

linux make xxxconfig执行过程

在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

linux make xxxconfig执行过程

linux make xxxconfig执行过程

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

linux make xxxconfig执行过程

从上面的代码片段可以看出来,所有的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

linux make xxxconfig执行过程

这里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

linux make xxxconfig执行过程

由于hostprogs-y和hostprogs-m值不相等(make xxxconfig),故这里又include了文件scripts/Makefile.host

Linux/scripts/Makefile.host

linux make xxxconfig执行过程

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

linux make xxxconfig执行过程

linux make xxxconfig执行过程

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

linux make xxxconfig执行过程

上面这段代码中的$(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

linux make xxxconfig执行过程

在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

linux make xxxconfig执行过程

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 make xxxconfig执行过程

Linux/scripts/kconfig/.mconf.cmd

linux make xxxconfig执行过程

看到了吧,这两个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

linux make xxxconfig执行过程