u-boot 2014-10 Makefile 配置过程分析
2015-02-09 11:34
363 查看
u-boot 2014-10的Makefile工程管理结构与以前的有了很大的区别,要做移植工作,就要了解整个工程的配置和编译过程。从u-boot文件配置到生成bin文件需要这些两个操作
1. 配置
在命令行中输入 make xxx_defconfig
2. 编译
在命令行中输入make命令
其中依赖scripts_basic
scripts_basic展开后
这里调用scripts/Makefile.build进行处理,留在后面对齐进行分析。
依赖条件outputmakefile
由于KBUILD_SRC为空,所以这段代码不被执行
依赖条件FORCE
依赖条件分析完成后,接着分析命令。当运行的make xxx_defconfig 后运行运行条件
命令中的一些变量意义如下:
替换拓展后
从最终的makefile中可以看出,Makefile调用了multiconfig.sh来完成接下来的配置工作接下来分析multiconfig.sh文件,当运行multiconfig.sh后它会到最后运行一个case语句
其中
根据case匹配,shell会调用do_board_defconfig函数
在do_board_defconfig函数中先将smdk2410_defconfig中的内容负责一份到config/.tmp_defconfig中,然后将.tmp_defconfig当做参数给run_make_config,最后变量替换后run_make_config为
然后调用文件内的build函数
变量替换拓展后
后面在分析Makefile.build,现在接着分析do_board_defconfig()函数。
在运行完成run_make_config()函数,接着进入一个for循环,但是由于smdk2410是Normal image,并为使用SPL和TPL所以for循环得不到执行(具体信息可以结合configs/smdk2410_defconfig和doc/README.kbuild).
接下来分析Makefile.build脚本。在配置的过程中总共调用到两次makefile.build脚本
makefile.build脚本是参考了linux kernel 中的kbuild框架设计的,如果深入了解可以查看内核文档说明。这里就不在赘述,只需要知道makfile.build脚本根据obj参数调用obj目标下的makefile,然后根据obj目录下的makefile对obj目录下的文件进行编译。当有这个认知后在看第一条指令
这里使用Mkaefile.build脚本去编译scripts/basic目录下的文件。具体的文件名可以查看该目录下啊的Makefile文件
这里编译fixdep.c文件(可以在配置的时候加入V=1参数)
接着分析第二条Makefile.build指令
这里使用makefile.build脚本去调用scripts/kconfig中的makefile文件,并将SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig 传入makefile。执行如下命令
拓展后
这里可以看出makefile.build首先是生成scripts/kconfig/conf程序,然后调用scripts/kconfig/conf程序配置文件,scripts/kconfig/conf编译过程如下
scripts/kconfig/conf的作用是生成配置信息。其源码位于scripts/kconfig/conf.c文件中。首先通过getopt_long获取—defconfig
此时的的input_mode为defconfig,所以运行第三个case语句,将optarg赋值给defconfig_file,该值为arch/../configs/.tmp_defconfig。接着获取Kconfig并该名字放入到name中
然后调用conf_parse(name)函数,解析所有的Kconfig文件,并将配置信息放入到struct symbol结构体链表中中。
接着调用con_read函数读取.tmp_defconfig中的内容,并根据这些内容生成新的配置信息
接着调用conf_set_all_new_sysmbols更新关系链表
最后调用conf_write函数将struct sysbol链表中的配置信息写入到.config文件
这里只是列出大概的配置流程,如果想要获取更多的信息可以阅读u-boot源码。
1. 配置
在命令行中输入 make xxx_defconfig
2. 编译
在命令行中输入make命令
配置
首先分析的配置部分,当我们在命令行下输入make xxx_defconfg 命令时,顶层的Makefile中唯一的匹配目标(以smdk2410为例)%config: scripts_basic outputmakefile FORCE +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/multiconfig.sh $@
其中依赖scripts_basic
PHONY += scripts_basic scripts_basic: $(Q)$(MAKE) $(build)=scripts/basic $(Q)rm -f .tmp_quiet_recordmcount
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
scripts_basic展开后
make -f scripts/Makefile.build obj=scripts/basic rm -f .tmp_quiet_recordmcount
这里调用scripts/Makefile.build进行处理,留在后面对齐进行分析。
依赖条件outputmakefile
PHONY += outputmakefile # outputmakefile generates a Makefile in the output directory, if using a # separate output directory. This allows convenient use of make in the # output directory. outputmakefile: ifneq ($(KBUILD_SRC),) $(Q)ln -fsn $(srctree) source $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) endif
由于KBUILD_SRC为空,所以这段代码不被执行
依赖条件FORCE
PHONY += FORCE FORCE:
依赖条件分析完成后,接着分析命令。当运行的make xxx_defconfig 后运行运行条件
%config: scripts_basic outputmakefile FORCE +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/multiconfig.sh $@
命令中的一些变量意义如下:
$(Q) = @ //当make xxx_defconfig V=1时 $(@) = //控制回显 $(CONFIG_SHELL) = /bin/sh $(srctree) = . //当前文件夹路径 $@ 表示目标文件
替换拓展后
smdk2410_defconfig:scripts_basic +@/bin/sh ./ scripts/multiconfig.sh smdk2410_defconfig
从最终的makefile中可以看出,Makefile调用了multiconfig.sh来完成接下来的配置工作接下来分析multiconfig.sh文件,当运行multiconfig.sh后它会到最后运行一个case语句
progname=$(basename $0) target=$1 case $target in *_defconfig) do_board_defconfig $target;; *_config) # backward compatibility do_board_defconfig ${target%_config}_defconfig;; silentoldconfig) do_silentoldconfig;; defconfig) do_defconfig;; savedefconfig) do_savedefconfig;; *) do_others $target;; esac
其中
Progname = multiconfig.sh Target = smdk2410_defconfig
根据case匹配,shell会调用do_board_defconfig函数
# Usage: # do_board_defconfig <board>_defconfig do_board_defconfig () { defconfig_path=$srctree/configs/$1 tmp_defconfig_path=configs/.tmp_defconfig if [ ! -r $defconfig_path ]; then echo >&2 "***" echo >&2 "*** Can't find default configuration \"configs/$1\"!" echo >&2 "***" exit 1 fi mkdir -p arch configs # defconfig for Normal: # pick lines without prefixes and lines starting '+' prefix # and rip the prefixes off. sed -n -e '/^[+A-Z]*:/!p' -e 's/^+[A-Z]*://p' $defconfig_path \ > 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 }
在do_board_defconfig函数中先将smdk2410_defconfig中的内容负责一份到config/.tmp_defconfig中,然后将.tmp_defconfig当做参数给run_make_config,最后变量替换后run_make_config为
run_make_config () { target=.tmp_defconfig objdir= # Linux expects defconfig files in arch/$(SRCARCH)/configs/ directory, # but U-Boot has them in configs/ directory. # Give SRCARCH=.. to fake scripts/kconfig/Makefile. options="SRCARCH=.. KCONFIG_OBJDIR=" if [ "$objdir" ]; then options="$options KCONFIG_CONFIG=$objdir/$KCONFIG_CONFIG" mkdir -p $objdir fi build scripts/kconfig "SRCARCH=.. KCONFIG_OBJDIR=" .tmp_defconfig }
然后调用文件内的build函数
# Useful shorthands build () { debug $progname: $MAKE -f $srctree/scripts/Makefile.build obj="$@" $MAKE -f $srctree/scripts/Makefile.build obj="$@" }
变量替换拓展后
multiconfig.sh: make -f /home/edward/ok6410/u-boot-2014.10/scripts/Makefile.build obj=scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig
后面在分析Makefile.build,现在接着分析do_board_defconfig()函数。
在运行完成run_make_config()函数,接着进入一个for循环,但是由于smdk2410是Normal image,并为使用SPL和TPL所以for循环得不到执行(具体信息可以结合configs/smdk2410_defconfig和doc/README.kbuild).
接下来分析Makefile.build脚本。在配置的过程中总共调用到两次makefile.build脚本
make -f scripts/Makefile.build obj=scripts/basic make -f /home/edward/ok6410/u-boot-2014.10/scripts/Makefile.build obj=scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig
makefile.build脚本是参考了linux kernel 中的kbuild框架设计的,如果深入了解可以查看内核文档说明。这里就不在赘述,只需要知道makfile.build脚本根据obj参数调用obj目标下的makefile,然后根据obj目录下的makefile对obj目录下的文件进行编译。当有这个认知后在看第一条指令
make -f scripts/Makefile.build obj=scripts/basic
这里使用Mkaefile.build脚本去编译scripts/basic目录下的文件。具体的文件名可以查看该目录下啊的Makefile文件
hostprogs-y := fixdep always := $(hostprogs-y) # fixdep is needed to compile other host programs $(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
这里编译fixdep.c文件(可以在配置的时候加入V=1参数)
cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/fixdep scripts/basic/fixdep.c
接着分析第二条Makefile.build指令
make -f /home/edward/ok6410/u-boot-2014.10/scripts/Makefile.build obj=scripts/kconfig SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig
这里使用makefile.build脚本去调用scripts/kconfig中的makefile文件,并将SRCARCH=.. KCONFIG_OBJDIR= .tmp_defconfig 传入makefile。执行如下命令
%_defconfig: $(obj)/conf $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
拓展后
.tmp_defconfig: scripts/kconfig/conf scripts/kconfig/conf --defconfig=arch/../configs/.tmp_defconfig Kconfig
这里可以看出makefile.build首先是生成scripts/kconfig/conf程序,然后调用scripts/kconfig/conf程序配置文件,scripts/kconfig/conf编译过程如下
/bin/sh /home/edward/ok6410/u-boot-2014.10/scripts/multiconfig.sh smdk2410_defconfig cc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -DCURSES_LOC="<ncurses.h>" -DLOCALE -c -o scripts/kconfig/conf.o scripts/kconfig/conf.c cat scripts/kconfig/zconf.tab.c_shipped > scripts/kconfig/zconf.tab.c cat scripts/kconfig/zconf.lex.c_shipped > scripts/kconfig/zconf.lex.c cat scripts/kconfig/zconf.hash.c_shipped > scripts/kconfig/zconf.hash.c cc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -DCURSES_LOC="<ncurses.h>" -DLOCALE -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c cc -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o scripts/kconfig/conf --defconfig=arch/../configs/.tmp_defconfig Kconfig
scripts/kconfig/conf的作用是生成配置信息。其源码位于scripts/kconfig/conf.c文件中。首先通过getopt_long获取—defconfig
while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { input_mode = (enum input_mode)opt; switch (opt) { case silentoldconfig: sync_kconfig = 1; break; case defconfig: case savedefconfig: defconfig_file = optarg; break; case randconfig: .... }
此时的的input_mode为defconfig,所以运行第三个case语句,将optarg赋值给defconfig_file,该值为arch/../configs/.tmp_defconfig。接着获取Kconfig并该名字放入到name中
name = av[optind];
然后调用conf_parse(name)函数,解析所有的Kconfig文件,并将配置信息放入到struct symbol结构体链表中中。
接着调用con_read函数读取.tmp_defconfig中的内容,并根据这些内容生成新的配置信息
switch (input_mode) { case defconfig: if (!defconfig_file) defconfig_file = conf_get_default_confname(); if (conf_read(defconfig_file)) { printf(_("***\n" "*** Can't find default configuration \"%s\"!\n" "***\n"), defconfig_file); exit(1); } break; case savedefconfig: .... }
接着调用conf_set_all_new_sysmbols更新关系链表
switch (input_mode) { .... case defconfig: conf_set_all_new_symbols(def_default); break; case savedefconfig: break; .... }
最后调用conf_write函数将struct sysbol链表中的配置信息写入到.config文件
..... else if (input_mode != listnewconfig) { if (conf_write(NULL)) { fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); exit(1); } }
这里只是列出大概的配置流程,如果想要获取更多的信息可以阅读u-boot源码。
相关文章推荐
- U-boot分析第1章------------------Makefile(配置过程)
- 二、uboot的配置过程分析 (2011-03-10 19:41)
- 2014-10 u-boot make xxx_defconfig 过程分析
- u-boot-2016.09 make配置过程分析
- u-boot-2012.04.01的配置编译过程分析.doc
- u-boot的配置过程分析2
- u-boot2013.01 sdmk2410 配置和编译过程分析
- u-boot-1.1.6的配置编译过程分析.doc
- u-boot-2016.09 make配置过程分析
- (二) u-boot 配置、编译过程分析
- u-boot-2012.10分析一配置过程
- 2014-10 u-boot make过程分析
- U-boot分析第1章------------------Makefile(编译过程)
- U-Boot的配置过程分析
- uboot配置和启动过程1(主Makefile分析)
- u-boot-2012.10分析一配置过程
- u-boot配置过程分析(ARM)
- U-Boot--配置过程分析
- u-boot分析之Makefile结构分析----配置