u-boot 编译改动了那些文件(2)-make all

本文详细介绍了U-Boot的编译流程,包括编译过程中涉及到的各种文件、宏定义和依赖关系。从Makefile开始,逐步分析了如何指定交叉编译工具、配置文件和连接脚本,并解释了如何生成最终的U-Boot二进制文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先汇总编译用到的文件:
顶层的Makefile、mkconfig;
include/config.mk(指定架构、CPU核、soc),lib_arm/config.mk(指定交叉编译工具),board/smdk2410/u-boot.lds(U-Boot的连接脚本),
board/smdk2410/config.mk(代码段连接的起始地址)cpu/arm920t/config.mk(设定了跟arm920t处理器相关的编译选项)
cpu/arm920t/s3c24x0/config.mk

和平台相关的源文件和库文件:
cpu/arm920t/start.o
cpu/arm920t/s3c24x0/libs3c24x0.a
cpu/arm920t/libarm920t.a
….

1、把make smdk2410_config命令生成的include/config.mk包含进来。根据里面的参数选择使用哪些工具和文件。

include $(obj)include/config.mk 
export ARCH CPU BOARD VENDOR SOC 

2、设置obj与src
由于目标输出到源代码目录下,因此执行完上面的代码后,src和obj都是空。

ifneq ($(OBJTREE),$(SRCTREE)) 
ifeq ($(CURDIR),$(SRCTREE)) 
dir := 
else 
dir := $(subst $(SRCTREE)/,,$(CURDIR)) 
endif 
obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/) 
src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/) 
$(shell mkdir -p $(obj)) 
else 
obj := 
src := 
endif 

3、指定交叉编译工具

AS = $(CROSS_COMPILE)as 
LD = $(CROSS_COMPILE)ld 
CC = $(CROSS_COMPILE)gcc 
CPP = $(CC) -E 
AR = $(CROSS_COMPILE)ar 
NM = $(CROSS_COMPILE)nm 
LDR = $(CROSS_COMPILE)ldr 
STRIP = $(CROSS_COMPILE)strip 
OBJCOPY = $(CROSS_COMPILE)objcopy 
OBJDUMP = $(CROSS_COMPILE)objdump 
RANLIB = $(CROSS_COMPILE)RANLIB 

对于arm开发板,其中的CROSS_COMPILE在lib_arm/config.mk文件中定义:
CROSS_COMPILE ?= arm-linux-
因此以上代码指定了使用前缀为“arm-linux-”的编译工具,即arm-linux-gcc,arm-linux-ld等等。

4、包含与开发板相关的配置文件

sinclude $(OBJTREE)/include/autoconf.mk 
ifdef ARCH 
sinclude $(TOPDIR)/lib_$(ARCH)/config.mk # include architecture dependend rules 
endif 
$(ARCH)的值是“arm”,因此将“lib_arm/config.mk”包含进来。lib_arm/config.mk脚本指定了交叉编译器,添加了一些跟CPU架构相关的编译选项,最后还指定了

cpu/arm920t/u-boot.lds为U-Boot的连接脚本。

ifdef CPU 
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk # include CPU specific rules 
endif 
$(CPU)的值是“arm920t”,因此将“cpu/arm920t/config.mk”包含进来。这个脚本主要设定了跟arm920t处理器相关的编译选项。 
ifdef SOC 
sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk # include SoC specific rules 
endif 
$(SOC)的值是s3c24x0,因此Make程序尝试将cpu/arm920t/s3c24x0/config.mk包含进来。
BOARDDIR = $(BOARD) 
ifdef BOARD 
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk endif 
Make将“board/smdk2410/config.mk”包含进来。该脚本只有如下的一行代码: 
TEXT_BASE = 0x33F80000 
U-Boot编译时将使用TEXT_BASE作为代码段连接的起始地址。 
LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS) 
ifneq ($(TEXT_BASE),) 
LDFLAGS += -Ttext $(TEXT_BASE) 
endif 
执行完以上代码后,LDFLAGS中包含了“-Bstatic -T u-boot.lds ”和“-Ttext 0x33F80000”的字样。 

LIBS变量指明了U-Boot需要的库文件,包括平台/开发板相关的目录、通用目录下相应的库,都通过相应的子目录编译得到的

OBJS = cpu/$(CPU)/start.o 
LIBS += cpu/$(CPU)/lib$(CPU).a 
ifdef SOC 
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a 
endif 
ifeq ($(CPU),ixp) 
LIBS += cpu/ixp/npe/libnpe.a 
endif 
LIBS += lib_$(ARCH)/lib$(ARCH).a 
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \ 
fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a \ 
fs/ubifs/libubifs.a 
… … 
LIBS += common/libcommon.a 
LIBS += libfdt/libfdt.a 
LIBS += api/libapi.a 
LIBS += post/libpost.a 
LIBS := $(addprefix $(obj),$(LIBS)) 

对于smdk2410开发板,以上跟平台相关的有以下几个:

cpu/$(CPU)/start.o 
board/$(VENDOR)/common/lib$(VENDOR).a 
cpu/$(CPU)/lib$(CPU).a 
cpu/$(CPU)/$(SOC)/lib$(SOC).a 
lib_$(ARCH)/lib$(ARCH).a 

其余都是与平台无关的。

