我是靠谱客的博主 复杂手链,最近开发中收集的这篇文章主要介绍uboot顶层Makefile解读 咬牙也要啃下它,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

下面从开头顺序对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中。

注意:这个config.mk文件是配置uboot时零时生成的,这个问题在uboot的配置一文中讲清楚了。

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行:
确定了交叉编译工具链的位置和前缀。

注意:144注释的行:#CROSS_COMPILE = arm-linux-,在交叉编译工具链目录中,我们可以导出符号链接为arm-linux-和导出环境变量为CROSS_COMPILE = arm-linux-,即可以使用这一行。

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路径就是上面提到的编译输出文件的路径。

$(addprefix fixstring,string1 string2 ...)
fixstring表示任意要添加的固定前缀,(string1和string2 前缀 fixstring)在逗号的后面可以是一个或多个要添加前缀的子字符串,多个子字符串之间用空格隔开,当然,你也可以像前面的例子一样用变量。


204~251 行:

生成库文件


Mkakefiel源文件截图:

Mkakefiel解读:

286~289行:
准备生成的各种目标(镜像)文件。

291行:
出现第一个目标 all,就是Makefile的总目标。
接下来的各种目标就是编译后生成的具体文件。

续待…

最后

以上就是复杂手链为你收集整理的uboot顶层Makefile解读 咬牙也要啃下它的全部内容,希望文章能够帮你解决uboot顶层Makefile解读 咬牙也要啃下它所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部