最新uboot的Kbuild系统 4 make构建Uboot简略流程

前面第三章生成了.config,实际上还是不清楚细节上如何移植,不同的板子怎样设计.confg文件。

我们只是知道在.config里面 配置了很多CONFIG_XXX以及各种变量。


实际上先了解makefile构建uboot的整个流程。我们才能最终知道构建Uboot编译了哪些文件。

然后先编译一个rpi再编译几个其他板子,查看他们哪些编译是通用的。哪些编译是不通用的就知道移植一块板子到底需要修改哪些东西了。


执行make

首先遇到的第一目标就是

PHONY := _all
_all:

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

# If building an external module we do not care about the all: rule
# but instead _all depend on modules
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif

由于没有M命令。所以

_all:all

all: $(ALL-y)

ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check

继续寻找依赖。发现 上面的 ALL-y最终都依赖u-boot。由u-boot产生的。


在真正执行make之前还要注意有几个-include

由于make没有带其他参数

所以

dot-config     := 1

如果带了其他比如xxx_defconfig 就不会进入ifeq ($(dot-config,1)这里来


ifeq ($(dot-config),1)
-include include/config/auto.conf
-include include/config/auto.conf.cmd

-include include/autoconf.mk
-include include/autoconf.mk.dep

include config.mk
include arch/$(ARCH)/Makefile

endif


这几个文件分别生成了 很多其他的文件

初始的时候auto.conf auto.conf.cmd  autoconf.mk autoconf.mk.dep都是不存在的。所以会首先使用隐含的规则查找构建这个目标。构建完毕后再执行一次make

和原来的比较一下就知道这几个Include分别产生了什么文件

1 顶层目录多了u-boot.cfg

2 include目录多了config.h autoconf.mk autoconf.mk.dep

3 include目录多了 generated目录以及目录里面的autoconf.h

4 include目录多了一个config目录。以及目录里面各种头文件(大部分是空文件,只有一个文件名,0字节)(应该是为下一版本准备或者之前移植过来尚未处理的)

基本上都是一些基础配置数据。主要的一些配置数据在config/auto.conf里面。比如CONFIG_CPU_ARM1176=y CONFIG_SYS_VENDOR="raspberrypi"等等。

后续include config.mk里面需要这些变量。



等头文件什么都包含了再回头再看u-boot是如何产生的

u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE

$(call if_changed,u-boot__)

先分别看三个依赖

1$(u-boot-init)

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

head-y由于包含了include arch/$(ARCH)/Makefile。

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

所以 u-boot-init就是start.o这个

2$(u-boot-main)

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

也就是各种库和各种驱动


3u-boot.lds有两个依赖

u-boot.lds: $(LDSCRIPT) prepare FORCE
$(call if_changed_dep,cpp_lds)

一个是LDSCRIPT

如果没有定义LDSCRIPT,那么去下面这三个地方寻找

ifndef LDSCRIPT
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds
endif
endif


还有一个依赖是prepare

prepare: prepare0


prepare0: archprepare FORCE
$(Q)$(MAKE) $(build)=.


archprepare: prepare1 scripts_basic

scripts_basic看前面make xxx_defconfig的分析

$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount


prepare1: prepare2 $(version_h) $(timestamp_h) \
                   include/config/auto.conf

prepare1产生了$(version_h) $(timestamp_h)

version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h

构建过程如下

$(version_h): include/config/uboot.release FORCE
$(call filechk,version.h)
$(timestamp_h): $(srctree)/Makefile FORCE
$(call filechk,timestamp.h)


prepare2: prepare3 outputmakefile

其中outputmakefile一半得不到执行。主要是outputmakefile用于设置了独立的编译目录情况下才使用到


prepare3: include/config/uboot.release

prepare3和前面的$(version_h)都依赖于 include/config/uboot.release


include/config/uboot.release: include/config/auto.conf FORCE

$(call filechk,uboot.release)
而include/config/uboot.release和prepare1也依赖于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 || \
{ rm -f include/config/auto.conf; false; }
$(Q)touch include/config/auto.conf

这里KCONFIG_CONFIG=.config include/config/auto.conf.cmd 被强制更新

但是是个空命令

$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;


接下来就是执行 

$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig

$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf


其中

$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig 命中目标

%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@

这里和配置里面的make xxx流程就一样了。不同的是参数是silentoldconfig 而不是rpi_defconfig了

这个silentoldconfig主要是创建了include/config目录以及里面的各种conf文件。关键的是 auto.conf.cmd、autoconf.h、tristate.conf、auto.conf

等文件


接下来执行

$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf

也就是产生__all: include/autoconf.mk include/autoconf.mk.dep

其中依次创建了include/config.h 还创建了一些符号链接。主要是将arch/arm/include/asm/arch连接到对应的板子目录当中去




最终执行了最后的

$(call if_changed,u-boot__) 链接过程产生u-boot

cmd_u-boot__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_u-boot) -o $@ \
      -T u-boot.lds $(u-boot-init)                             \
      --start-group $(u-boot-main) --end-group                 \
      $(PLATFORM_LIBS) -Map u-boot.map


