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

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_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源码。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值