以u-boot1.1.6为例,详细剖析u-boot的顶层Makefile:
VERSION = 1 #主版本号
PATCHLEVEL = 1 #次版本号
SUBLEVEL = 6 #再次版本号
EXTRAVERSION = #另外的附加的版本信息
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) #u-boot版本是1.1.6
VERSION_FILE = $(obj)include/version_autogenerated.h #定义了u-boot的版本号
# 通过定义上面4个变量且用.隔开构成最终的版本号。
# include/version_autogenerated.h文件是在编译完成后生成的文件,源目录是没有的,该文件里面是一个宏定义:
# #define U_BOOT_VERSION "U-Boot 1.1.6"
# 该宏定义内容就是Makefile中的u-boot版本号。
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/macppc/ppc/)
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\).*/cygwin/')
export HOSTARCH HOSTOS
# “sed –e”表示后面跟的是一串命令脚本。
# “s/i.86/i386/”表示要从标准输入中,查找到内容为“i.86”,然后替换成“i386”。其中“i.86”表达式的“.”为通配符。
# 遇到 ’i.86’ 就替换为 ‘i386’。
# shell中的“|”叫做管道,管道的作用就是把管道前面一个运算式的输出作为后面一个的输入再去做处理,
# 最终的输出才是我们整个式子的输出。
# HOSTARCH:主机的CPU的架构。直接在shell中执行“uname –m”输出主机CPU的体系架构类型i686。
# “i686”可以匹配命令“sed -e s/i.86/i386/”中的“i.86”,因此在我的机器上执行Makefile,HOSTARCH将被设置成“i386”。
# HOSTOS:主机操作系统。直接在shell中执行“uname –s”得到Linux。
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
# 这句话表示如果在编译的命令里面加入参数O(如 make O=/tmp).,就把O后面所指定的值赋给变量BUILD_DIR,
# (BUILD_DIR表示uboot的编译路径)。
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# 如果BUILD_DIR不为空,则将BUILD_DIR的值赋值给saved-output
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
# 如果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),)
# shell命令的意思是先进入到BUILD_DIR目录,然后调用PWD命令显示当前路径名,并把当前路径名赋给BUILD_DIR变量,
# If语句判断BUILD_DIR是否存在,如果还为空就显示错误(命令里面两个逗号之间表示空)
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) #输出目录
SRCTREE := $(CURDIR) #源码目录
TOPDIR := $(SRCTREE) #顶层目录
LNDIR := $(OBJTREE) #连接目录
export TOPDIR SRCTREE OBJTREE
# CURDIR代表当前的路径
# 所以如果编译时没有定义编译路径,及没有定义BUILD_DIR,则以上所有变量都是CURDIR,即当前目录,
# 也就是uboot的顶层目录
MKCONFIG := $(SRCTREE)/mkc