U-boot顶层Makefile文件分析(一)

news2024/9/20 20:36:12

在阅读 uboot 源码之前,肯定是要先看一下顶层 Makefile,分析 gcc 版本代码的时候一定是先从顶层 Makefile 开始的,然后再是子 Makefile,这样通过层层分析 Makefile 即可了解整个工程的组织结构。顶层 Makefile 也就是 uboot 根目录下的 Makefile 文件,由于顶层 Makefile 文件内容比较多,所以我们将其分开来看。

版本号

VERSION = 2016
PATCHLEVEL = 03
SUBLEVEL =
EXTRAVERSION =
NAME =

VERSION 是主版本号,PATCHLEVEL 是补丁版本号,SUBLEVEL 是次版本号,这三个一起构成了 uboot 的版本号,比如当前的 uboot 版本号就是“2016.03”。EXTRAVERSION 是附加版本信息,NAME 是和名字有关的,一般不使用这两个。

MAKEFLAGS变量
make是支持递归调用的,也就是在Makefile中使用“make”命令来执行其它的Makefile文件,一般都是子目录中的Makefile文件。

假如在当前目录下存在一个“subdir”子目录,这个子目录中又有其对应的 Makefile 文件,那么这个工程在编译的时候其主目录中的 Makefile 就可以调用子目录中的 Makefile,以此来完成所有子目录的编译。主目录的 Makefile 可以使用如下代码来编译这个子目录:

$(MAKE) -C subdir

$(MAKE)就是调用“make”命令,-C指定子目录,有时候我们需要向子make传递变量,这个时候使用export来导出要传递给子make的变量即可,如果不希望哪个变量传递给子make 的话就使用“unexport"声明不导出。

export VARIABLE …… //导出变量给子 make 。
unexport VARIABLE…… //不导出变量给子 make。

有两个特殊的变量:“SHELL和MAKEFLAGS”,这两个变量除非使用“unexport”声明,否则的话在整个make的执行过程中,它们的值始终自动的传递给子make。

在uboot的主Makefile中有如下代码:

MAKEFLAGS += -rR --include-dir=$(CURDIR)

+=给变量MAKEFLAGS追加了一些值
-rR表示禁止使用内置的隐含规则和变量定义
–include-dir指明搜索路径
$(CURDIR)当前目录

命令输出
uboot默认编译不会再终端显示完整命令,都是短命令。
在这里插入图片描述
在终端中输出短命令虽然看起来很清爽,但是不利于分析 uboot 的编译过程。
可以通过设置变量“V=1“来实现完整的命令输出,这个在调试 uboot 的时候很有用。

顶层Makefile中控制命令输出的代码如下:

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

使用iref判断“$(origin V)”和“command line”是否相等。
这里用到了 Makefile中的函数 origin,origin 和其他的函数不一样,它不操作变量的值,origin 用于告诉你变量是哪来的。

$(origin <variable>)

