uboot编译过程

make xxx_defconfig

生成.config文件

make xxx_defconfig的目标就是生成.config文件。

通过命令:scripts/kconfig/conf --defconfig=configs/xxx_defconfig Kconfig,生成.config文件。

conf为主机上的可执行文件,由scripts/kconfig目录下的conf.c和zconf.tab.c生成,功能为解析defconfig和Kconfig文件,将其中的符号生成到.config文件中。

make xxx_defconfig在makefile中的执行过程如下

  • make xxx_defconfig实际执行 make-f scripts/Makefile.buid obj=scripts/kconfig xxx_defconfig,如下所示:
build=-f scripts/Makefile.buid obj=
%config: scripts_basic FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@
  • 执行make-f scripts/Makefile.buid obj=scripts/kconfig xxx_defconfig时,Makefile.build会包含scripts/kconfig/Makefile,如下所示:
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
  • 而xxx_defconfig目标正是定义在scripts/kconfig/Makefile中,如下所示:
# Added for U-Boot
#  Linux has defconfig files in arch/$(SRCARCH)/configs/,
#  on the other hand, U-Boot does in configs/.
#  Set SRCARCH to .. fake this Makefile.
SRCARCH := ..

%_defconfig: $(obj)/conf
	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
  • 上诉语句会执行命令:scripts/kconfig/conf --defconfig=configs/xxx_defconfig Kconfig

conf的代码没有深究,理解Kconfig文件的规则也能大概理解.config文件的生成逻辑。

make

生成配置文件

概述

生成的主要配置文件如下:

include/config/auto.conf
include/autoconf.mk
include/generated/autoconf.h

其中,include/config/auto.conf来自于.config文件,是.config文件去掉注释后的配置,为编译过程所用。

include/autoconf.mk来自于incluce/common.h,包含了uboot中c头文件的配置,为编译过程所用。

include/generated/autoconf.h来自于include/config/auto.conf,是将auto.conf的配置转化为c语言的宏定义,为uboot源代码所用。

生成配置文件的主要代码如下:

# Read in config
-include include/config/auto.conf

include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf 

all:

make all时,如果include/config/auto.conf文件不存在,那么include/config/%.conf目标下的规则会被执行,即使include/config/%.conf没有被all依赖。之后再执行all目标,此时会重新包含include/config/auto.conf文件里面的内容。

include/config/%.conf目标规则的功能如下:

1、执行 make silentoldconfig,生成include/config/auto.conf和include/generated/autoconf.h。

2、执行 make -f scripts/Makefile.autoconf,生成 include/autoconf.mk。

make silentoldconfig

执行 make silentoldconfig与执行make xxx_defconfig类似,silentoldconfig目标也是定义在scripts/kconfig/Makefile中,如下所示:

silentoldconfig: $(obj)/conf
	$(Q)mkdir -p include/config include/generated
	$< $(silent) --$@ $(Kconfig)

上诉语句会执行命令:scripts/kconfig/conf --silentoldconfig Kconfig

make -f scripts/Makefile.autoconf

Makefile.autoconf的目标主要是生成include/config.h和include/autoconf.mk,代码如下:

__all: include/autoconf.mk include/autoconf.mk.dep

include/autoconf.mk include/autoconf.mk.dep \
	spl/include/autoconf.mk tpl/include/autoconf.mk: include/config.h

include/config.h一个重要的功能就是指明了需要包含的板级预配置头文件:include/configs/$(CONFIG_SYS_CONFIG_NAME).h.

其中,CONFIG_SYS_CONFIG_NAME在第一步make xxx_defconfig中已经生成到.config文件中。

  • 生成 include/config.h的代码如下所示:
