U-Boot学习(2):U-Boot编译和.config配置文件生成分析

上一节U-Boot学习(1):简介及命令行指令详解中,介绍了如何使用U-Boot。我们知道一个U-Boot可能要适配不同的硬件,所以不同的硬件就有不同的配置,配置后就可以编译U-Boot,最终生成镜像。U-Boot如何编译,以什么规则编译,编译后下载到内存中的哪里呢,这一切都在Makefile中。所以本节课就来分析一下U-Boot的Makefile的结构。

文章目录

  • 1 U-Boot源码
    • 1.1 下载
    • 1.2 目录结构
  • 2 U-Boot编译
    • 2.1 源码
    • 2.2 配置
    • 2.3 编译
  • 3 .config配置文件生成分析
    • 3.1 Makefile展开
    • 3.2 头文件依赖生成之fixdep工具
    • 3.3 .config文件生成

1 U-Boot源码

1.1 下载

1、官方源码

U-Boot官方的源码在Github上有对应的镜像:https://github.com/u-boot/u-boot,大家可以在这里下载源码。

2、半导体产商适配源码

前面说了,U-Boot主要是一个引导的操作,但是对于不同半导体产商的芯片来说,它们的接口类型和初始化方式都有差异,虽然U-Boot源码中做了一定的适配,但是不如半导体产商自身做的适配完善,比如NXP就提供了I.MX系列Cortex-A核芯片的U-Boot适配,可以在下面的地址中下载:https://github.com/nxp-imx/uboot-imx。

这里面提供的U-Boot基本上就是基于官方的开发板进行了适配,也就是说我们使用同一款芯片的话,假设Flash可以接到多个Flash接口上,可能官方开发板接在接口1,而你的产品接到了接口2,这时候你就可以在官方源码的基础上更改一下这个接口。如果需要网络启动,那对于以太网接口的初始化也是一样的,要适配你自己的开发板的硬件连接。

1.2 目录结构

解压U-Boot源码后,常见的文件夹的作用如下:

目录描述
/arch体系结构特定的文件
/arch/arm适用于ARM体系结构的通用文件(该目录下除了ARM架构外还有其他架构的,这里省略)
/api面向外部应用的机器/体系结构无关的API
/board依赖于板级别的文件
/boot支持镜像和引导
/cmdU-Boot命令函数
/common各体系结构通用的杂项函数
/configs板默认配置文件
/disk处理磁盘驱动分区的代码
/doc文档(一组ReST和README文件的混合)
/drivers设备驱动程序
/dts用于构建内部U-Boot fdt的Makefile
/env环境支持
/examples独立应用程序示例代码等
/fs文件系统代码(cramfs,ext2,jffs2等)
/include头文件
/lib所有体系结构通用的库例程
/Licenses各种许可文件
/net网络代码
/post自检
/scripts各种构建脚本和Makefile
/test各种单元测试文件
/tools用于构建和签名FIT镜像等的工具

2 U-Boot编译

2.1 源码

这里我们以NXP官方提供的U-Boot源码为例进行分析,我这就下载了当前这个仓库的默认分支if_v2022.04。下载解压后,目录结构如下:
在这里插入图片描述

2.2 配置

(1)不同开发板的配置

我们现在想要编译U-Boot,首先我们来看看README中怎么说:
在这里插入图片描述
也就是说在configs目录下有对应不同的配置文件,不同的配置文件对应不同的开发板,我们根据自己的需求选择一个配置文件进行make,这里我就选择目录下的imx6ul_isiot_emmc_defconfig。在执行指令之前,需要安装以下四个库

sudo apt install make
sudo apt install gcc
sudo apt install bison
sudo apt install flex

现在我们执行make imx6ul_isiot_emmc_defconfig,看一下执行的结果:
在这里插入图片描述
此时目录下会生成一个.config文件:
在这里插入图片描述
实际上就是一些宏定义,一会编译U-Boot的时候肯定会用到这些宏定义。

(2)交叉编译器的配置
继续看README:
在这里插入图片描述
也就是说我们要指定用什么交叉编译器来编译U-Boot。

  • 交叉编译器下载地址:https://releases.linaro.org/components/toolchain/binaries/

这里我下载了gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz,把交叉编译器解压到了/usr/local/arm/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf,然后需要在/etc/profile的最后添加环境变量:export PATH=$PATH:/usr/local/arm/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf/bin,最后输入source /etc/profile让环境变量立即生效(每次打开终端都要输入一次,要一直生效需要重启系统)。

  • 选择交叉编译器的时候,需要注意交叉编译器所支持的处理器架构要与芯片的处理器架构一样

