概述
下面从开头顺序对Makefile重要的功能模块截图,并且逐一分析它实现的功能,面面俱到。
Mkakefiel源文件截图:
Mkakefiel解读: 设置uboot版本号
VERSION = 1 #主版本号
PATCHLEVEL = 3 # 补丁版本号
SUBLEVEL = 4 #次版本号
EXTRAVERSION = xx # 附加信息
U_BOOT_VERSION =$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE => $(obj)include/version_autogenerated.h
由上面的四个变量组合形成一个由点(.)分开的版本号U_BOOT_VERSION
即:U_BOOT_VERSION=1.3.4.xx
编译后会在include目录下生成一个版本配置文件version_autogenerated.h,文件内容就是这个uboot的版本号。
Mkakefiel源文件截图:
Mkakefiel解读: 获取宿主机CPU架构和操作系统类型
HOSTARCH := $(shell uname -m| #shell uname -m 用执行linux命令方式,获取主机CPU信息
sed -e s/i.86/i386/ #将 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/)
sed 是linux下文本处理工具
格式:sed ‘s/要替换的字符串/新的字符串/g’
上面的“shell uname -m”命令是用来获取宿主机的CPU类型,然后过管道“|”,将获取的值传递到后面的运算输入中,这个输入的值与后面的字符串逐一匹配,当匹配相同时,发生替换操作。例如:如果获取的宿主机值是 i.86,那就把结果替换成i386,最后把这个值赋给 变量HOSTARCH。
Mkakefiel源文件截图:
Mkakefiel解读: 获取宿主机操作系统类型
HOSTOS := $(shell uname -s| tr '[:upper:]' '[:lower:]' | # 大写转小写
sed -e 's/(cygwin).*/cygwin/') #一种在windows上模拟Linux的虚拟环境
export HOSTARCH HOSTOS #导出环境变量
“shell uname -s ”获取宿主机的操作系统类型,把大写转换成小写,赋值给变量HOSTOS 。
Mkakefiel源文件截图:
Mkakefiel解读: 编译输出信息设置(允许静默编译)
MAKEFLAGS 是编译时传递给 命令make 的参数,findstring会从MAKEFLAGS 寻找是否有“s”,如果有,则XECHO = echo,否则XECHO = :(即为空)。当XECHO = echo时,编译中就会打印信息,否则不打印。
使用方法:
make -s 静默编译
make 打印信息
Mkakefiel源文件截图:
Mkakefiel解读: 是否存在定义的编译输出目录
首先解释编译输出几种方式:
默认编译:
编译生成的文件和源文件混一起,编译时直接输入命令make
make
指定编译输出目录:
这种方法是指定一个目录作为编译生成文件的输出目录。有两种指定输出目录的方法。
- 方法一
编译时make后面带一个参数
make O=/tmp/build all
- 方法二
命令行中先导出一个全局变量,然后再“make”
export BUILD_DIR=/tmp/build
make
ifdef O
ifeq ("$(origin O)", "command line") #command line:比较返回变量和在命令行定义的变量
BUILD_DIR := $(O)
endif
endif
$(origin variable):
origin函数作用是返回一个表明变量 varible 是如何定义的字符串。
字符串包括:
- undefined:未定义的变量
- default:比如 CC CXX Variables Used by Implicit Rules
- environment:环境变量
- environment override:make -e 选项所覆盖的环境变量
- file:在makefile中定义的变量
- command line:在命令行定义的变量
- override:makefile 中通过 override 得到的变量
- automatic:makefile中保留的变量,如 @,^
上面Makefile内容的意思是,首先判断是否定义了O。如果变量“O”的值和在参数行“command line”中定义的变量相等,那么就会把变量“O”赋值给BUILD_DIR 。
从上面的命令可以看出,假如方法一于方法二同时使用了,第一种编译方法’make O=/tmp/build all’有更高的优先级。
Mkakefiel源文件截图:
Mkakefiel解读: 编译输出目录判断和设置
ifneq ($(BUILD_DIR),) #如果变量BUILD_DIR非空
saved-output := $(BUILD_DIR) #则把这个变量赋值给saved-output
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}) #如果BUILD_DIR是一个目录名称,则创建它
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd) #进入BUILD_DIR目录,PWD命令显示当前路径名,并把当前路径名赋给BUILD_DIR变量,
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist)) #If语句判断BUILD_DIR是否存在,为空显示错误(两个逗号表示空)
endif # ifneq ($(BUILD_DIR),)
OBJTREE := $(if> $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) #输出目录
SRCTREE := $(CURDIR) #源码目录
TOPDIR := $(SRCTREE) #顶层目录
LNDIR := $(OBJTREE) #连接目录
export TOPDIR> SRCTREE OBJTREE
MKCONFIG := $(SRCTREE)/mkconfig #在源文件目录下的文件mkconfig ,赋值文件名给MKCONFIG
export MKCONFIG
ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD := 1 #置位,在用户指定的目录进行编译
export REMOTE_BUILD
endif
上面的首先是检查变量是否被定义,如果定义了就创建相应的目录。
CURIDR是一个MAKEFILE的内嵌变量,代表当前路径.如果定义了BUILD_DIR,就将BUILD_DIR赋给OBJTREE,如果没有定义,就将CURIDR赋给OBJTREE;
所以如果编译时没有定义编译路径,及没有定义BUILD_DIR,则以上所有变量都是CURDIR,即当前目录,也就是uboot的顶层目录
Mkakefiel源文件截图:
Mkakefiel解读: 编译输出目录变量赋值
ifneq> ($(OBJTREE),$(SRCTREE)) #如果两个路径不相同,下面的输出和源码目录分别赋不同的路径
obj := $(OBJTREE)/
src := $(SRCTREE)/
else #否则它们的值是空
obj :=
src :=
endif
export obj src #导出全局变量
意思是说,如果我们定义了编译输出目录,那么编译目录就和源文件目录就不形同了,此时编译输出目录obj就赋值为我们定义的输出目录。
Mkakefiel源文件截图:
Mkakefiel解读:
126~128行:
如果变量ARCH和powerpc匹配,则ARCH变量被赋值ppc。
130行:
判断是否$(obj)(当前编译输出路径)下的include/config.mk存在。函数 $(wildcard pattern) 列出patterm指定目录下的文件是否存在。
133行:
包含$(obj)目录下的include/config.mk文件到当前Makefiel中。
134行:
导出全局的环境变量,ARCH CPU BOARD VENDOR SOC,这些变量就是config.mk文件里被配置的内容。config.mk这个文件是MKCONFIG配置脚本配置而生成的文件,如下图:
ARCH : 目标CPU架构(即ARM架构)
CPU: 即目标CPU所属型号
BOARD: 开发板型号
VENDOR :厂商名称
SOC: CPU具体型号
136~142行:
叉编译工具链的前缀CROSS_COMPILE没有被定义。
143~147行:
确定了交叉编译工具链的位置和前缀。
Mkakefiel源文件截图:
Mkakefiel解读:
include $(TOPDIR)/config.mk
包含顶层目录下的config.mk文件config.mk,这个文件里面主要定义了交叉编译器及选项和编译规则,这个文件将在下另外一篇文章中进行分析。
Mkakefiel源文件截图:
Mkakefiel解读:
190行:
U-boot需要的目标文件,start.o必须放首位。
191~200行,判断CPU类型来确定使用哪些.o文件
200行:
在OBJS前缀obj,意思是说,在OBJS前缀一个路径obj。这个obj路径就是上面提到的编译输出文件的路径。
fixstring表示任意要添加的固定前缀,(string1和string2 前缀 fixstring)在逗号的后面可以是一个或多个要添加前缀的子字符串,多个子字符串之间用空格隔开,当然,你也可以像前面的例子一样用变量。
204~251 行:
生成库文件
Mkakefiel源文件截图:
Mkakefiel解读:
286~289行:
准备生成的各种目标(镜像)文件。
291行:
出现第一个目标 all,就是Makefile的总目标。
接下来的各种目标就是编译后生成的具体文件。
续待…
最后
以上就是复杂手链为你收集整理的uboot顶层Makefile解读 咬牙也要啃下它的全部内容,希望文章能够帮你解决uboot顶层Makefile解读 咬牙也要啃下它所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复