前言:作为一个初学者,只是为了记笔记,如果有什么地方分析的不对,请各位大佬指出来。
这篇文章接着分析uboot-2012.04.01编译的第二步骤make all,主要分析顶层的makefile文件:
第一部分
VERSION = 2012 //主版本号
PATCHLEVEL = 04 //修补版本号
SUBLEVEL = 01 //次版本号
EXTRAVERSION = ///附加信息,一般默认为空,我们可以自己设置
ifneq "$(SUBLEVEL)" ""
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) //2012.04.01
else
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL)$(EXTRAVERSION)
endif
TIMESTAMP_FILE = $(obj)include/generated/timestamp_autogenerated.h
VERSION_FILE = $(obj)include/generated/version_autogenerated.h
HOSTARCH := $(shell uname -m | \ //uname -m是读取机器硬件,我们这台机器是64位,读取结果是i686
sed -e s/i.86/x86/ \ //sed -e s/123/abc xxx 将字符串xxx中的123替换成abc
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ \
-e s/sa110/arm/ \
-e s/ppc64/powerpc/ \
-e s/ppc/powerpc/ \
-e s/macppc/powerpc/\
-e s/sh.*/sh/)
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ //uname -s读取操作系统,我们这里是Linux
sed -e 's/\(cygwin\).*/cygwin/') //tr ‘[:upper:]’’[:lower:]’表示将结果里面的大写字符全部换成小写字符
SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ //-x判断文件是否可执行的,这里执行else语句SHELLE:=/bin/bash
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi; fi)
export HOSTARCH HOSTOS SHELL //导出这三个变量,供其它文件使用
VENDOR=
这一部分主要定义了uboot版本号和HOSTARCH HOSTOS SHELL这三个变量,我的环境下这些变量的值都写在了注释了。
第二部分
这一部分代码规定了该make是非静默编译还是静默编译,这里我们的编译未加任何标志,所以MAKEFLAGS变量为空,If$( findstring string,text )表示从text中寻找string字样,如果找到了则返回text,如果没找到就返回空,这里我们不加-s编译,findstrin返回空,ifeq条件成立,XECHO=echo,所以会打印相关编译信息。加上-s,会执行静默编译。
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif
第三部分
该部分是分析uboot的编译目录是什么,我们执行make all是默认在当前目录生成编译文件,但是这样会破坏uboot原有的文件,所以编译的时候加上-O参数的话,-O后面跟的目录即为编译输出目录。
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
这里介绍一下$(origin variable),origin函数不像其它函数。他并不直接操作变量的值,只是通过返回值来告诉我们这个变量时从哪来的。返回值有以下几个:
(1)返回值为"undefine"时,这个变量没有被定义过;
(2)返回值为“command line”时,这个变量是被命令行定义的;
(3)返回值为“environment”时,这个变量是定义为环境变量;
(4)返回值为“file”时,这个变量是定义在Makefile中;
(5)返回值为“default”时,变量是默认定义的;
(6)返回值为“override”时,被override指示符重新定义
(7)返回值为“automatic”时,是一个命令运行中自动化变量
下面接着分析如果带了-O参数,会进行什么处理:
ifneq ($(BUILD_DIR),) //如果BUILD_DIR不为空,即加了-O /xxx/xxx 编译参数的话,执行下列部分
saved-output := $(BUILD_DIR) //saved-output=/xxx/xxx
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}) //判断BUILD_DIR是否是个目录,是的话创建这个目录
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd) //进入创建好的目录,将绝对路径赋值给BUILD_DIR
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist)) //判断路径是否存在
endif # ifneq ($(BUILD_DIR),) //因为我这里为使用-O 参数,所以以上部分未执行
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) //CURDIR是当前路径的意思,我们这里BUILD_DIR为空,OBJTREE=$(CURDIR)
SPLTREE := $(OBJTREE)/spl //SPLTREE= $(CURDIR)/spl
SRCTREE := $(CURDIR) //SRCTREE=$(CURDIR)
TOPDIR := $(SRCTREE) //TOPDIR=$(CURDIR)
LNDIR := $(OBJTREE) //LNDIR=$(CURDIR)
export TOPDIR SRCTREE OBJTREE SPLTREE //导出变量供其它文件使用
MKCONFIG := $(SRCTREE)/mkconfig //MKCONFIG=$(CURDIR)/mkconfig,这个文件就是我们第一篇分析的文件
export MKCONFIG
ifneq ($(OBJTREE),$(SRCTREE)) //我这里的这两个变量都等于当前目录,所以没有进行REMOTE_BUILD=1的标记。
REMOTE_BUILD := 1
export REMOTE_BUILD
endif
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src //我这里这两个变量为空
以上部分就是makefile中对编译目录的定义部分,由于我这次编译未采用-O参数来指定编译目录,所以程序里大部分未执行,但是也在注释里都仔细分析了下。
第四部分
这里先定义了三个伪目标
SUBDIR_TOOLS = tools
SUBDIR_EXAMPLES = examples/standalone examples/api
SUBDIRS = $(SUBDIR_TOOLS)
.PHONY : $(SUBDIRS) $(VERSION_FILE) $(TIMESTAMP_FILE)
接下来是一个判断,判断config.mk是否存在,如果存在,执行下面的内容,不存在,后面再分析。
ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))
all:
sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mk
这里出现了一个目标all,但是没有依赖跟规则,如果继续往下看的话,还会有一个伪目标all
(all: $(ALL-y) $(SUBDIR_EXAMPLES)),这里大概说一下这俩个all的不同作用,首先解释几个概念:
1.当makefile中有两个相同目标的时候,会执行后一个目标。因为后一个目标会重载前一个。
比如:
all:
echo all1
all:
echo all2
执行make 会输出后一个all2
2.空命令
可以存在依赖文件,但是没有命令行。
比如
all:
或者
all: $(obj)
空命令的唯一作用是防止make在执行时,试图为重建这个目标去查找隐含命令,这里可能不是很好理解,之后会继续介绍。
3.makefile的执行规则和include
makefile首先被解析。遇到include。先去解析include的文件(假设为inc.mk),解析完毕以后再回头来解析原makefile。关键点是如果这个inc.mk不存在。make不会退出。而是先提出一个警告,继续处理原makefile的内容。等到原makefile的内容处理完毕以后。会尝试使用规则来重建这个inc.mk文件,也就是尝试将这个inc.mk文件当做一个目标来执行。如果不能重建出这个inc.mk。那么报告一个错误,make退出。如果这个inc.mk重建成功了。那么将原makefile的状态重置,重新开始执行这个makefile。
这里来分析一下我们的uboot:
假如我们第一次执行make xxx_conifig后,再次执行make命令,我们首先遇到的就是:
all:
sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mk
这里我们先假设如果没有第一个all目标(注释掉这一目标行),会怎么运行:
由于两个mk文件都不存在,但根据makefile执行规则这时候并不会退出,而是先执行完整个makefile,再回头来看include的文件。然后回过头将include/autoconf.mk以及 include/autoconf.mk.dep当做一个目标执行。因此才会有Generating include/autoconf.mk
Generating include/autoconf.mk.dep的输出。完毕后重置makefile状态。重新执行makefile。此时autoconf.mk和autoconf.mk.dep都有了。
但这个时候并没有编译uboot, 因为我们执行的命令是make 。后面没有带参数,因此makefile会编译默认遇到的第一个目标。因为我们注释了第一个all:所以直接执行了include。打开autoconf.mk.dep看到第一行就是include/autoconf.mk: include/common.h 。这就是makefile遇到的第一个目标include/autoconf.mk。因此将include/autoconf.mk当做终极目标执行了。此时的include/autoconf.mk是前一次刚产生的,所以是最新的。makefile认为没有必要重新执行。因此什么都不做,最后输出了make: `include/autoconf.mk’ is up to date.这里也就理解了前面的第三条 空命令的唯一作用是防止make在执行时,试图为重建这个目标去查找隐含命令,这个隐含的命令就是执行第一个遇到的目标。
如果有第一个all:的话。makefile就知道需要执行的终极目标是 all。而不是include的autoconf.mk.dep里面的include/autoconf.mk。
继续执行到遇到后面的all: 后面的all将覆盖前面的all。执行这里的操作。所以最终执行的是第二个all
因此第一个all:的含义就是:
如果你 执行make的时候没有带任何其他目标。单独的一个make。可以避免以autoconf.mk.dep里面的include/autoconf.mk作为错误目标。
如果你执行make的时候带了目标。这个all:有不有都无所谓。
第五部分
如果主板代码显式地指定了LDSCRIPT或CONFIG_SYS_LDSCRIPT,则使用它(如果没有,则失败)。否则,在标准位置搜索链接器脚本。
LDSCRIPT_MAKEFILE_DIR = $(dir $(LDSCRIPT))
ifndef LDSCRIPT //如果没有定义LDSCRIPT
#LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
ifdef CONFIG_SYS_LDSCRIPT //如果定义了CONFIG_SYS_LDSCRIPT
# need to strip off double quotes
LDSCRIPT := $(subst ",,$(CONFIG_SYS_LDSCRIPT))
endif
endif
ifndef LDSCRIPT //如果没有定义LDSCRIPT,构建自己的lds
ifeq ($(CONFIG_NAND_U_BOOT),y)
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
//CONFIG_NAND_U_BOOT=y,LDSCRIPT LDSCRIPT= $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
//如果LDSCRIPT为空,即上面的 $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds 不存在,使用$(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
endif
endif
ifeq ($(wildcard $(LDSCRIPT)),) //如果CONFIG_NAND_U_BOOT不等于y,这个时候LDSCRIPT为空
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds //
endif
ifeq ($(wildcard $(LDSCRIPT)),) //如果 $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds不存在
LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),) //如果LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot.lds不存在
LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds
# We don't expect a Makefile here
LDSCRIPT_MAKEFILE_DIR =
endif
ifeq ($(wildcard $(LDSCRIPT)),) //如果$(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds也不存在报错,找不到链接脚本
$(error could not find linker script)
endif
endif
这一部分主要就是说如果没有定义自己特殊的连接脚本,就使用默认的连接脚本,使用哪一个根据配置来。这里我也不知道使用哪一个,但是可以通过make时的输出信息来找一下,我这里找到应该是/u-boot-2012.04.01/arch/arm/cpu/u-boot.lds,即LDSCRIPT :=
(
T
O
P
D
I
R
)
/
a
r
c
h
/
(TOPDIR)/arch/
(TOPDIR)/arch/(ARCH)/cpu/u-boot.lds。
这里makefile中链接脚本的使用分析完了,我们接着分析。
第六部分
这一部分是定义OBJS与LIBS,根据之前导出的五个变量ARCH CPU BOARD VENDOR SOC来自动加载LIBS与OBJS,这里就不详细解释这一部分代码了。
OBJS = $(CPUDIR)/start.o
ifeq ($(CPU),x86)
OBJS += $(CPUDIR)/start16.o
OBJS += $(CPUDIR)/resetvec.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += $(CPUDIR)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += $(CPUDIR)/resetvec.o
endif
OBJS := $(addprefix $(obj),$(OBJS))
LIBS = lib/libgeneric.o
LIBS += lib/lzma/liblzma.o
LIBS += lib/lzo/liblzo.o
LIBS += lib/zlib/libz.o
LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
"board/$(VENDOR)/common/lib$(VENDOR).o"; fi)
LIBS += $(CPUDIR)/lib$(CPU).o
ifdef SOC
LIBS += $(CPUDIR)/$(SOC)/lib$(SOC).o
endif
ifeq ($(CPU),ixp)
LIBS += arch/arm/cpu/ixp/npe/libnpe.o
endif
ifeq ($(CONFIG_OF_EMBED),y)
LIBS += dts/libdts.o
endif
LIBS += arch/$(ARCH)/lib/lib$(ARCH).o
LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o \
fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/yaffs2/libyaffs2.o \
fs/ubifs/libubifs.o
LIBS += net/libnet.o
LIBS += disk/libdisk.o
LIBS += drivers/bios_emulator/libatibiosemu.o
LIBS += drivers/block/libblock.o
LIBS += drivers/dma/libdma.o
LIBS += drivers/fpga/libfpga.o
LIBS += drivers/gpio/libgpio.o
LIBS += drivers/hwmon/libhwmon.o
LIBS += drivers/i2c/libi2c.o
LIBS += drivers/input/libinput.o
LIBS += drivers/misc/libmisc.o
LIBS += drivers/mmc/libmmc.o
LIBS += drivers/mtd/libmtd.o
LIBS += drivers/mtd/nand/libnand.o
LIBS += drivers/mtd/onenand/libonenand.o
LIBS += drivers/mtd/ubi/libubi.o
LIBS += drivers/mtd/spi/libspi_flash.o
LIBS += drivers/net/libnet.o
LIBS += drivers/net/phy/libphy.o
LIBS += drivers/pci/libpci.o
LIBS += drivers/pcmcia/libpcmcia.o
LIBS += drivers/power/libpower.o
LIBS += drivers/spi/libspi.o
ifeq ($(CPU),mpc83xx)
LIBS += drivers/qe/libqe.o
LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
endif
ifeq ($(CPU),mpc85xx)
LIBS += drivers/qe/libqe.o
LIBS += drivers/net/fm/libfm.o
LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
endif
ifeq ($(CPU),mpc86xx)
LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
LIBS += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
endif
LIBS += drivers/rtc/librtc.o
LIBS += drivers/serial/libserial.o
ifeq ($(CONFIG_GENERIC_LPC_TPM),y)
LIBS += drivers/tpm/libtpm.o
endif
LIBS += drivers/twserial/libtws.o
LIBS += drivers/usb/eth/libusb_eth.o
LIBS += drivers/usb/gadget/libusb_gadget.o
LIBS += drivers/usb/host/libusb_host.o
LIBS += drivers/usb/musb/libusb_musb.o
LIBS += drivers/usb/phy/libusb_phy.o
LIBS += drivers/usb/ulpi/libusb_ulpi.o
LIBS += drivers/video/libvideo.o
LIBS += drivers/watchdog/libwatchdog.o
LIBS += common/libcommon.o
LIBS += lib/libfdt/libfdt.o
LIBS += api/libapi.o
LIBS += post/libpost.o
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
LIBS += $(CPUDIR)/omap-common/libomap-common.o
endif
ifeq ($(SOC),mx5)
LIBS += $(CPUDIR)/imx-common/libimx-common.o
endif
ifeq ($(SOC),mx6)
LIBS += $(CPUDIR)/imx-common/libimx-common.o
endif
ifeq ($(SOC),s5pc1xx)
LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
endif
ifeq ($(SOC),exynos)
LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
endif
LIBS := $(addprefix $(obj),$(sort $(LIBS)))
.PHONY : $(LIBS)
LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).o
LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
ifdef USE_PRIVATE_LIBGCC
ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
PLATFORM_LIBGCC = $(OBJTREE)/arch/$(ARCH)/lib/libgcc.o
else
PLATFORM_LIBGCC = -L $(USE_PRIVATE_LIBGCC) -lgcc
endif
else
PLATFORM_LIBGCC := -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
endif
PLATFORM_LIBS += $(PLATFORM_LIBGCC)
export PLATFORM_LIBS
LDPPFLAGS += \
-include $(TOPDIR)/include/u-boot/u-boot.lds.h \
-DCPUDIR=$(CPUDIR) \
$(shell $(LD) --version | \
sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')
__OBJS := $(subst $(obj),,$(OBJS))
__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
第七部分
接下来我们分析all目标:
all: $(ALL-y) $(SUBDIR_EXAMPLES)
ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
我们这里重点分析u-boot.bin的生成:
$(obj)u-boot.bin: $(obj)u-boot //这个u-boot是elf格式的文件
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
$(BOARD_SIZE_CHECK)
$(obj)u-boot: depend \
$(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
$(GEN_UBOOT)
ifeq ($(CONFIG_KALLSYMS),y)
smap=`$(call SYSTEM_MAP,u-boot) | \
awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \
$(CC) $(CFLAGS) -DSYSTEM_MAP="\"$${smap}\"" \
-c common/system_map.c -o $(obj)common/system_map.o
$(GEN_UBOOT) $(obj)common/system_map.o
endif
第一个依赖:depend
depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE) \
$(obj)include/autoconf.mk \
$(obj)include/generated/generic-asm-offsets.h \
$(obj)include/generated/asm-offsets.h
for dir in $(SUBDIRS) $(CPUDIR) $(LDSCRIPT_MAKEFILE_DIR) ; do \
$(MAKE) -C $$dir _depend ; done
CPUDIR=arch/
(
A
R
C
H
)
/
c
p
u
/
(ARCH)/cpu/
(ARCH)/cpu/(CPU)
因此,depend会去这些目录(也就是目录tools [examples/standalone、examples/api] arch/arm/cpu/armv7/)执行_depend目标。
第二个依赖$(SUBDIR_TOOLS)
因为之前定义过:
SUBDIR_TOOLS=tools
SUBDIRS = $(SUBDIR_TOOLS)
$(SUBDIRS): depend
$(MAKE) -C $@ all
所以该部分就是去tools目录执行目标all
第三个依赖OBJS
$(OBJS): depend
$(MAKE) -C $(CPUDIR) $(if $(REMOTE_BUILD),$@,$(notdir $@))
其实就是构建arch/arm/cpu/armv7/start.o
第四个依赖LIBBOARD
$(LIBBOARD): depend $(LIBS)
$(MAKE) -C $(dir $(subst $(obj),,$@)
这个目标的依赖文件有LIBS,所以说其实是LIBS这个目标,即第五个目标先被执行,
上面有定义过
LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).o
LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
之前在跟目录下的MKconigi文件中,有过如下定义:
if [ -z "${vendor}" ] ; then
BOARDDIR=${board}
else
BOARDDIR=${vendor}/${board}
fi
所以我们这里BOARDDIR=samsung/smdk2410,所以这里就是构建board/samsung/smdk2410中的makefile。
第五个依赖LIBS
$(LIBS): depend $(SUBDIR_TOOLS)
$(MAKE) -C $(dir $(subst $(obj),,$@))
大部分文件的编译都在这一步了。这些就是上面添加的LIBS相关的库。
第六个依赖LDSCRIPT
$(LDSCRIPT): depend
$(MAKE) -C $(dir $@) $(notdir $@)
这个目标就是我们上面定义的LDSCRIPT,但是这个目录下没有makefile
第七个依赖u-boot.lds
$(obj)u-boot.lds: $(LDSCRIPT)
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$< >$@
这部分执行对应的是输出信息里的:
arm-linux-gcc -E -g -Os -fno-common -ffixed-r8 -msoft-float -D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0x0 -I/home/zhangjun/u-boot-2012.04.01/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/arm-linux-gcc-4.4.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.3/include -pipe -DCONFIG_ARM -D__ARM__ -marm -mabi=aapcs-linux -mno-thumb-interwork -march=armv4 -include /home/zhangjun/u-boot-2012.04.01/include/u-boot/u-boot.lds.h -DCPUDIR=arch/arm/cpu/arm920t -ansi -D__ASSEMBLY__ -P - </home/zhangjun/u-boot-2012.04.01/arch/arm/cpu/u-boot.lds >u-boot.lds
到这里我们依赖部分就分析完了,接下来我们继续分析命令部分:
$(GEN_UBOOT)
ifeq ($(CONFIG_SANDBOX),y)
GEN_UBOOT = \
cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
-Wl,--start-group $(__LIBS) -Wl,--end-group \
$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map -o u-boot
else
GEN_UBOOT = \
cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
$(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
endif
这里对应的是输出的这部分:
cd /home/zhangjun/u-boot-2012.04.01 && arm-linux-ld -pie -T u-boot.lds -Bstatic -Ttext 0x0 $UNDEF_SYM arch/arm/cpu/arm920t/start.o --start-group api/libapi.o arch/arm/cpu/arm920t/libarm920t.o arch/arm/cpu/arm920t/s3c24x0/libs3c24x0.o arch/arm/lib/libarm.o common/libcommon.o disk/libdisk.o drivers/bios_emulator/libatibiosemu.o drivers/block/libblock.o drivers/dma/libdma.o drivers/fpga/libfpga.o drivers/gpio/libgpio.o drivers/hwmon/libhwmon.o drivers/i2c/libi2c.o drivers/input/libinput.o drivers/misc/libmisc.o drivers/mmc/libmmc.o drivers/mtd/libmtd.o drivers/mtd/nand/libnand.o drivers/mtd/onenand/libonenand.o drivers/mtd/spi/libspi_flash.o drivers/mtd/ubi/libubi.o drivers/net/libnet.o drivers/net/phy/libphy.o drivers/pci/libpci.o drivers/pcmcia/libpcmcia.o drivers/power/libpower.o drivers/rtc/librtc.o drivers/serial/libserial.o drivers/spi/libspi.o drivers/twserial/libtws.o drivers/usb/eth/libusb_eth.o drivers/usb/gadget/libusb_gadget.o drivers/usb/host/libusb_host.o drivers/usb/musb/libusb_musb.o drivers/usb/phy/libusb_phy.o drivers/usb/ulpi/libusb_ulpi.o drivers/video/libvideo.o drivers/watchdog/libwatchdog.o fs/cramfs/libcramfs.o fs/ext2/libext2fs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o fs/reiserfs/libreiserfs.o fs/ubifs/libubifs.o fs/yaffs2/libyaffs2.o lib/libfdt/libfdt.o lib/libgeneric.o lib/lzma/liblzma.o lib/lzo/liblzo.o lib/zlib/libz.o net/libnet.o post/libpost.o board/samsung/smdk2410/libsmdk2410.o --end-group /home/zhangjun/u-boot-2012.04.01/arch/arm/lib/eabi_compat.o -L /usr/local/arm/arm-linux-gcc-4.4.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.3 -lgcc -Map u-boot.map -o u-boot
到这里uboot的elf文件就构建完成了,下面就是生成.bin文件。
$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
$(BOARD_SIZE_CHECK)
对应我这里输出的下面部分:
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
至此编译的分析就完成了。