uboot移植(二)编译过程分析

这里引入一个 Makefile 的知识点, GUN make 的执行过程分为两个阶段:
第一阶段:读取所有的
makefile 文件(包括“ MAKIFILES ”变量指定的、指示符“ include ”指定的、
以及命令行选项“
-f(--file) ”指定的 makefile 文件),内建所有的变量、明确规则和隐含规则,并建立所
有目标和依赖之间的依赖关系结构链表。
第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则
来重建这些目标。
所以,当我们执行
make smdkc100_config 或者 make all 时, make 命令首先会将 Makefile 文件从头

解析一遍,然后才是根据“目标-依赖”关系来建立目标。


这里的$(CURDIR)Makefile 自己的环境变量,它等于当前目录,展开即为:
srctree=/home/work/u-boot-2014.04
objtree=/home/work/u-boot-2014.04
src=/home/work/u-boot-2014.04
obj=/home/work/u-boot-2014.04
VPATH=/home/work/u-boot-2014.04
MKCONFIG=/home/work/u-boot-2014.04/mkconfig
接下来得到宿主机架构和宿主机系统:
HOSTARCH=x86
HOSTOS=linux


这里定义了编译过程中要使用到的一些编译、链接工具,我们需要指定 CROSS_COMPILE
arm-linux- ,可以直接修改 Makefile,或者在编译时通过命令行指定:
root@zjh:/home/work/u-boot-2014.04# make all CROSS_COMPILE=arm-linux-

这里决定了我们执行 make smdkc100_config make all Makefile 中的走向。 用到了 Makefile 的函
filter filter-out,不清楚的可以查看《GNU make 中文手册》。 MAKECMDGOALS Makefile 的变量,
它保存了我们执行
make 时所带的命令行参数。
当我们执行
make smdkc100_config 时, $(filter config %config,$(MAKECMDGOALS))会返回字符串
smdkc100,不为空, 因此得到 config-targets := 1
当我们执行 make all 时, 这里没有一项匹配的,最终得到:
config-targets = 0
mixed-targets = 0
dot-config = 1
接下来有几个 if……else ifeq……endif 分支:
ifeq ($(mixed-targets),1)
……
else
ifeq ($(config-targets),1)
当执行 make smdkc100_config 时将进入到这个分支
……
else
当执行 make all 时将进入这个分支
……
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)
下面分析执行 make all 时进入的那个分支

首先包含头文件 include/config.mkinclude/config.mk 5.2 节有说明
包含指令
include 前面的 - 表示当包含的文件不存在时, make 不输出任何信息,也不退出。
478 行,如果不存在 include/config.mk,则输出错误信息,如果没有配置,就不存在这个文件:


这里从相关目录取出链接脚本文件,然后赋给变量 LDSCRIPT

这里导出变量 CONFIG_SYS_TEXT_BASE, 表示代码段的基地址,在单板配置文件 smdkc100.h 中定义
下面定义了一些目标:
head-y := $(CPUDIR)/start.o
head-$(CONFIG_4xx) += arch/powerpc/cpu/ppc4xx/resetvec.o
head-$(CONFIG_MPC85xx) += arch/powerpc/cpu/mpc85xx/resetvec.o
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
libs-y += lib/
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
libs-y += $(CPUDIR)/
ifdef SOC
libs-y += $(CPUDIR)/$(SOC)/
endif
libs-$(CONFIG_OF_EMBED) += dts/

libs-y += arch/$(ARCH)/lib/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
……
u-boot-init := $(head-y)
u-boot-main := $(libs-y)
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += u-boot.srec u-boot.bin System.map
ALL-$(CONFIG_NAND_U_BOOT) += u-boot-nand.bin
ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb u-boot-dtb.bin
ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
ifneq ($(CONFIG_SPL_TARGET),)
ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
上面这些 CONFIG_都没有配置,所有最终$(ALL-y)展开为
u-boot.srec u-boot.bin System.map

我们分析了那么久,终于找到目标 all 了,它依赖于$(ALL-y)$(ALL-y)会被展开为多个目标,然后
make 会找到每个目标,根据每个目标的依赖关系进行编译。 我们最终需要得到 u-boot.bin

从这得知 u-boot.bin 依赖于 u-boot

从这得知 u-boot 依赖于$(u-boot-init) $(u-boot-main) u-boot.lds
$(u-boot-init)
展开为: arch/arm/cpu/armv7/start.o
$(u-boot-main)
展开为: $(libs-y)$(libs-y)展开为各个目录下的相关库。
这里依赖的链接脚本为:
arch/arm/cpu/u-boot.lds

这里根据.h 头文件生成被所有 Makefile 包含的 autoconf.mk
gcc
通过使用 –M –dM 可以输出输入文件中的所有宏和 gcc 自己的宏, 这里把输出的宏保存到一个
临时文件,然后交给
sed 处理, sed 根据一个脚本 define2mk.sed 定义的规则把这些宏输出到 autoconf.mk
下面是
define2mk.sed 的内容:

define2mk.sed 只处理以 CONFIG_ 为前缀的宏,看下 include/autoconf.mk 的内容就能明白它的处理
规则。




猜你喜欢

转载自blog.csdn.net/jerrygou/article/details/80368262