VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION = XXXXX
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
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
版本号由VERSION、PATCHLEVEL、SUBLEVEL、EXTRAVERSION组合生成,形成最终的版本号U_BOOT_VERSION。此例中生成的版本号U_BOOT_VERSION = 1.3.4XXXXX,VERSION_FILE指定路径,在下面的代码中进行相应操作,在路径为uboot/include的version_autogenerated.h文件中写入宏定义来定义版本号,此宏定义为#define U_BOOT_VERSION "U-Boot 1.3.4XXXXX"
。
HOSTARCH表示主机的CPU架构,此代码用shell uname -m得到此主机的CPU版本号,用管道" | "把管道前面的一个运算式的输出作为后面的一个输入,然后用sed进行操作,将CPU的架构内容存在环境变量HOSTARCH中(sed -e s/a/b就是把a替换为b)。
HOSTOS表示主机的操作系统,用shell uname -s得到主机的操作系统,再用管道将其大写内容全部转换为小写,然后存入环境变量HOSTOS中。
# Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif
使用静默编译可以在编译过程中不打印编译信息,实现代码如上,使用方法是在编译make时在后面加-s,这个-s会作为MAKEFLAGS参数传到里面,findstring s找到s符号,ifeq里面的内容不成立,从而执行else的代码,令XECHO为空即可实现静默编译。
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
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
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
# Make sure CDPATH settings don't interfere
unexport CDPATH
原地编译和指定目录输出编译部分代码如上,如果要实现指定目录编译,则有两个方法,第一种是在编译时输入“make O=输出目录”;第二种则是导入环境变量“export BUILD_DIR=输出目录”,然后再make。如果两个都指定了编译输出目录,则第一种方法指定的目录具有更高的优先级。
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
的含义是如果BUILD_DIR被赋值,则将其作为OBJTREE的目录,如果未赋值就把CURDIR作为其目录。
代码中的OBJTREE是编译出的.o文件存放的目录,SRCTREE和TOPDIR是源码的根目录,也就是uboot目录,使用原地编译时OBJTREE和SRCTREE相等,使用指定目录编译时OBJTREE就是指定的那个输出目录,而SRCTREE是根目录。
下面将根目录下的mkconfig赋值给MKCONFIG。接着判断是否使用原地编译,如果未使用原地编译,则在REMOTE_BUILD中写入1,如果用原地编译则不进行操作,最后再次判断是否使用原地编译,如果未使用原地编译就将OBJTREE赋值给obj,将SRCTREE赋值给src,如果用了就将obj和src赋值为空。
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
x210_sd_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
这里我们使用x210_sd_config的配置,先make x210_sd_config,使用uboot根目录下的mkconfig此配置文件),对应传入相应的参数,生成uboot/include/config.mk,里面的内容如下
ARCH = arm
CPU = s5pc11x
BOARD = x210
VENDOR = samsung
SOC = s5pc110
最后在uboot/board/samsung/x210/config.mk中输入链接地址
TEXT_BASE = 0xc3e00000
。
其中ARCH是当前目标的CPU架构,它的选择会影响交叉编译工具链CROSS_COMPILE的选择,接着进行的一大段代码是判断ARCH是什么CPU架构并且选用相应的交叉编译工具链和包含相应的库文件和驱动代码的。
(2)x210_sd_config中的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
$(obj)include/autoconf.mk: $(obj)include/config.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Extract the config macros ; \
$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
sed -n -f tools/scripts/define2mk.sed > $@
这段代码用uboot/include/config.h的内容作为原材料,自动生成uboot的相关配置信息文件autoconf.mk,而原材料文件uboot/include/config.h的内容为宏定义#include
,可以理解为这个配置信息的根本原材料在uboot/include/configs/x210_sd.h。而uboot/include/config.h文件以及文件的内容是在mkconfig配置文件中配置并且生成的,下面就来进行mkconfig配置文件的详解。
while [ $# -gt 0 ] ; do
case "$1" in
--) shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
*) break ;;
esac
done
如上代码,如果传参数大于0则进行相应匹配操作,操作完成后break跳出while循环。
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1
判断板子是否有名字,没有则赋值$1的传参名,判断传参数量如果小于4或者大于6就说明传参数量是错的。
echo "Configuring for ${BOARD_NAME} board..."
#
# Create link to architecture specific headers
#
if [ "$SRCTREE" != "$OBJTREE" ] ; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/include/asm-$2 asm
LNPREFIX="../../include2/asm/"
cd ../include
rm -rf asm-$2
rm -f asm
mkdir asm-$2
ln -s asm-$2 asm
else
cd ./include
rm -f asm
ln -s asm-$2 asm
fi
rm -f asm-$2/arch
打印“Configuring for (板名) board…”字样,判断SRCTREE和OBJTREE的值是否相等来判断是否是原地编译,如果不是原地编译就进行else下面的操作。最后删除uboot/include/asm-$2/arch。
if [ -z "$6" -o "$6" = "NULL" ] ; then
ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch
fi
判断,若不为空就执行创建链接令uboot/include/asm-$2/arch指向include/asm-arm/arch-$6。
在这里我们的$1-$6参数分别为$1:x210_sd、$2:arm、$3:s5pc11x、$4:x210 、$5:samsung 、$6:s5pc110,并且 $# = 6。
if [ "$3" = "s5pc1xx" ] ; then
rm -f regs.h
ln -s $6.h regs.h
rm -f asm-$2/arch
ln -s arch-$3 asm-$2/arch
fi
if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi
令uboot/include/regs.h文件指向uboot/include/s5pc110.h,然后再删除uboot/include/asm-arm/arch,再创建uboot/include/asm-arm/arch来指向include/asm-arm/arch-s5pc11x。
echo "ARCH = $2" > config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
在uboot/include/config.mk中输入ARCH、CPU、BOARD、VENDOR、SOC等信息。创建这个文件是为了让Makefile去包含,对应上面第4部分的内容。
(7)判断是否需要创建uboot/include/config.h并且向里面输入相应内容
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include $1 .h>" >>config.h
判断APPEND的值来确定是否有config.h这个文件,如果有就打印,如果没有就创建,然后在里面输入相应的内容。对应第5部分内容来理解。
主要作用有两方面
代码如下
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
ifndef LDSCRIPT
#LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
ifeq ($(CONFIG_NAND_U_BOOT),y)
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
else
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
endif
endif
代码如上,判断uboot/include/autoconf.mk中CONFIG_NAND_U_BOOT的值来确定用哪个链接脚本。
此目标下面进行了各种编译工作。