uboot移植之主Makefile分析
1:#uboot 的版本号 VERSION = 1 #主版本号 PATCHLEVEL = 3 #次版本号 SUBLEVEL = 4 #再次版本号 EXTRAVERSION = #关于uboo的一些另外的描述 #变量U_BOOT_VERSION用来保存uboot的版本信息 U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = $(obj)include/version_autogenerated.h //存放变量U_BOOT_VERSION,也就是版本信息 # 这个文件是编译时产生的中间文件include/version_autogenerated.h,这个文件的内容为 #define U_BOOT_VERSION "U-Boot 1.3.4"。 2:HOSTARCH(主机架构)和HOSTOS(主机操作系统) HOSTARCH := $(shell uname -m | \ sed -e s/i.86/i386/ \ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ \ -e s/sa110/arm/ \ -e s/powerpc/ppc/ \ -e s/ppc64/ppc/ \ -e s/macppc/ppc/) HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ sed -e 's/\(cygwin\).*/cygwin/') export HOSTARCH HOSTOS (1)shell uname -m,脚本执行的方法,可以通过shell + 命令来直接执行, uname -m表示获取主机架构 (2)| 表示管道,前面的表达式的结果作为后面表达式的一个输入,从而得到最终的输出,这里也就是shell uname -m得到的结果通过管道作为 sed -e的输入。 (3)sed -e 直接在命令模式下进行sed的动作,s 表示替代。所以这部分的意识就是,通过执行uname -m来获取主机的架构,然后通过管道的方法根据主机的架构来得到我们需要的主机架构,比如,我的主机架构是i686,那么sed -e s /i.86/i386,所以HOSTARCH := i386。(:=表示覆盖之前的内容) (4)uname -s 表示获取操作系统的名字 ,我们在ubuntu下开发,所以操作系统就是Linux,然后通过tr '[:upper:]' '[:lower:]'将大写字母改为小写,也就是HOSTOS := linux 3:ifeq (,$(findstring s,$(MAKEFLAGS))) XECHO = echo else XECHO = : endif 判断是否为静默编译,静默编译就是不在控制台打印Makefile里面的信息,但是其他文件的信息还是会被打印出来。 $(findstring s,$(MAKEFLAGS)的意思是在MAKEFLAGS查找字符 s ,也就是假如我们编译的时候输入的是 make -s 则为静默编译。 4:ifdef O ifeq ("$(origin O)", "command line") BUILD_DIR := $(O) endif endif 原地编译或者是单独文件编译, 单独文件编译实现的方法有两种 (1)通过make O = xxx(输出文件的pathname)来实现,主要这种方式在我们配置和清除的时候也要添加 O = xxx,也就是 make distclean O = xxx make x210_sd_config O = xxx make O = xxx (2)通过定义 export BUILD_DIR=xxx(输出文件的pathname)来实现, O=xxx的优先级高于export BUILD_DIR=xxx 5:OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) #输出文件目录 SRCTREE := $(CURDIR) #当前目录,Makefile的当前目录也就是uboot的根目录 TOPDIR := $(SRCTREE) #顶层目录 LNDIR := $(OBJTREE) #链接文件目录 export TOPDIR SRCTREE OBJTREE 根据上面选择的是原地编译还是单独文件编译来确定并且导出这几个环境变量,用于后面使用,当选择原地编译时OBJTREE = SRCTREE OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) 如果 (if $(BUILD_DIR)为真(也就是BUILD_DIR被赋值)则OBJTREE = BUILD_DIR,否则OBJTREE = CURDIR。 6:MKCONFIG := $(SRCTREE)/mkconfig export MKCONFIG 定义并保存环境变量MKCONFIG。uboot根目录下的mkconfig文件是一个很重要的文件,uboot的配置就是根据这个文件的内容来实现的。 7:include $(obj)include/config.mk export ARCH CPU BOARD VENDOR SOC 包含$(obj)目录下的include目录下的config.mk文件,这个文件的内容为 ARCH = arm CPU = s5pc11x BOARD = x210 VENDOR = samsung SOC = s5pc110 config.mk文件也是在配置的时候生成的 obj = OBJTREE,当原地编译的时候OBJTREE = SRCTREE = 源码根目录, 8:ifeq ($(ARCH),arm) #CROSS_COMPILE = arm-linux- #CROSS_COMPILE = /usr/local/arm/4.4.1-eabi-cortex-a8/usr/bin/arm-linux- #CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi- 通过ARCH的值来确定交叉编译工具链的前缀,CROSS_COMPILE的值其实就是交叉编译工具链的前缀。 9:include $(TOPDIR)/config.mk 添加根目录下的config.mk文件,这个文件的主要作用是 (1)补全交叉编译工具链,前面,在CROSS_COMPILE变量中我们保存了交叉编译工具链的前缀,其后缀就是在这个文件中补全的 (2)sinclude $(OBJTREE)/include/autoconf.mk:添加编译目录下的/include/autoconf.mk文件,这个文件是配置后生成的,里面全是CONFIG_开头的宏,这些宏定义左右着配置的uboot属于哪一款开发板。而这个文件的生成材料是顶层目录下的include/configs/xxx.h这个头文件,里面的一个头文件对应一款开发板,这个头文件的内容就是去描述或者说是配置这个开发板的硬件相关的信息。 (3)TEXT_BASE:链接地址的值 10:OBJS = cpu/$(CPU)/start.o,以及后面的LIBS = lib_generic/libgeneric.a等是在指定编译时需要添加的文件。 11:ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) $(obj)u-boot.dis ifeq ($(ARCH),blackfin) ALL += $(obj)u-boot.ldr all: $(ALL) $(obj)u-boot.hex: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ 当我们make编译的时候其实就是make all,当我们make all的时候又会生成类似于u-boot.hex的很多小目标,其中要注意的是最后一个目标unconfig unconfig: @rm -f $(obj)include/config.h $(obj)include/config.mk \ $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \ $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep \ $(obj)board/$(VENDOR)/$(BOARD)/config.mk unconfig这个目标就是rm -f移除我们在配置的时候生成的配置文件,这也是我们在make x210_sd_config之后再次执行make x210_sd_config时得到的效果是一样的,原因就是x210_sd_config依赖于unconfig,unconfig而将我们之前配置的文件全部移除了。 12:x210_sd_config : unconfig @$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110 @echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk @表示静默执行 $(MKCONFIG) 表示引用MKCONFIG这个环境变量,也就是根目录下的mkconfig,并且向这个文件传递了$(@:_config=) arm s5pc11x x210 samsung s5pc110这6个参数。 当我们执行make x210_sd_config的时候其实就是执行了这里的x210_sd_config这个目标。 本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1919951