您的位置:首页 > 其它

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命令

配置

首先分析的配置部分,当我们在命令行下输入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源码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: