2設置編譯選項
PLATFORM_RELFLAGS =
PLATFORM_CPPFLAGS = #編譯選項
PLATFORM_LDFLAGS = #連接選項
用這3個變量表示交叉編譯器的編譯選項,在后面Make會檢查交叉編譯器支持的編譯選項,然后將適當的選項添加到這3個變量中。
#
# 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在后面的代碼定義為延時變量,其中的CC即arm-linux-gcc。函數cc-option用于檢查編譯器CC是否支持某選項。將2個選項作為參數傳遞給cc-option函數,該函數調用CC編譯器檢查參數1是否支持,若支持則函數返回參數1,否則返回參數2 (因此CC編譯器必須支持參數1或參數2,若兩個都不支持則會編譯出錯)。可以像下面這樣調用cc-option函數,并將支持的選項添加到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
對于arm開發板,其中的CROSS_COMPILE在lib_arm/config.mk文件中定義:
CROSS_COMPILE ?= arm-linux-
因此以上代碼指定了使用前綴為“arm-linux-”的編譯工具,即arm-linux-gcc,arm-linux-ld等等。
4包含與開發板相關的配置文件
# Load generated board configuration
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 specificrules
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包含進來,而這個文件并不存在,但是由于用的是“sinclude”命令,所以并不會報錯。
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
$(BOARD)的值是mini2440,VENDOR的值是samsung,因此BOARDDIR的值是samsung/mini2440。BOARDDIR變量表示開發板特有的代碼所在的目錄。
ifdef BOARD
sinclude$(TOPDIR)/board/$(BOARDDIR)/config.mk #include board specific rules
endif
Make將“board/samsung/mini2440/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”的字樣。
5指定隱含的編譯規則
# 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
例如:根據以上的定義,以“.s”結尾的目標文件將根據第一條規則由同名但后綴為“.S”的源文件來生成,若不存在“.S”結尾的同名文件則根據最后一條規則由同名的“.c”文件生成。
下面回來接著分析Makefile的內容:
# 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需要的庫文件,包括平臺/開發板相關的目錄、通用目錄下相應的庫,都通過相應的子目錄編譯得到的。
對于mini2440開發板,以上跟平臺相關的有以下幾個:
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
其余都是與平臺無關的。
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
對于有的開發板,U-Boot支持在NAND Flash啟動,這些開發板的配置文件定義了CONFIG_NAND_U_BOOT,CONFIG_ONENAND_U_BOOT。對于s3c2440,U-Boot原始代碼并不支持NAND Flash啟動,因此也沒有定義這兩個宏。
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)
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目標就是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)編譯命令。
評論
查看更多