variable是变量名,origin函数的返回值就是变量来源,因此 ( o r i g i n V ) 就是变量 V 的来源。如果变量 V 是在命令行定义的 n a m e 它的来源就是 c o m m a n d l i n e ,这样两者的值就像等。当这两个相等的时候变量 K B U I L D V E R B O S E 就等于 V 的值,比如在命令行中输入“ V = 1 “的话那么 K B U I L D V E R B O S E = 1 。如果没有在命令行输入 V 的话 K B U I L D V E R B O S E = 0 。 i f e q ( (origin V)就是变量V的来源。 如果变量V是在命令行定义的name它的来源就是command line,这样两者的值就像等。 当这两个相等的时候变量 KBUILD_VERBOSE 就等于 V 的值,比如在命令行中输入“ V=1 “ 的 话 那 么 KBUILD_VERBOSE=1 。 如 果 没 有 在 命 令 行 输 入 V 的 话KBUILD_VERBOSE=0。 ifeq( (originV)就是变量V的来源。如果变量V是在命令行定义的name它的来源就是commandline,这样两者的值就像等。当这两个相等的时候变量KBUILDVERBOSE就等于V的值,比如在命令行中输入V=1“的话那么KBUILDVERBOSE=1。如果没有在命令行输入V的话KBUILDVERBOSE=0ifeq((KBUILD_VERBOSE),1),如果 KBUILD_VERBOSE 为 1 的话变量 quiet和 Q 都为空,如果 KBUILD_VERBOSE=0 的话变量 quiet 为“quiet_“,变量 Q 为“@”。

Makefile中会用到变量quiet和Q来控制编译的时候是否在终端输出完整的命令。

$(Q)$(MAKE)$(build)=tools

如果V=0,上述命令实际上为@ make $(build)=tools。
make在执行的时候默认会在终端输出命令,但在命令前面加上@就不会。
当 V=1 的时候 Q 就为空,上述命令就是“make $(build)=tools”,因此在 make 执行的过程,命令会被完整的输出在终端上。

有些命令会有两个版本,比如

quiet_cmd_sys ?= SYM $@
cmd_sym ?= $(OBJDUMP) -t $< >$@

sys命令分为quiet_cmd_sym和cmd_sym两个版本,这两个命令的功能都是一样的,区别在于make执行的时候输出的命令不同。
quiet_cmd_sys命令输出信息少,也就是短命令。
而cmd_xxx命令输出信息多,就是完整的命令。

  • 如果变量quiet为空,整个命令都会输出。
  • 如果变量 quiet 为“quiet_”的话,仅输出短版本。
  • 如果变量 quiet 为“silent_”的话,整个命令都不会输出。

静默输出
设置V=0或者命令行中不定义V的话,编译uboot的时候终端中显示短命令,但是还是会有命令输出,有时候我们在编译uboot的时候不需要输出命令,这个就可以使用 uboot 的静默输出,编译的时候使用“make -s”即可实现静默输出。

设置编译结果输出目录
uboot可以将编译出来的目标文件输出到单独的目录中,在 make 的时候使用“O”来指定输出目录。
比如“make O=out”设置目标文件输出到out目录中。
这么做是为了将源文件和编译产生的文件分开,,当然也可以不指定 O 参数,不指定的话源文件和编译产生的文件都在同一个目录内,一般我们不指定O参数。

# kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntaxes are supported.
# In both cases the working directory must be the root of the kernel src.
# 1) O=
# Use "make O=dir/to/store/output/files/"
#
# 2) Set KBUILD_OUTPUT
# Set the environment variable KBUILD_OUTPUT to point to the directory
# where the output files shall be placed.
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
# The O= assignment takes precedence over the KBUILD_OUTPUT environment
# variable.

# KBUILD_SRC is set on invocation of make in OBJ directory
# KBUILD_SRC is not intended to be used by the regular user (for now)
ifeq ($(KBUILD_SRC),)

# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

# That's our default target when none is given on the command line
PHONY := _all
_all:

# Cancel implicit rules on top Makefile
$(CURDIR)/Makefile Makefile: ;

ifneq ($(KBUILD_OUTPUT),)
# Invoke a second make in the output directory, passing relevant variables
# check that the output directory actually exists
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
								&& /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error failed to create output directory "$(saved-output)"))

PHONY += $(MAKECMDGOALS) sub-make

$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
	@:

sub-make: FORCE
	$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
	-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))

# Leave processing to above invocation of make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)
endif # ifeq ($(KBUILD_SRC),)

ifeq (“$(origin O)”, “command line”)
KBUILD_OUTPUT := $(O)
endif

  • 判断O是否来自于命令行,如果来自命令行,KBUILD_OUTPUT =$(O),因此变量KBUILD_OUTPUT就是输出目录。

ifneq ($(KBUILD_OUTPUT),)

  • 判断KBUILD_OUTPUT是否为空
  • 调用mkdir命令,创建KBUILD_OUTPUT目录,并且创建成功以后的绝对路径赋值给KBUILD_OUTPUT,至此,通过O指定的输出目录就存在了。

模块编译
在uboot中也允许单独编译某个模块,使用命令“make M=dir”或旧语法“make SUBDIRS=dir”也支持。

获取主机架构和系统
接下来顶层Makefile会获取主机架构和系统,也就是我们电脑的架构和系统:

HOSTARCH := $(shell uname -m | \
	sed -e s/i.86/x86/ \
	    -e s/sun4u/sparc64/ \
	    -e s/arm.*/arm/ \
	    -e s/sa110/arm/ \
	    -e s/ppc64/powerpc/ \
	    -e s/ppc/powerpc/ \
	    -e s/macppc/powerpc/\
	    -e s/sh.*/sh/)

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
	    sed -e 's/\(cygwin\).*/cygwin/')