现在我们就直接在U-Boot的Makefile中修改CROSS_COMPILE变量为我们交叉编译器的执行名前缀:
在这里插入图片描述

2.3 编译

现在就可以直接在U-Boot目录下输入make进行编译,由于编译过程比较久,我们可以指定-j12,表示使用12个线程编译以加快编译速度。输入make -j12,但是会报错:
在这里插入图片描述
这是因为U-Boot的部分文件使用了OpenSSL协议,我们需要安装相关库:

sudo apt install libssl-dev

然后我们还会遇到问题:
在这里插入图片描述
这里我们不使用LDO旁路检测,直接在.config文件中注释掉CONFIG_LDO_BYPASS_CHECK即可。
在这里插入图片描述
现在就编译成功了,目录下多了很多的文件
在这里插入图片描述

3 .config配置文件生成分析

前面我们虽然编译出来了u-boot.bin,但是这个文件的链接地址是否和我们开发板的RAM相对应呢,还有刚刚的make XXXconfig完成了什么操作,.config中的内容代表什么呢。这些都与Makefile有关,所以现在我们就来分析一下Makefile。

  • 对于Makefile相关知识及常用函数可以参考我的另一篇文章:Makefile基础、常用函数及通用Makefile

3.1 Makefile展开

由前面的介绍我们知道,在configs目录下有对应不同的配置文件,前面我们选择了make imx6ul_isiot_emmc_defconfig这个配置,我们来看一下Makefile中对应的生成规则:
在这里插入图片描述

  • %为通配符,即匹配了所有make xxxdeconfig

展开来实际上是:

make -f ./scripts/Makefile.build obj=scripts/kconfig imx6ul_isiot_emmc_defconfig

这句make指令使用了-f选项指定了要使用的Makefile文件的路径,即./scripts/Makefile.build。然后,通过obj=scripts/basic传递了一个变量obj和我们的目标名。

1、outputmakefile

PHONY += outputmakefile

outputmakefile:
ifneq ($(KBUILD_SRC),)
	$(Q)ln -fsn $(srctree) source
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree)
endif

可以看到如果KBUILD_SRC为空的话,才会执行下面的指令,但是实际上KBUILD_SRC是为空的,文档中有以下两句:

# 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)

其中第一句指出KBUILD_SRC是在调用make时设置的(如果不设置的话就使用当前目录)。

2、FORCE

PHONY += FORCE
FORCE:

这里FORCE被声明为.PHONY(伪目标),所以如果FORCE是其他目标的依赖,那么无论FORCE是否实际上被修改,这些目标都将始终被认为是需要重新生成的。因此,make将忽略文件时间戳,总是认为.PHONY目标需要重新生成。

3、scripts_basic

# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;

我们在Makefile中搜索QMAKEbuild等变量,展开后就是:

make -f ./scripts/Makefile.build obj=scripts/basic
rm -f .tmp_quiet_recordmcount

这里的make和前面的%config的语句很像,最终还是执行./scripts/Makefile.build这个Makefile。

3.2 头文件依赖生成之fixdep工具

这里就不继续往下分析了,Makefile.build和Linux内核的Makefile.build很像,可以参考前面分享的Makefile介绍的文章。这里就直接说结论:scripts_basic会生成fixdep应用。
这个应用是用来生成头文件依赖的,下面来介绍一下相关的知识。


在编译过程中,使用-MD选项可以生成依赖关系文件。这些文件包含了源代码文件和它们之间的依赖关系,通常以 Makefile 的规则格式保存,这样可以在后续的编译过程中更好地管理文件的依赖关系。这在大型项目中是很有用的,因为它可以确保在修改一个源文件后,只重新编译与之相关的文件,而不是整个项目。

下面是一个简单的例子,假设有一个C语言项目,包含三个源文件:main.cutils.c,和header.hmain.c 包含了main函数,utils.c包含了一些工具函数,而header.h包含了函数的声明。

假设我们使用GCC编译器,可以通过以下命令使用-MD选项生成依赖关系文件:

gcc -MD -o main main.c utils.c

这个命令会生成main.d文件,内容可能如下:

main.o: main.c header.h
utils.o: utils.c header.h

这表示在编译main.c时,依赖于main.cheader.h;在编译utils.c时,依赖于utils.cheader.h。这样,如果修改了header.h,只有依赖于它的文件会重新编译,而不是整个项目。

这对于Makefile来说非常有用,因为它们可以根据这些依赖关系文件来判断哪些文件需要重新编译,从而提高编译效率。