make all

ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) 
all: $(ALL) 
其中U_BOOT_NAND与U_BOOT_ONENAND 为空,而u-boot.srec,u-boot.bin,System.map都依赖与u-boot。因此执行“make all”命令将生成u-boot,u-boot.srec,u-boot.bin,System.map 。其中u-boot是ELF文件,u-boot.srec是Motorola S-Record format文件,System.map 是U-Boot的符号表,u-boot.bin是最终烧写到开发板的二进制可执行的文件。 

下面再来分析u-boot.bin文件生成的过程。ELF格式“u-boot”文件生成规则如下:

$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds $(GEN_UBOOT) 
这里生成的$(obj)u-boot目标就是ELF格式的U-Boot文件了。其中depend,$(SUBDIRS),$(OBJS),$(LIBBOARD),$(LIBS),$(LDSCRIPT), $(obj)u-boot.lds是$(obj)u-boot的依赖,而$(GEN_UBOOT)编译命令。 
下面分析$(obj)u-boot的各个依赖:

1、依赖目标depend

depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk 
for dir in $(SUBDIRS) cpu/$(CPU) $(dir $(LDSCRIPT)) ; do \ 
$(MAKE) -C $$dir _depend ; done 
对于$(SUBDIRS),cpu/$(CPU),$(dir $(LDSCRIPT))中的每个元素都进入该目录执行“make _depend”,生成各个子目录的.depend文件,.depend列出每个目标文件的依赖文件。 

2、依赖SUBDIRS

SUBDIRS = tools \ 
examples/standalone \ 
examples/api 
$(SUBDIRS): depend 
$(MAKE) -C $@ all 
执行tools ,examples/standalone ,examples/api目录下的Makefile

3、OBJS

OBJS的值是“cpu/arm920t/start.o”。它使用如下代码编译得到: 
$(OBJS): depend 
$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@)) 
以上规则表明,对于OBJS包含的每个成员,都进入cpu/$(CPU)目录(即cpu/arm920t)编译它们。 

4、LIBBOARD

LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a 
LIBBOARD := $(addprefix $(obj),$(LIBBOARD)) 
… … 
$(LIBBOARD): depend $(LIBS) 
$(MAKE) -C $(dir $(subst $(obj),,$@)) 
这里LIBBOARD的值是 $(obj)board/smdk2410/libsmdk2410.a。make执行board/smdk2410/目录下的Makefile,生成libsmdk2410.a 。

5、LIBS

LIBS变量中的每个元素使用如下的规则编译得到: 
$(LIBS): depend $(SUBDIRS) 
$(MAKE) -C $(dir $(subst $(obj),,$@)) 
上面的规则表明,对于LIBS中的每个成员,都进入相应的子目录执行“make”命令编译它们。例如对于LIBS中的“common/libcommon.a”成员,程序将进入common目录执行Makefile,生成libcommon.a

6、LDSCRIPT

LDSCRIPT := $(SRCTREE)/cpu/$(CPU)/u-boot.lds 
… … 
$(LDSCRIPT): depend 
$(MAKE) -C $(dir $@) $(notdir $@) 
“$(MAKE) -C $(dir $@) $(notdir $@)”命令经过变量替换后就是“make -C cpu/arm920t/ u-boot.lds”。也就是转到cpu/arm920t/目录下,执行“make u-boot.lds”命令。

7、$(obj)u-boot.lds

$(obj)u-boot.lds: $(LDSCRIPT) 
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@ 
以上执行结果实质上是将cpu/arm920t/u-boot.lds经编译器简单预处理后输出到U-Boot顶层目录下的u-boot.lds文件。其中的cpu/arm920t/u-boot.lds文件内容如下: 
/* 输出为ELF文件,小端方式, */ 
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 
OUTPUT_ARCH(arm) 
ENTRY(_start) 
SECTIONS 
{ 
. = 0x00000000; 
. = ALIGN(4); 
.text : 
{ 
/* cpu/arm920t/start.o放在最前面,保证最先执行的是start.o */ 
cpu/arm920t/start.o (.text) 
/*以下2个文件必须放在前4K,因此也放在前面,其中board/smdk2410/lowlevel_init.o 包含内存初始化所需代码,而 board/smdk2410/nand_read.o包含U-Boot从NAND Flash搬运自身的代码 */ 
board/smdk2410/lowlevel_init.o (.text) 
board/smdk2410/nand_read.o (.text) 
/* 其他文件的代码段 */ 
*(.text) 
} 
/* 只读数据段 */ 
. = ALIGN(4); 
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } 
/* 代码段 */ 
. = ALIGN(4); 
.data : { *(.data) } 
/* u-boot自定义的got段 */ 
. = ALIGN(4); 
.got : { *(.got) } 
. = .; 
__u_boot_cmd_start = .; /*将 __u_boot_cmd_start指定为当前地址 */ 
.u_boot_cmd : { *(.u_boot_cmd) } /* 存放所有U-Boot命令对应的cmd_tbl_t结构体 */ 
__u_boot_cmd_end = .; /* 将__u_boot_cmd_end指定为当前地址 */ 
/* bss段 */ 
. = ALIGN(4); 
__bss_start = .; 
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); } 
_end = .; /* 将_end指定为当前地址 */ 
} 
u-boot.lds实质上是U-Boot连接脚本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值