# include/config.h
# Prior to Kconfig, it was generated by mkconfig. Now it is created here.
define filechk_config_h
	(echo "/* Automatically generated - do not edit */";		\
	for i in $$(echo $(CONFIG_SYS_EXTRA_OPTIONS) | sed 's/,/ /g'); do \
		echo \#define CONFIG_$$i				\
		| sed '/=/ {s/=/	/;q; } ; { s/$$/	1/; }'; \
	done;								\
	echo \#define CONFIG_BOARDDIR board/$(if $(VENDOR),$(VENDOR)/)$(BOARD);\
	echo \#include \<config_defaults.h\>;				\
	echo \#include \<config_uncmd_spl.h\>;				\
	echo \#include \<configs/$(CONFIG_SYS_CONFIG_NAME).h\>;		\
	echo \#include \<asm/config.h\>;				\
	echo \#include \<config_fallbacks.h\>;)
endef

include/config.h: scripts/Makefile.autoconf create_symlink FORCE
	$(call filechk,config_h)

autoconf.mk来源于include/common.h,而通过如下文件包含关系,获取了板级预配置头文件的所有宏定义

include/common.h -> include/config.h -> include/configs/$(CONFIG_SYS_CONFIG_NAME).h

  • 生成autoconf.mk的代码如下所示:
# We are migrating from board headers to Kconfig little by little.
# In the interim, we use both of
#  - include/config/auto.conf (generated by Kconfig)
#  - include/autoconf.mk      (used in the U-Boot conventional configuration)
# The following rule creates autoconf.mk
# include/config/auto.conf is grepped in order to avoid duplication of the
# same CONFIG macros
quiet_cmd_autoconf = GEN     $@
      cmd_autoconf = \
	$(CPP) $(c_flags) $2 -DDO_DEPS_ONLY -dM $(srctree)/include/common.h > $@.tmp && { \
		sed -n -f $(srctree)/tools/scripts/define2mk.sed $@.tmp |		\
		while read line; do							\
			if [ -n "${KCONFIG_IGNORE_DUPLICATES}" ] ||			\
			   ! grep -q "$${line%=*}=" include/config/auto.conf; then	\
				echo "$$line";						\
			fi								\
		done > $@;								\
		rm $@.tmp;								\
	} || {										\
		rm $@.tmp; false;							\
	}

include/autoconf.mk: FORCE
	$(call cmd,autoconf)

生成u-boot.bin

生成elf文件和bin文件

u-boot为生成的elf文件;u-boot.bin为u-boot去除符号表后的二进制文件。它们的依赖关系如下所示:

u-boot:	$(u-boot-init) $(u-boot-main) u-boot.lds FORCE
	$(call if_changed,u-boot__)

u-boot-nodtb.bin: u-boot FORCE
	$(call if_changed,objcopy)
	$(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))

u-boot.bin: u-boot-nodtb.bin FORCE
	$(call if_changed,copy)

u-boot主要依赖u-boot-init和u-boot-main,两者在主makefile中定义。

arch/arm/Makefile(被主makefile包含):

head-y := arch/arm/cpu/$(CPU)/start.o

libs-y += arch/arm/cpu/$(CPU)/
libs-y += arch/arm/cpu/
libs-y += arch/arm/lib/
......

主makefile:

include arch/$(ARCH)/Makefile

libs-y += lib/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
libs-$(CONFIG_UT_ENV) += test/env/
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
......

u-boot-init := $(head-y)
u-boot-main := $(libs-y)

$(sort $(u-boot-init) $(u-boot-main)): $(u-boot-dirs) ;

u-boot-dirs	:= $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples

u-boot-dirs代表了libs-y中包含的所有目录,为u-boot-init和u-boot-main所依赖。

而u-boot-dirs中每个目录的标规是:

make -f scripts/Makefile.buid obj=$(dir)

该规则功能是将该目录下的待编译c文件编译打包成一个built-in.o文件。

$(u-boot-dirs): prepare scripts
	$(Q)$(MAKE) $(build)=$@

Makefile.build

make -f scripts/Makefile.buid obj=$(dir),来编译某个目录,生成该目录的built-in.o文件。

分析生成built-in.o的过程,Makefile.buid可简化为

src := $(obj)
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
	 $(subdir-ym) $(always)
	@:

builtin-target := $(obj)/built-in.o
$(builtin-target): $(obj-y) FORCE
	$(call if_changed,link_o_target)

$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
	$(call if_changed_rule,cc_o_c)

__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y	+= $(__subdir-y)
subdir-ym	:= $(sort $(subdir-y) $(subdir-m))

$(subdir-ym):
	$(Q)$(MAKE) $(build)=$@

Makefile.build首先包括当前目录($(obj)取值的目录)的Makefile,该Makfile中会定义obj-y,可能是文件,也可能是目录,代表需要编译的文件和子目录。如下所示:

src := $(obj)
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)

Makefile.build的目标为__build,它依赖于 ( o b j ) / b u i l t − i n . o ,而 (obj)/built-in.o,而 (obj)/builtin.o,而(obj)/built-in.o又依赖于$(obj-y)。

当obj-y为xxx.o时,通过c文件编译,如下所示:

$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
	$(call if_changed_rule,cc_o_c)

当obj-y为xxx/时,代表一个子目录,则递归调用Makefile.build,进一步编译该子目录。如下所示:

__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y	+= $(__subdir-y)
subdir-ym	:= $(sort $(subdir-y) $(subdir-m))

$(subdir-ym):
	$(Q)$(MAKE) $(build)=$@
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值