fixdep是一个用于生成Makefile依赖关系的工具。它主要用于处理头文件之间的依赖关系,以确保在构建U-Boot时,当某个头文件发生变化时,只重新编译与之相关的文件,而不是整个项目。具体来说,fixdep主要完成以下任务:

  1. 解析源代码文件中的#include指令:fixdep分析源代码文件,找到其中包含的头文件。
  2. 生成Makefile规则: 通过分析源代码文件中的 #include 指令,fixdep 生成一个包含依赖关系的 Makefile 规则。这些规则通常包含了源文件和其所依赖的头文件,以及它们之间的关系。
  3. 输出依赖关系: fixdep将生成的 Makefile 规则输出到标准输出或指定的文件中,以便后续的构建工具(如Make)使用。

例如,在U-Boot的Makefile中可能包含类似如下的使用fixdep的命令:

depend:
    $(SRCTREE)/scripts/fixdep $(CFLAGS) $(CPPFLAGS) $(SRCARCH) $(SRC) > .depend

这个命令使用fixdep生成头文件依赖关系,并将结果保存到.depend文件中。在Makefile的其他地方可以包含这个文件,以便Make工具能够使用这些依赖关系。

3.3 .config文件生成

前面的%config目标最终会执行:

scripts/kconfig/conf  --defconfig=arch/../configs/imx6ul_isiot_emmc_defconfig Kconfig

我们可以通过执行make imx6ul_isiot_emmc_defconfig V=1看到:
在这里插入图片描述
在U-Boot中,scripts/kconfig/conf是Kconfig工具的配置脚本,用于处理配置文件和生成配置信息。Kconfig是Linux内核中使用的配置系统,也被U-Boot采用,用于管理项目的配置选项。conf脚本会根据imx6ul_isiot_emmc_defconfig中的配置生成一个配置文件.config ,其中包含了用户所做的配置选项。这个文件会被后续的构建过程使用,以根据用户的配置生成相应的代码。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【GoLang入门教程】Go语言几种标准库介绍(六)

文章目录 前言几种库Net库 (网络库,支持 Socket、HTTP、邮件、RPC、SMTP 等)重要的子包和功能:示例 OS库(操作系统平台不依赖平台操作封装)主要功能:示例 path库(兼容各操作系统的路径操作实用函数)常用函数&#xff1…

ejs默认配置 原型链污染

文章目录 ejs默认配置 造成原型链污染漏洞背景漏洞分析漏洞利用 例题 [SEETF 2023]Express JavaScript Security ejs默认配置 造成原型链污染 参考文章 漏洞背景 EJS维护者对原型链污染的问题有着很好的理解,并使用非常安全的函数清理他们创建的每个对象 利用Re…

爬虫你需要知道的:什么是http请求

1. 什么是http请求 我们将通过发送http请求来获取网页内容。http是HyperText Transfer Protocol的缩写,意思是超文本传输协议,它是一种客户端和服务器之间的请求响应协议。 浏览器就可以看作是一个客户端,当我们在浏览器地址栏输入想访问的…

web第一次作业

题1&#xff1a; <form action"#" method"post"><table><tr><td>用户名&#xff1a;</td><td><input type"text" name"UserName" maxlength"20" size"15"></td>…

“Tab“ 的新型可穿戴人工智能项链

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【Copilot使用】

Copilot是什么 copilot有多火&#xff0c;1月4日&#xff0c;科技巨头微软在官网上宣布将为Windows 11 PC推出Copilot键。 Copilot是微软在Windows 11中加入的AI助手&#xff0c;该AI助手是一个集成了在操作系统中的侧边栏工具&#xff0c;可以帮助用户完成各种任务。 Copilo…

react项目运行卡在编译:您当前运行的TypeScript版本不受@TypeScript eslint/TypeScript estree的官方支持

1.问题 错误信息具体如下&#xff1a; 搜索了一下&#xff0c;是typescript版本的问题&#xff0c;提示我版本需要在3.3.0和4.5.0中间&#xff0c;我查看了package.json&#xff0c;显示版本为4.1.3&#xff0c;然后一直给我提示我的版本是4.9.5&#xff0c;全局搜索一下&…

【深度学习:Foundation Models】基础模型完整指南

【深度学习&#xff1a;Foundation Models】基础模型完整指南 什么是基础模型&#xff1f;基础模型背后的 5 项人工智能原理根据大量数据进行预训练自我监督学习过度拟合微调和快速工程&#xff08;适应性强&#xff09;广义的 基础模型的用例基础模型的类型计算机视觉基础模型…

【图解面试】JS系列 - 如何回答数据类型相关问题(上)