export	HOSTARCH HOSTOS
  • 定义了一个HOSTARCH变量,保存主机架构,这里调用shell命令“uname -m”获取架构名称。
    在这里插入图片描述
    可以看出电脑主机架构为x86_64,shell中的“|”表示管道,意思是将左边的输出作为右边的输入。

sed -e是替换命令,“sed -e s/i.86/x86/”表示将管道输入的字符串i.86替换为“x86”。

HOSTOS用于保存主机OS的值,使用管道将“Linux”作为后面tr ‘[:upper:]’ '[:lower:]'的输入。
tr ‘[:upper:]’ '[:lower:]'将所有的大小字母替换为小写字母,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512295.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

界面控件DevExpress WPF MessageBox组件,进一步增强用户体验!

在DevExpress WPF v22.2版本中&#xff0c;官方引入了一系列功能来帮助改进一个常见WPF UI元素——MessageBox的用户体验&#xff0c;新的MessageBox相关选项包括&#xff1a; 文本选择支持自定义图像支持带有计时器的按钮&#xff0c;可以自动关闭窗口 ThemedMessageBox类允…

OJ练习第103题——最大矩形

最大矩形 力扣链接&#xff1a;85. 最大矩形 题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 示例 输入&#xff1a;matrix [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”…

数据库管理-第七十四期 我的Oracle ACE之路(20230511)

数据库管理 2023-05-11 第七十四期 我的Oracle ACE之路1 差点错过2 ACE Associate3 一路走来总结 第七十四期 我的Oracle ACE之路 “终于等到你&#xff0c;还好我没放弃”。经过了整整4个月20天的等待&#xff0c;我终于收到了Oracle ACE Associate的确认邮件&#xff0c;成为…

『python爬虫』17. 线程池和进程池以及线程池实战(保姆级图文)

目录 1. 线程池和进程池解决的是调度问题2. 线程池3. 线程池实战&#xff1a;爬取西游记的标题总结 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 1. 线程池和进程池解决的是调度问题 ⽹站的数据太多了&#xff0…

典型随机噪声激励

1.按噪声的起源分类 根据噪声的起源&#xff0c;分为内部噪声和外部噪声。 内部噪声&#xff1a;来源于系统内部的涨落运动或被检测信号&#xff0c;如布朗粒子受到周围液体分子的无规则碰撞即为内部噪声&#xff1b; 外部噪声&#xff1a;来自系统所处外部环境的随机涨落&…

endNote X9 导入英文文献(谷歌学术、web of science 等)

文章目录 1 导入英文文献&#xff08;谷歌学术、web of science 等&#xff09;2 EndNote X9 插入参考文献常见问题总结3 EndNote X9 快速上手教程&#xff08;毕业论文参考文献管理器&#xff09; 1 导入英文文献&#xff08;谷歌学术、web of science 等&#xff09; 谷歌学术…

Vite如何实现秒级依赖预构建的能力

大家都知道, Vite是一个提倡 no-bundle 的构建工具,相比于传统的 Webpack,能做到开发时的模块按需编译,而不用先打包完再加载。这一点我们在快速上手这一节已经具体地分析过了。 需要注意的是,我们所说的模块代码其实分为两部分,一部分是源代码,也就是业务代码,另一部…

线性代数——特征值与特征向量的性质

&#xff08;1&#xff09;设A为方阵&#xff0c;则A与 A T A^{T} AT有相同的特征值。 此处用到了两个关键性质&#xff0c;一&#xff1a;单位阵的转置为其本身,二&#xff1a;转置并不改变行列式的值。 &#xff08;2&#xff09;&#xff1a; 设n阶方阵A&#xff08; a i j…

汽车电子的电磁兼容性分析

随着电子技术的不断发展&#xff0c;新技术越来越多的应用到汽车领域&#xff0c;因此各个电子装置和电子控制系统必须相互适应&#xff0c;这就是电磁兼容性(EMC)要求。为了保证汽车可靠性&#xff0c;设计师必须在早期设计阶段分析电磁兼容性问题。目前市场上推出了一些电磁兼…

jdk20-虚拟线程简单了解

普通线程 JDK中的普通线程和操作系统线程是一对一关系的&#xff0c;存在映射关系&#xff1b;由操作系统进行调度&#xff0c;线程过多&#xff0c;会引起操作系统频繁调度&#xff0c;导致线程上下文切换太过频繁&#xff0c;反而会降低系统性能&#xff1b;线程越多&#x…

即时通讯私有化部署有哪些优势?企业在选择时需要考虑哪些因素?

