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 解析