1. JS中的数据类型有哪些&#xff0c;他们的区别是什么&#xff1f; 知识点大纲 语言组织&#xff08;示例&#xff09; 要点&#xff1a;数量 → 种类 → 区别 JS中的数据类型主要有 8 种&#xff0c;分为两大类 基础数据类型 和 引用数据类型 基础数据类型中主要有 Numbe…

wpf的资源路径

1、手动命名空间 xmlns:share"clr-namespace:***;assembly**" 2、资源文件 Pack URI 编译到本地程序集内的资源文件的 pack URI 使用以下授权和路径&#xff1a; 授权&#xff1a;application:///。 路径&#xff1a;资源文件的名称&#xff0c;包括其相对于本地…

【OpenCV学习笔记06】- 制作使用轨迹条控制的调色板

内容 学习将轨迹栏绑定到 OpenCV 窗口。你将学习这些函数&#xff1a;cv.getTrackbarPos(), cv.createTrackbar() 等等。 调色板代码 这里&#xff0c;我们将创建用以显示指定颜色的简单程序。 你有一个显示颜色的窗口和三个轨迹栏&#xff0c;用来指定 B&#xff0c;G&…

研发型企业怎样选择安全便捷的数据摆渡解决方案?

研发型企业在市场经济发展中发挥着至关重要的作用&#xff0c;研发型企业是指以科技创新为核心&#xff0c;以研发新产品、新技术、新工艺为主要业务的企业。这类企业注重技术创新和研发&#xff0c;持续不断地进行技术创新和产品升级&#xff0c;为经济发展注入新鲜的活力。 研…

Vue学习笔记五--路由

1、什么是路由 2、VueRouter 2、1VueRouter介绍 2、2使用步骤 2、3路由封装 3、router-link 3.1两个类名 3.2声明式导航传参 4、路由重定向、404 当找不到路由时&#xff0c;跳转配置到404页面 5、路由模式 6、通过代码跳转路由---编程式导航&传参 路由跳转时传参 跳转方式…

canvas设置线条样式(宽度,端点形态、拐点样式、虚线)

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

学习笔记之——3D Gaussian Splatting源码解读

之前博客对3DGS进行了学习与调研 学习笔记之——3D Gaussian Splatting及其在SLAM与自动驾驶上的应用调研-CSDN博客文章浏览阅读450次。论文主页3D Gaussian Splatting是最近NeRF方面的突破性工作&#xff0c;它的特点在于重建质量高的情况下还能接入传统光栅化&#xff0c;优…

【Python】AttributeError: module ‘torch.nn‘ has no attribute ‘HardSigmoid‘

AttributeError: module ‘torch.nn’ has no attribute ‘HardSigmoid’ 这个错误是因为PyTorch的torch.nn模块中并没有HardSigmoid这个函数。是拼写的大小写问题&#xff0c;换成nn.Hardsigmoid()即可。 如下述代码出错。 import torch import torch.nn as nn hard_sigmoid…

进程、线程、协程的对比、区别和联系,进程之间的通信方式、线程之间的通信方式、协程之间的通信方式

前言 之前的一篇文章曾写过一些关于进程、线程、协程的内容——进程、线程、协程… … ——任务管理器的性能里都有什么&#xff1f;那么多的线程&#xff0c;进程、线程、句柄都是什么&#xff1f; 但对其之间的通信方式还是没有太过详细了解&#xff0c;因此特写此&#xf…

Flink构造宽表实时入库案例介绍

1. 安装包准备 Flink 1.15.4 安装包 Flink cdc的mysql连接器 Flink sql的sdb连接器 MySQL驱动 SDB驱动 Flink jdbc的mysql连接器 2. 入库流程图 3. Flink安装部署 上传Flink压缩包到服务器&#xff0c;并解压 tar -zxvf flink-1.14.5-bin-scala_2.11.tgz -C /opt/ 复…

7个JavaScript面试题全面解析,一文搞定技术面试

JavaScript是构建网络的主要基石之一。这个强大的语言也有自己的怪癖。例如,您知道0 -0计算为true,或者Number("")产生0吗? 问题在于,这些怪癖有时会让你抓耳挠腮,甚至质疑Brendon Eich发明JavaScript的那一天是不是high了。当然,这里的重点不是说JavaScript是一种…

金融帝国实验室(Capitalism Lab)V10版本游戏平衡性优化与改进

即将推出的V10版本中的各种游戏平衡性优化与改进&#xff1a; ————————————— 一、当玩家被提议收购一家即将破产的公司时&#xff0c;显示商业秘密。 当一家公司濒临破产&#xff0c;玩家被提议收购该公司时&#xff0c;如果玩家有兴趣评估该公司&#xff0c;则无…