tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——编译过程
2014-07-28 14:44
555 查看
这里引入一个 Makefile 的知识点,GUN make 的执行过程分为两个阶段:
第一阶段:读取所有的 makefile 文件(包括“MAKIFILES”变量指定的、指示符“include”指定的、以及命令行选项“-f(--file)”指定的 makefile 文件),内建所有的变量、明确规则和隐含规则,并建立所有目标和依赖之间的依赖关系结构链表。
第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则来重建这些目标。所以,当我们执行 make smdkc100_config 或者 make all 时,make 命令首先会将 Makefile 文件从头解析一遍,然后才是根据“目标-依赖”关系来建立目标。
在前面我们已经分析了顶层的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,或者在编译时通过命令行指定:
make all CROSS_COMPILE=arm-linux-
当我们执行 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.mk,包含指令 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 了,它依赖于$(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。
第一阶段:读取所有的 makefile 文件(包括“MAKIFILES”变量指定的、指示符“include”指定的、以及命令行选项“-f(--file)”指定的 makefile 文件),内建所有的变量、明确规则和隐含规则,并建立所有目标和依赖之间的依赖关系结构链表。
第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则来重建这些目标。所以,当我们执行 make smdkc100_config 或者 make all 时,make 命令首先会将 Makefile 文件从头解析一遍,然后才是根据“目标-依赖”关系来建立目标。
在前面我们已经分析了顶层的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,或者在编译时通过命令行指定:
make all CROSS_COMPILE=arm-linux-
当我们执行 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.mk,包含指令 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 了,它依赖于$(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。
相关文章推荐
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——编译过程
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——配置过程(一)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——配置过程(一)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——配置过程(三)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot.bin(修改显示信息)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——NAND添加分区
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot.bin(打印串口控制台)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植开始
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot.bin(内存布局)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot-spl.bin(时钟初始化)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot-spl.bin(核心初始化)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——NAND 启动
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——前言
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——NAND添加分区
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot-spl.bin(时钟初始化)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——命令补全和历史命令
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot.bin(打印串口控制台)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot.bin(修改显示信息)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——移植u-boot-spl.bin(内存初始化)
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)——SPL