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)编译命令。
评论
查看更多