即时通讯私有化部署是一种将即时通讯系统部署在企业的私有服务器上&#xff0c;以保护企业的信息安全和隐私。相比于使用Saas部署即时通讯应用程序&#xff0c;私有化部署可以更好地保护企业的机密信息&#xff0c;避免信息泄露的风险。 在即时通讯私有化部署中&#xff0c;企业…

半导体热处理设备微环境中的精密微正压控制解决方案

摘要&#xff1a;针对半导体热处理设备微环境中的微正压精密控制&#xff0c;本文分析了现有技术造成微正压控制不稳定的原因&#xff0c;提出了相应的解决方案。解决方案主要是采用绝对电容真空计替代压差计&#xff0c;采用真空低漏率的高速电动针阀和电动球阀替代气体质量流…

【Python 正则表达式】零基础也能精通的正则表达式学习路线与参考资料

文章目录 一、正则表达式基础二、进阶知识三、优秀实践参考资料&#xff1a; 一、正则表达式基础 正则表达式是一种用来描述字符模式的语言&#xff0c;它可以用来匹配、查找、替换字符串中的文本。在Python中&#xff0c;我们可以使用re模块来操作正则表达式。 正则表达式基…

MATLAB三维曲面作图(三)特殊效果的绘图(灯光)

首先&#xff0c;我们来绘制一个海螺的复杂图形 close all t linspace(0,2*pi,512); [u v] meshgrid(t); a -0.4; b 0.5; c 0.1; n 3; x (a*(1-v/(2*pi)).*(1cos(u))c).*cos(n*v); y (a*(1-v/(2*pi)).*(1cos(u))c).*sin(n*v); z b*v/(2*pi)a*(1-v/(2*pi)).*sin(u); s…

RabbitMQ详解(五):过期时间TTL、死信队列、磁盘监控

过期时间TTL&#xff08;Time To Live&#xff09; 过期时间TTL表示可以对消息设置预期的时间&#xff0c;在这个时间内都可以被消费者接收获取&#xff1b;过了之后消息将自动被删除。 目前有两种方法可以设置 第一种方法是通过队列属性设置&#xff0c;队列中所有消息都有…

App报毒-Google Play保护机制,已屏蔽不安全的应用

一、概述 解决安卓app在海外国际版本如&#xff1a;华为、OPP/VIVO、小米和荣耀报毒问题.触发Google Play保护机制. 安卓app报毒爆红&#xff0c;vivo手机爆红&#xff0c;oppo小米华为荣耀手机报毒&#xff0c;手机安装app时提示报毒&#xff0c;有的app是刚打包出来、有的是用…

Cocos Creator 3.7.3 正式上线,渲染管线和算法持续更新

Cocos Creator 3.7.3 正式发布。该版本对近日用户反馈的一系列关键性问题进行了集中修复&#xff0c;也对一部分性能进行了优化&#xff0c;提升了用户体验&#xff0c;建议所有 v3.x 用户升级。 Engine Features Render Graph 自定义渲染管线支持 GLES 后端Deprecate addRast…

【C++】五一假期,我学会了C++类和对象 ( 看完这篇你也能学会 ~ )

文章目录 ☑️前言✅类和对象【&#x1f3c6;上篇&#x1f3c6;】一. 面向过程和面向对象初步认识二. 与类的完美邂逅❤️1. 类的引入2. 类的定义 三. 增进与类的距离❤️1. 类的访问限定符及封装1.1. 访问限定符1.2. 封装【⭐重大思想⭐】 2. 类的作用域3. 类的实例化 四. 类对…

专访惠众科技|元宇宙应用如何借助3DCAT实时云渲染实现流畅大并发呈现?

当前互联网流量红利已经逐渐消失&#xff0c;营销同质化愈发严重。在这样的背景下&#xff0c;催生了以为元宇宙 焦点的虚拟产业经济。元宇宙在各行各业中以不同形式快速萌生、成长&#xff0c;呈现出多元化的应用场景。尤其是众多品牌&#xff0c;将元宇宙视为品牌建设与营销新…

JavaScript - 进阶+高级(笔记)

前言 给孩子点点关注吧&#xff01;&#x1f62d; 本篇文章主要记录以下几部分&#xff1a; 进阶&#xff1a; 作用域&#xff1b;函数进阶&#xff08;函数提升、函数参数、箭头函数&#xff09;&#xff1b;解构赋值&#xff1b;对象进阶&#xff08;构造函数、实例成员、静…