1. VERSION(24 ~ 29行)
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
VERSION:主版本号
PATCHLEVEL:次版本号
SUBLEVEL:修正版本号
EXTRAVERSION:扩展版本号
U_BOOT_VERSION:uboot的版本号
include/version_autogenerated.h文件是编译过程中自动生成的一个文件,因此源目录中没有,只有编译后才有。内容如下:
#define U_BOOT_VERSION "U-Boot 1.3.4"
2. HOSTARCH、HOSTOS(31 ~ 43行)
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
HOSTARCH:主机架构,主机的CPU架构是x86_64。首先执行uname -r得到i686,通过管道传送给sed命令,然后sed命令将执行sed -e s/i*86/i386将i686替换成i386,最后的结果是HOSTARCH=i386
HOSTOS:主机操作系统,主机操作是Linux。首先执行uname -s查看平台的系统,结果为Linux,然后通过管道传送给tr命令,tr命令利用字符类[:upper:]和[:lower:]将Linux字符串转换为linux,然后再利用sed命令,最后的结果是linux。
最后一句是导出HOSTARCH、HOSTOS。
3. 静默编译(50 ~ 54行)
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif
默认编译时命令行会打印很多编译信息,但是有时候不希望看到这些编译信息,后台编译即可,这就是静默编译。
使用方法:make -s(在make时加上-s标志)
4. 编译方法选择:原地编译 or 单独输出编译(56 ~ 123行)
#########################################################################
#
# U-boot build supports producing a object files to the separate external
# directory. Two use cases are supported:
#
# 1) Add O= to the make command line
# 'make O=/tmp/build all'
#
# 2) Set environement variable BUILD_DIR to point to the desired location
# 'export BUILD_DIR=/tmp/build'
# 'make'
#
# The second approach can also be used with a MAKEALL script
# 'export BUILD_DIR=/tmp/build'
# './MAKEALL'
#
# Command line 'O=' setting overrides BUILD_DIR environent variable.
#
# When none of the above methods is used the local build is performed and
# the object files are placed in the source directory.
#
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
export TOPDIR SRCTREE OBJTREE
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD := 1
export REMOTE_BUILD
endif
# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
# Make sure CDPATH settings don't interfere
unexport CDPATH
(1)编译复杂项目,Makefile提供了两种编译方式:原地编译和单独输出编译。
原地编译就是生成.o文件和.c文件放在同一目录下。这种编译的方式好处是处理简单,但是它也有坏处:第一,污染源文件目录;第二,一套源代码只能按照一种配置和编译方法进行处理,无法同时维护2个或2个以上的配置编译方式。
为了解决以上缺陷,Makefile还提供了单独输出编译,它的实现思路是在编译时指定一个输出目录,然后将所有编译生成的.o文件或其他文件都放到这个输出目录中。
使用方法:默认使用的是原地编译,使用单独输出编译需要指定输出目录,如下:
第1种方式:make O=输出目录
第2种方式:export BUILD_DIR=输出目录; make
第3种方式:两个都指定,但是'O=输出目录'的优先级要高于'BUILD_DIR=输出目录'。
(2)OBJTREE、SRCTREE、TOPDIR、LNDIR
OBJTREE:编译出的.o文件存放的目录。在默认编译下,OBJTREE=当前目录;在O=xxx下,OBJTREE=xxx。
SRCTREE:源码目录,uboot的根目录,当前目录。
TOPDIR:顶层目录,也就是uboot的根目录。
LNDIR:链接目录。
总结:在默认编译下,OBJTREE等于SRCTREE;在O=xxx下,OBJTREE与SRCTREE不相等。
(3)MKCONFIG
MKCOFNIG是一个变量,它的值是uboot根目录下的mkconfig。mkconfig是一个脚本文件,在uboot配置阶段使用。
5. 两个重要的环境变量:ARCH、CROSS_COMPILE(124 ~ 182行)
#########################################################################
ifeq ($(ARCH),powerpc)
ARCH = ppc
endif
ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))
# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = ppc_8xx-
endif
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 = /home/linuxwei/toolchain/arm-2009q3/bin/arm-none-linux-gnueabi-
endif
ifeq ($(ARCH),i386)
CROSS_COMPILE = i386-linux-
endif
ifeq ($(ARCH),mips)
CROSS_COMPILE = mips_4KC-
endif
ifeq ($(ARCH),nios)
CROSS_COMPILE = nios-elf-
endif
ifeq ($(ARCH),nios2)
CROSS_COMPILE = nios2-elf-
endif
ifeq ($(ARCH),m68k)
CROSS_COMPILE = m68k-elf-
endif
ifeq ($(ARCH),microblaze)
CROSS_COMPILE = mb-
endif
ifeq ($(ARCH),blackfin)
CROSS_COMPILE = bfin-uclinux-
endif
ifeq ($(ARCH),avr32)
CROSS_COMPILE = avr32-linux-
endif
ifeq ($(ARCH),sh)
CROSS_COMPILE = sh4-linux-
endif
ifeq ($(ARCH),sparc)
CROSS_COMPILE = sparc-elf-
endif # sparc
endif # HOSTARCH,ARCH
endif # CROSS_COMPILE
export CROSS_COMPILE
(1)include $(obj)include/config.mk
include/config.mk不是源码自带的,是在配置过程(make x210_sd_config)中自动生成的。
在x210下生成的config.mk的内容为:
ARCH = arm
CPU = s5pc11x
BOARD = x210
VENDOR = samsung
SOC = s5pc110
后面一行就将这5个变量使用export导出作为环境变量。
注:这两行的作用就是为当前Makefile定义了5个环境变量,之所以没有直接给出,是希望这5个值可以很容易、集中配置。
(2)ARCH
ARCH:当前编译的目标CPU的架构。ARCH来自于配置过程,在上面已导出,它的值会影响后面CROSS_COMPILE的值。
(3)CROSS_COMPILE
CROSS_COMPILE:交叉编译工具链的前缀。在uboot中使用前缀+后缀的组成工具链中的各种工具,原因是在不同的CPU架构上,交叉编译工具链只是前缀不一样,后缀都是一样的,因此在定义时只需要把前缀和后缀分开,使用前缀来区分不同架构的CPU,就可以实现可移植性。
使用有两种方式:在Makefile中直接更改;在编译时指定CROSS_COMPILE。
6. include $(TOPDIR)/config.mk(185行)
# load other configuration
include $(TOPDIR)/config.mk
包含config.mk,该文件还是比较重要的,它的解析参考《uboot根目录下的config.mk解析》。
7. 第一个目标:all(291行)
all: $(ALL)
注意一下uboot.*的生成。
8. 目标:unconfig(473 ~ 477行)
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
9. 目标:x210_sd_config(2589 ~ 2591行)
x210_sd_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
第1行命令:@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@:表示该条指令不显示。
$(MKCONFIG):MKCONFIG变量在前面已有定义,表示uboot根目录下的mkconfig,参考第4部分。
$(@:_config):@表示目标,即x210_sd_config,后面的‘:’表示要对其进行加工,即将目标中_config替换为空格。
经过以上分析,那么第1行命令替换完后的结果为mkconfig x210_sd arm s5pc11x x210 samsung s5pc110,也就是说该条指令的意思是执行mkconfig这个脚本文件,并给这个脚本文件传递6个参数,第1个参数为x210_sd,第2个参数为arm,第3个参数为s5pc11x,第4个参数为x210,第5个参数为samsung,第6个参数为s5pc110。
第2行命令:@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
@:表示该条指令不显示
echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk:表示将内容TEXT_BASE = 0xc3e00000写入到board/samsung/x210/config.mk文件中。