Based on u-boot-2014-10.

 

当我们执行make xxx_defconfig时,顶层Makefile中唯一的匹配目标是:

 

%config: scripts_basic outputmakefile FORCE

    +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/multiconfig.sh $@

 

依赖条件1:scripts_basic

scripts_basic:

    $(Q)$(MAKE) $(build)=scripts/basic

 

    $(Q)rm -f .tmp_quiet_recordmcount

 

依赖条件2:outputmakefile

outputmakefile:

ifneq ($(KBUILD_SRC),)

    $(Q)ln -fsn $(srctree) source

    $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile  

    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)

endif

 

此时由于KBUILD_SRC为空,所以此条依赖条件并不执行。

依赖条件3:FORCE

FORCE:

执行命令:

+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/multiconfig.sh $@

几个变量:

$(Q) = @  

$(CONFIG_SHELL) = /bin/sh

$(MAKE) = make

$@ = %config

$(srctree) = .

所以依赖条件1变成:

scripts_basic:

    @make $(build)=scripts/basic

    @rm -f .tmp_quiet_recordmcount

$(build)的定义在:scripts/Kbuild.include

build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj

KBUILD_SRC为空,所以$(if $(KBUILD_SRC),$(srctree)/)也为空。

所以变为:build := -f scripts/Makefile.build obj

所以依赖条件1变为:

scripts_basic:

    @make -f scripts/Makefile.build obj=scripts/basic

    @rm -f .tmp_quiet_recordmcount

此时主目标变成:

%config: scripts_basic

    +@/bin/sh ./scripts/multiconfig.sh %config

 

一、script_basic分析

scripts_basic:

    @make -f scripts/Makefile.build obj=scripts/basic

    @rm -f .tmp_quiet_recordmcount

在这里主要还是对@make -f scripts/Makefile.build obj=scripts/basic

这句命令的分析。

将obj = scripts/basic 这个变量名传入Makefile.build。

二、主目标分析

%config: scripts_basic

    +@/bin/sh ./scripts/multiconfig.sh %config

加入我们输入的命令是:make trats_defconfig

那么得到:

trats_defconfig: scripts_basic

    +@/bin/sh ./scripts/multiconfig.sh trats_defconfig

也就是将trats_defconfig这个文件传入multiconfig.sh脚本中,然后执行。

三、调用 multiconfig.sh 脚本过程分析

下面再来解析multiconfig.sh:

target=$1

 

case $target in

 

*_defconfig)

 

    do_board_defconfig $target;;

esac

 

此时target = trats_defconfig 符合*_defconfig,执行:

do_board_defconfig trats_defconfig;

do_board_defconfig是一个内部函数,另外经过替换一些已知变量后得到:

 do_board_defconfig () {

     defconfig_path=$srctree/configs/trats_defconfig

     tmp_defconfig_path=configs/.tmp_defconfig

 

     sed -n -e '/^[+A-Z]*:/!p' -e 's/^+[A-Z]*://p'$srctree/configs/trats_defconfig > configs/.tmp_defconfig

 

     run_make_config .tmp_defconfig || {

         cleanup_after_defconfig

         exit 1

     }

 

     for img in $(get_enabled_subimages)

     do

         symbol=$(echo$img| cut -c 1 | tr '[a-z]' '[A-Z]')

 

         # defconfig for SPL, TPL:

         #   pick lines with 'S', 'T' prefix and rip the prefixes off

         sed -n -e 's/^[+A-Z]*'$symbol'[A-Z]*://p'$defconfig_path > configs/.tmp_defconfig

        run_make_config .tmp_defconfig $img || {

            cleanup_after_defconfig

            exit 1

        }

    done

    cleanup_after_defconfig

}

大概意思是先把trats_defconfig复制一份到configs/.tmp_defconfig然后,

基本可以分为红色和粉红色两部分:

红色部分:

run_make_config .tmp_defconfig || {

         cleanup_after_defconfig

         exit 1

}

再次把.tmp_defconfig当作参数给run_make_config函数,run_make_config经过已知变量代换后变成:

run_make_config () {

      target=.tmp_defconfig

      objdir=

 

      options="SRCARCH=.. KCONFIG_OBJDIR="

      build scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig

}

最后一句再次调用build函数:

 build () {

     make -f $srctree/scripts/Makefile.build obj=“$@"

}

变量代换后变成:

make -f $srctree/scripts/Makefile.build obj=scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig

 

粉红色部分:

     for img in $(get_enabled_subimages)

     do

         symbol=$(echo$img| cut -c 1 | tr '[a-z]' '[A-Z]')

 

         # defconfig for SPL, TPL:

         #   pick lines with 'S', 'T' prefix and rip the prefixes off

         sed -n -e 's/^[+A-Z]*'$symbol'[A-Z]*://p'$defconfig_path > configs/.tmp_defconfig

        run_make_config .tmp_defconfig $img || {

            cleanup_after_defconfig

            exit 1

        }

在这我们没有定义过SPL和TPL,所以跳过这一步。

最后,其实只有一句话:

make -f $srctree/scripts/Makefile.build obj=scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig

四、Makefile.build分析

从二三节得到了两条待执行的指令:

make -f scripts/Makefile.build obj=scripts/basic

make -f scripts/Makefile.build obj=scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig

先分析第1条:

make -f scripts/Makefile.build obj=scripts/basic

编译scripts/basic.c文件

再分析第2条:

把scripts/kconfig 先传入Makefile.build中,然后再将根据其初始化的值暴露到顶层Makefile中。

匹配kconfig/Makefile里的:

%_defconfig:$(obj)/conf

    $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)

展开后:

.tmp_defconfig:scripts/kconfig/conf

    @scripts/kconfig/conf —defconfig=arch/../configs/.tmp_defconfig Kconfig

这句话的意图很明显,先编译scripts/kconfig/conf.c生成scripts/kconfig/conf,然后输入两个参数:

—defconfig=arch/../configs/.tmp_defconfig

Kconfig

五、scripts/kconfig/conf.c 解析