二 配置目标make menuconfig的执行过程分析

    进入kernel的根目录,并输入make menuconfig,将会跳出如下图2.1所示的界面:二 配置目标make menuconfig的执行过程分析                                          图2.1
    此后,你可以修改相应的配置,修改完成后,退出保存。在根目录下输入ls -a,会发现其输出中有一个如图2.2所示的.config文件,该文件即是由make menuconfi*生的。有兴趣的话可以打开该文件看下,其中都是一些配置信息,用于定义各目标的编译方式的。二 配置目标make menuconfig的执行过程分析
                                          图2.2
    闲话少说,由以上命令可知,该命令会调用linux根目录下*makefile,其目标为menuconfig。查看*makefile,可以看到有如图2.3的内容:二 配置目标make menuconfig的执行过程分析
                                          图2.3
其中,该段代码执行的条件是config-targets的值为1,再次查看代码,可见该值的定义如下图2.4:二 配置目标make menuconfig的执行过程分析
                                          图2.4
以上命令我们逐条分析:
(1)ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
    它的意思是从MAKECMDGOALS变量中提取$(no-dot-config-targets)包含的值,若结果不为空,则继续执行下面语句。其中MAKECMDGOALS为makefile自带的环境变量,用于存放命令行指定的终极目标的值,在这里为menuconfig。显然,$(no-dot-config-targets)不含有menuconfig,因此其下面的语句不会被执行,我们也不再赘述
(2)ifeq ($(KBUILD_EXTMOD),)
    它的定义如下图2.5,其中SUBDIRS是老式的语法,只是为了兼容支持。新的语法为ifeq ("$(origin M)", “command line”)。它的意思是若在命令行中指定了M=xxx,则KBUILD_EXTMOD的值就等于xxx。由于我们没有在命令行指定M变量,则ifeq ($(KBUILD_EXTMOD),)会返回true,并执行其后面的语句。
二 配置目标make menuconfig的执行过程分析
                               图2.5
3)ifneq ($(filter config %config,$(MAKECMDGOALS)),)
    从$(MAKECMDGOALS)变量中过滤config和%config的值,其中%为通配符,在makefile中表示匹配一个或多个字符。故$(MAKECMDGOALS)的值menuconfig与%config匹配,config-tartgets的值被设置为1,所以图2.3的后续代码会被执行。
    回到图2.3的内容,它先将arch/arm64/Makefile包含进来,然后导出两个环境变量,其后定义了两个目标config和%config。menuconfig会匹配到%config那一行的目标,它的依赖为scripts_basic outputmakefile和FORCE,我们分别介绍如下:
(1)scripts_basic定义如下图2.6。其中的build我们前面已经介绍过是定义在kbuild.include中的,其定义如下图2.7所示。我们将其代入2.6中后,即为:
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=scripts/basic
即它会调用scripts下的Makefile.build文件,然后将obj=scripts/basic作为参数传入该makefile。由于makefile.build文件是编译目标时调用的通用文件,我们将其分析放到第六章。
二 配置目标make menuconfig的执行过程分析
                            图2.6
二 配置目标make menuconfig的执行过程分析
                            图2.7
    结合第六章的分析,我们知道以上调用会将scripts/basic目录下的makefile包含进去,然后编译该makefile所指定的目标。该makefile的内容如下图2.8:
二 配置目标make menuconfig的执行过程分析
                            图2.8
    hostprogs-y表示编译的fixdep和bin2c两个目标都会用主机架构相同的工具链编译,并且可以在主机上运行的文件。
    那么hostprogs-y定义的目标是如何编译的呢?在makefile.build中有图2.9这段内容,即若定义有host相关的目标,则将scripts/Makefile.host文件包含进来。
二 配置目标make menuconfig的执行过程分析
                                    图2.9
    我们可以发现在该文件下有如下图2.10所示的内容,hostprogs-y和hostpogs-m一起构成了__hostprogs,它们会被分成两类。一类为通过单个c文件编译成可执行文件的目标,它们被归类到host-csingle中,另一类是多个c文件编译成.o文件后再链接成可执行文件的目标,它们被归类到host-cmulti中。
二 配置目标make menuconfig的执行过程分析
                                    图2.10
host-csingle目标的规则如图2.11,即它会调用HOSTCC将相应的.c文件编译成可执行文件。其中HOSTCC定义在顶层Makefile中,如图2.12所示。
二 配置目标make menuconfig的执行过程分析
                                    图2.11
二 配置目标make menuconfig的执行过程分析
                                    图2.12
    简单地说,scripts_basic的主要目的是编译了主机可执行文件fixdep和bin2c,用于支持其它主机相关目标的生成。
(2)outputmakefile的规则如图2.13,只有定义了KBUILD_SRC,才会执行其下的命令。
二 配置目标make menuconfig的执行过程分析
                                    图2.13
    KBUILD_SRC的定义位于图2.14的sub-make规则中,而该规则只有在KBUILD_OUTPUT有定义的情况才可能会执行。
二 配置目标make menuconfig的执行过程分析
                                    图2.14
    KBUILD_OUTPUT的定义如图2.15,即它是由命令行参数O=xxx定义的。该参数用于指定编译目标的输出目录。在图2.14中,我们也看到了sub-make的命令中用-C $(KBUILD_OUTPUT)指定了编译目录。
二 配置目标make menuconfig的执行过程分析
                                    图2.15
    上面的内容其实就是说,只有在命令行中指定了O=xxx参数后,outputmakefile规则的命令才会执行。下面我们再分别看下这两条命令,第一条ln命令用于建立一个软链接,将kernel源码链接为当前目录下(即命令O指定的xxx)的source。第二条命令调用了scripts目录下的mkmakefile脚本,该脚本比较简单,就是在xxx目录下创建了一个名叫Makefile的文件,文件内容由mkmakefile生成,具体的内容可以打开该脚本看下。
    简单小结下,outputmakefile主要的工作是在命令行指定的输出目录中创建了一个source软链接,该链接指向了kernel的源码,然后它会调用scripts下的mkmakefile脚本在输出目录中创建一个名叫Makefile的文件。
(3)FORCE是一个既没有依赖,也没有命令的伪目标,主要目的是用于强制执行目标的生成,具体内容可以参考第六章。
(4)最后该规则会调用$(MAKE) $(build)=scripts/kconfig [email protected]命令,我们将其展开后为:
    make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig
即它还是会调用Makeile.build文件,并包含进scripts/kconfig下的makefile文件,编译目标为menuconfig。
    我们打开scripts/kconfig/makefile,发现其中有menuconfig目标的规则如图2.16。它依赖于$(obj)/mconf,即scripts/kconfig/mconf,规则的命令展开后为scripts/kconfig/mconf $(Kconfig)。
二 配置目标make menuconfig的执行过程分析
                                    图2.16
    其中mconf可以由该目录下的mconf.c编译生成,而Kconfig定义如图2.17所示。总结以下该命令就是以Kconfig为参数调用mconf命令,从图2.16可以看出其他的几种配置命令也是调用相应的xconf命令完成。具体各种conf的功能已经超出了makefile的范畴,这里不再展开。
二 配置目标make menuconfig的执行过程分析
                 图2.17