2設(shè)置編譯選項(xiàng)
PLATFORM_RELFLAGS =
PLATFORM_CPPFLAGS = #編譯選項(xiàng)
PLATFORM_LDFLAGS = #連接選項(xiàng)
用這3個(gè)變量表示交叉編譯器的編譯選項(xiàng),在后面Make會(huì)檢查交叉編譯器支持的編譯選項(xiàng),然后將適當(dāng)?shù)倪x項(xiàng)添加到這3個(gè)變量中。
#
# Option checker (courtesy linux kernel)to ensure
# only supported compiler options are used
#
cc-option = $(shell if $(CC) $(CFLAGS)$(1) -S -o /dev/null -xc /dev/null \
》/dev/null 2》&1; then echo “$(1)”; else echo “$(2)”;fi ;)
變量CC和CFLAGS在后面的代碼定義為延時(shí)變量,其中的CC即arm-linux-gcc。函數(shù)cc-option用于檢查編譯器CC是否支持某選項(xiàng)。將2個(gè)選項(xiàng)作為參數(shù)傳遞給cc-option函數(shù),該函數(shù)調(diào)用CC編譯器檢查參數(shù)1是否支持,若支持則函數(shù)返回參數(shù)1,否則返回參數(shù)2 (因此CC編譯器必須支持參數(shù)1或參數(shù)2,若兩個(gè)都不支持則會(huì)編譯出錯(cuò))。可以像下面這樣調(diào)用cc-option函數(shù),并將支持的選項(xiàng)添加到FLAGS中:
FLAGS +=$(call cc-option,option1,option2)
3指定交叉編譯工具
#
# Include the make variables (CC, etc.。。)
#
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
對(duì)于arm開(kāi)發(fā)板,其中的CROSS_COMPILE在lib_arm/config.mk文件中定義:
CROSS_COMPILE ?= arm-linux-
因此以上代碼指定了使用前綴為“arm-linux-”的編譯工具,即arm-linux-gcc,arm-linux-ld等等。
4包含與開(kāi)發(fā)板相關(guān)的配置文件
# Load generated board configuration
sinclude $(OBJTREE)/include/autoconf.mk
ifdef ARCH
sinclude $(TOPDIR)/lib_$(ARCH)/config.mk # include architecture dependend rules
endif
$(ARCH)的值是“arm”,因此將“l(fā)ib_arm/config.mk”包含進(jìn)來(lái)。lib_arm/config.mk腳本指定了交叉編譯器,添加了一些跟CPU架構(gòu)相關(guān)的編譯選項(xiàng),最后還指定了cpu/arm920t/u-boot.lds為U-Boot的連接腳本。
ifdef CPU
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk # include CPU specificrules
endif
$(CPU)的值是“arm920t”,因此將“cpu/arm920t/config.mk”包含進(jìn)來(lái)。這個(gè)腳本主要設(shè)定了跟arm920t處理器相關(guān)的編譯選項(xiàng)。
ifdef SOC
sinclude$(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk #include SoC specific rules
endif
$(SOC)的值是s3c24x0,因此Make程序嘗試將cpu/arm920t/s3c24x0/config.mk包含進(jìn)來(lái),而這個(gè)文件并不存在,但是由于用的是“sinclude”命令,所以并不會(huì)報(bào)錯(cuò)。
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
$(BOARD)的值是mini2440,VENDOR的值是samsung,因此BOARDDIR的值是samsung/mini2440。BOARDDIR變量表示開(kāi)發(fā)板特有的代碼所在的目錄。
ifdef BOARD
sinclude$(TOPDIR)/board/$(BOARDDIR)/config.mk #include board specific rules
endif
Make將“board/samsung/mini2440/config.mk”包含進(jìn)來(lái)。該腳本只有如下的一行代碼:
TEXT_BASE = 0x33F80000
U-Boot編譯時(shí)將使用TEXT_BASE作為代碼段連接的起始地址。
LDFLAGS += -Bstatic -T $(obj)u-boot.lds$(PLATFORM_LDFLAGS)
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
執(zhí)行完以上代碼后,LDFLAGS中包含了“-Bstatic -T u-boot.lds ”和“-Ttext 0x33F80000”的字樣。
5指定隱含的編譯規(guī)則
# Allow boards to use custom optimizeflags on a per dir/file basis
BCURDIR := $(notdir $(CURDIR))
$(obj)%.s: %.S
$(CPP)$(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $《
$(obj)%.o: %.S
$(CC) $(AFLAGS) $(AFLAGS_$(@F))$(AFLAGS_$(BCURDIR)) -o $@ $《 -c
$(obj)%.o: %.c
$(CC) $(CFLAGS) $(CFLAGS_$(@F))$(CFLAGS_$(BCURDIR)) -o $@ $《 -c
$(obj)%.i: %.c
$(CPP)$(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $《 -c
$(obj)%.s: %.c
$(CC) $(CFLAGS) $(CFLAGS_$(@F))$(CFLAGS_$(BCURDIR)) -o $@ $《 -c -S
例如:根據(jù)以上的定義,以“.s”結(jié)尾的目標(biāo)文件將根據(jù)第一條規(guī)則由同名但后綴為“.S”的源文件來(lái)生成,若不存在“.S”結(jié)尾的同名文件則根據(jù)最后一條規(guī)則由同名的“.c”文件生成。
下面回來(lái)接著分析Makefile的內(nèi)容:
# U-Boot objects.。。.order is important(i.e. start must be first)
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.afs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
fs/reiserfs/libreiserfs.afs/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))
LIBS變量指明了U-Boot需要的庫(kù)文件,包括平臺(tái)/開(kāi)發(fā)板相關(guān)的目錄、通用目錄下相應(yīng)的庫(kù),都通過(guò)相應(yīng)的子目錄編譯得到的。
對(duì)于mini2440開(kāi)發(fā)板,以上跟平臺(tái)相關(guān)的有以下幾個(gè):
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
其余都是與平臺(tái)無(wú)關(guān)的。
ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif
ifeq ($(CONFIG_ONENAND_U_BOOT),y)
ONENAND_IPL = onenand_ipl
U_BOOT_ONENAND = $(obj)u-boot-onenand.bin
ONENAND_BIN ?=$(obj)onenand_ipl/onenand-ipl-2k.bin
endif
對(duì)于有的開(kāi)發(fā)板,U-Boot支持在NAND Flash啟動(dòng),這些開(kāi)發(fā)板的配置文件定義了CONFIG_NAND_U_BOOT,CONFIG_ONENAND_U_BOOT。對(duì)于s3c2440,U-Boot原始代碼并不支持NAND Flash啟動(dòng),因此也沒(méi)有定義這兩個(gè)宏。
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。因此執(zhí)行“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的符號(hào)表,u-boot.bin是最終燒寫(xiě)到開(kāi)發(fā)板的二進(jìn)制可執(zhí)行的文件。
下面再來(lái)分析u-boot.bin文件生成的過(guò)程。ELF格式“u-boot”文件生成規(guī)則如下:
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)$(obj)u-boot.lds
$(GEN_UBOOT)
ifeq ($(CONFIG_KALLSYMS),y)
smap=`$(callSYSTEM_MAP,u-boot) | \
awk‘
2 ~ /[tTwW]/ {printf
1 $$3 “\\\\000”}’` ; \
$(CC)$(CFLAGS) -DSYSTEM_MAP=“\”$${smap}\“” \
-ccommon/system_map.c -o $(obj)common/system_map.o
$(GEN_UBOOT)$(obj)common/system_map.o
endif
這里生成的$(obj)u-boot目標(biāo)就是ELF格式的U-Boot文件了。由于CONFIG_KALLSYMS未定義,因此ifeq ($(CONFIG_KALLSYMS),y)與endif間的代碼不起作用。
其中depend,$(SUBDIRS),$(OBJS),$(LIBBOARD),$(LIBS),$(LDSCRIPT), $(obj)u-boot.lds是$(obj)u-boot的依賴,而$(GEN_UBOOT)編譯命令。
評(píng)論