完全展开得到

arm-linux-gnueabihf-ld.bfd   -pie  --gc-sections -Bstatic -Ttext 0x00008000 -o u-boot -T u-boot.lds arch/arm/cpu/arm1176/start.o --start-group  arch/arm/cpu/built-in.o  arch/arm/cpu/arm1176/built-in.o  arch/arm/lib/built-in.o  arch/arm/mach-bcm283x/built-in.o  board/raspberrypi/rpi/built-in.o  cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o  drivers/dma/built-in.o  drivers/gpio/built-in.o  drivers/i2c/built-in.o  drivers/mmc/built-in.o  drivers/mtd/built-in.o  drivers/mtd/onenand/built-in.o  drivers/mtd/spi/built-in.o  drivers/net/built-in.o  drivers/net/phy/built-in.o  drivers/pci/built-in.o  drivers/power/built-in.o  drivers/power/battery/built-in.o  drivers/power/domain/built-in.o  drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o  drivers/serial/built-in.o  drivers/spi/built-in.o  drivers/usb/common/built-in.o  drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o  drivers/usb/eth/built-in.o  drivers/usb/gadget/built-in.o  drivers/usb/gadget/udc/built-in.o  drivers/usb/host/built-in.o  drivers/usb/musb-new/built-in.o  drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o  fs/built-in.o  lib/built-in.o  net/built-in.o  test/built-in.o  test/dm/built-in.o --end-group arch/arm/lib/eabi_compat.o  arch/arm/lib/lib.a -Map u-boot.map

查看一下使用的的编译选项


-pie 创建一个位置独立的可执行文件

这一点参看http://blog.chinaunix.net/uid-20528014-id-4445271.html

PIC(与位置无关代码)在u-boot上的实现 

http://hardenedlinux.org/system-security/2016/07/01/PIC_and_PIE_analysis.html


因为uboot存放的位置一般是ROM,无法写,所以一般要把UBOOT移动到 RAM里面再运行。

如果不是位置无关的代码。拷贝的时候对于全局变量的操作都需要修改代码。如果是位置无关的代码。只需要修改后面的表里面的数据。


--gc-sections 删除掉没有用到的代码段。减小体积。


-o u-boot 输出文件叫做u-boot


-Bstatic 指定使用静态方式连接 比如后面的lib.a uboot肯定要静态链接,他不能还去依赖其他的库。


-Ttext 0x00008000设置.text段的地址


-T uboot.lds 使用lds连接脚本来进行连接


--start-group 和--end-group主要是解决之间的文档的依赖问题。通常一般只搜索一次,按照命令行的顺序,比如 -liba -libb 如果a需要b的符号,但是b排在了a的后面,这时候就会报错,需要把b放到a的前面才行。但是加上--start-group和--end-group以后就会重复搜索,直到找到这个依赖。


-Map u-boot.map 生成一个map文件


这里只简单讲了基本的整个构建过程,Obj文件这些后续再看。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值