u-boot 2014-10 Makefile 配置过程分析

来源:互联网 发布:淘宝运费险能退多少钱 编辑:程序博客网 时间:2024/06/05 08:20

u-boot 2014-10的Makefile工程管理结构与以前的有了很大的区别,要做移植工作,就要了解整个工程的配置和编译过程。从u-boot文件配置到生成bin文件需要这些两个操作
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_basicscripts_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/basicrm -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 += FORCEFORCE:

依赖条件分析完成后,接着分析命令。当运行的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=$1case $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.shTarget = smdk2410_defconfig

根据case匹配,shell会调用do_board_defconfig函数

# Usage:#  do_board_defconfig <board>_defconfigdo_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 shorthandsbuild () {    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/basicmake -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 := fixdepalways      := $(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源码。

0 0
原创粉丝点击