OpenBmc
一、概念
1.1.简介
-
BMC(Baseboard Manager Controller,简称BMC)
BMC应用了IPMI架构的智能性,是嵌入在计算机(通常是服务器)主板上的专用的微控制器。它是负责管理系统和管理软件与服务器平台硬件之间的一个接口。
根据IPMI规范,BMC需要满足如下条件:
- 具有IMPI命令; 提供BMC访问接口(一般是网口);
- 提供标准化的看门狗定时器接口和看门狗内部事件产生功能;
- 提供可被其他主机组件使用的事件接收功能;
- 提供可通过相应的IPMI必选命令访问的SDR(传感器数据记录)、SEL(系统事件记录)和FRU(现场可替换单元)等功能;
简而言之,BMC就是服务器主板上一块独立的小板卡,有自己独立的处理器,和控制系统,通过IPMB、LPC(low-pin-count-interface)、SMBus等接口与主机硬件或者主机系统进行通信,并通过网络、串行/Moderm、PCI等接口传向本地主机/远程服务器提供查询和控制等功能。
-
IPMI简介
可以说IPMI目前是BMC的核心,BMC的远程控制都是通过ipmi协议实现。IPMI的全称是Intelligent Platform Management Interface,智能平台管理接口。IPMI规定了很多的东西,BMC是其中最重要的一个部分,此外还有一些”模块“控制器通过IPMB与BMC相连,这些”模块“控制器一般控制特定的设备,有些支持热插拔。IPMI是一个标准和规范,而IMPI接口是实现这一规范的具体接口之一。
IMPI接口基于命令/响应机制,可通过网络将机箱、传感器、固件、存储、应用等主机组件的信息进行分类传递,通过软件ID对BIOS、系统管理软件、远程终端等传感器等进行分类管理,在网络、串行/Moderm接口、IPMB(I2C)、KCS、SMIC、SMBus等不同接口上传递都使用统一的格式。
IPMB全称Intelligent Platform Management Bus,是一种基于I2C的串行总线,它用于BMC与模块(主板上的子卡)控制器的通信,其上传递的是IPMI命令。
-
OpenBMC
OpenBMC是一个开源的基于Linux的固件项目,用于管理和控制服务器硬件的底层管理系统。BMC的全称是Baseboard Management Controller,它是嵌入在服务器主板上的一个独立的处理器,负责监控和管理服务器的硬件。
OpenBMC项目的目标是提供一个开放的、可定制的BMC固件解决方案,以便服务器制造商和开发人员能够自定义和扩展BMC的功能。它采用了开源的技术和标准,如Linux操作系统、IPMI(Intelligent Platform Management Interface)和Redfish等,以提供灵活、可扩展和可管理的服务器管理解决方案。
1.2.OpenBmc软件架构
BMC硬件本身就是一个计算机系统。与常用的计算机系统相比,BMC中的硬件资源非常有限。BMC硬件中CPU运行速度较慢,闪存一般在32 MB,RAM一般少于256 MB。因此,OpenBMC被设计为完整的Linux发行版,可以灵活地定制以支持不同的BMC SoC或板卡。
OpenBMC映像包括一个引导程序(u-boot),一个Linux内核,开源软件包和特定于主板的软件包。
-
引导加载程序和Linux内核都包括BMC SoC的各种硬件驱动程序,包括i2c驱动程序,USB驱动程序,LPC驱动、PWM驱动程序和SPI驱动程序。
-
开源软件包一般包括常用应用程序,例如BusyBox,i2c工具,lm传感器,OpenSSH和Python等。
-
用户板的软件包包括用于特定板的初始化脚本和工具。例如,它包括一个用于从EEPROM转储资产信息的工具和一个风扇控制器守护程序,用于根据环境读数控制风扇速度。
OpenBMC中,共有三组层:
- 通用层包括可用于不同板卡和BMC SoC的软件包。如meta-openembedded、meta-security等。
- SoC层包括特定于BMC SoC的软件包,例如Aspeed对AST2300 / AST2400 SoC 基础包,引导加载程序和内核都在SoC层中定义。如meta-aspeed、meta-raspberrypi、meta-xilinx等。
- 板层包括用于不同板的封装。应用于特定Wedge的硬件配置的初始化脚本和工具,如meta-facebook、meta-ibm等。
1.3.OpenBmc特点
OpenBMC
使用 Yocto
项目作为底层构建和分发生成框架。固件本身基于 U-Boot
。OpenBMC
使用 D-Bus
作为进程间通信(IPC
)。OpenBMC
包含一个用于与固件堆栈交互的 Web
应用程序。OpenBMC
添加了 Redfish
对硬件管理的支持。
OpenBMC的主要特点和功能包括:
-
远程管理:OpenBMC提供了通过网络远程管理服务器的能力。管理员可以通过Web界面或命令行界面远程监控服务器的状态、进行配置和控制。
-
硬件监控:OpenBMC可以监控服务器的各种硬件组件,如温度、风扇转速、电压和电流等。它可以提供实时的硬件信息和警报,帮助管理员发现和解决问题。
-
远程控制:OpenBMC支持通过网络远程控制服务器的电源、重启和BIOS设置等操作。管理员可以在服务器出现故障或需要远程维护时进行远程控制。
-
扩展性和定制性:OpenBMC项目的开源性质使得用户能够根据自己的需求进行定制和扩展。用户可以根据需要添加自定义功能或集成其他开源工具和解决方案。
1.4.Yocto项目
-
简介:
Yocto项目是一个由Linux基金会赞助的开源协作项目,它提供了工具和流程来帮助创建Linux发行版的嵌入式和物联网软件,这些软件与嵌入式硬件的底层架构无关。Yocto项目允许开发人员创建基于Linux的定制系统,这些系统专为嵌入式产品而设计,不区分硬件体系架构。它提供了灵活的工具集和开发环境,允许全球的嵌入式设备开发人员通过共享技术、软件堆栈、配置和最佳实践来创建这些定制的Linux映像。
-
主要特点:
- 广泛应用于整个行业:Yocto项目被全球数以千计的开发人员用于系统和应用程序开发、存档和管理以及用于速度、占用空间和内存利用率的定制。
- 架构无关:Yocto项目支持多种硬件架构,包括x86(32位和64位)、ARM(32位和64位)、RISC-V、PPC和MIPS等。
- 镜像和代码移植容易:Yocto项目允许针对多个硬件平台进行软件定制和构建交换。
- 灵活:Yocto项目提供了灵活的工具集和开发环境,允许开发者根据自己的需求定制Linux发行版。
- 适用于资源受限的嵌入式和物联网设备:Yocto项目支持为资源受限的设备创建定制系统。
- 全面的工具链支持:Yocto项目可以生成用于交叉编译的工具链和针对其自己的发行版量身定做的软件开发工具包(SDK)。
- 执行机制大于策略:Yocto项目关注机制而不是策略,确保可以根据设计需求自由设置策略。
- 层模型:Yocto项目使用层模型来组织相关功能,这样可以将不同硬件平台的特定配置和软件隔离在不同的层中,从而减少项目复杂性和冗余。
- 支持部分组件构建:Yocto项目通过其共享状态缓存(sstate)方案实现单独构建和重建单个程序包。
- 板级支持包(BSP):Yocto项目允许通过添加BSP层来支持额外的硬件设备。BSP是为特定硬件平台提供支持的软件包,它包含了硬件平台所需的配置和驱动程序。通过为不同的硬件平台创建和添加BSP,Yocto项目可以扩展其对新硬件的支持。
Yocto项目的核心是BitBake,这是一个高效的任务调度器和执行系统,能够处理复杂的依赖关系,并优化构建过程。通过Yocto项目,开发者可以确保他们的定制Linux系统在不同硬件平台上具有高度的兼容性和可移植性。
-
如何添加BSP(板级支持包)
- 设置构建环境:确保你的宿主开发系统已经设置好,可以使用BitBake进行构建。
- 克隆poky仓库:你需要有Yocto项目源代码的本地副本,即本地poky仓库。
- 确定BSP层:Yocto项目支持许多BSP,这些BSP在它们自己的层中维护,或者在设计为包含几个BSP的层中维护。
- 创建新的BSP层:你可以使用
bitbake-layers
脚本来创建一个新的BSP层。这个脚本允许你交互式地配置许多BSP相关的内容(例如键盘、触摸屏等)。 - 配置新的BSP层:在BSP层中,你需要编辑
conf
目录和几个recipes-*
目录中的文件。这些配置更改包括标识新层在本地系统上的位置以及你将使用的内核。 - 修改BSP层的Recipe:这包括修改recipe文件(
*.bb
文件),移除不使用的recipe,以及添加新的recipe或append文件(.bbappend
)来支持你的硬件。 - 准备构建:在你对BSP层做出所有更改后,还需要做一些准备工作,以使OpenEmbedded构建系统能够创建你的映像。你需要通过source一个环境设置脚本(例如
oe-init-build-env
)来准备构建环境,并且确保两个关键配置文件适当配置:conf/local.conf
和conf/bblayers.conf
文件。你必须让OpenEmbedded构建系统知道你的新层。 - 将BSP层添加到BBLAYERS变量:在你的构建目录下的
conf/bblayers.conf
文件中,添加你的BSP层路径到BBLAYERS
变量中,这样构建系统才能识别并使用你的BSP层。 - 构建映像:使用BitBake工具和OpenEmbedded构建系统来构建你的映像。
- 管理内核补丁和配置项:如果你使用
yocto-bsp
创建了Yocto BSP层,并将其添加到了BBLAYERS
,你可以使用yocto-kernel
命令来添加补丁和配置项到BSP的内核。
1.5.OpenEmbedded
OpenEmbedded是一个用于构建定制Linux发行版的开源项目,它特别适用于嵌入式系统。它提供了一套完整的工具和方法,允许开发者创建针对特定硬件平台优化的Linux系统。以下是OpenEmbedded构建系统的主要特点和组成部分:
- BitBake:OpenEmbedded的核心是一个名为BitBake的构建工具。它是一个基于任务的构建工具,用于处理软件包的构建、安装和打包。BitBake使用一个名为recipe的配方文件来描述如何构建软件包。
- Recipes:在OpenEmbedded中,软件包的构建过程由recipe文件定义。这些文件包含了构建软件包所需的所有信息,包括源代码的位置、构建依赖、编译选项等。
- Layers:OpenEmbedded使用层(layers)的概念来组织recipes和相关配置。层可以包含recipes、配置文件、补丁等。开发者可以创建自己的层来添加新的recipes或修改现有层中的recipes。
- 配置文件:OpenEmbedded使用配置文件来定义构建过程中的各种选项,如目标架构、构建选项、包管理器等。这些配置文件通常位于构建目录的
conf
目录下。 - 任务(Tasks):BitBake通过任务来执行构建过程中的各个步骤。任务可以是编译源代码、安装软件包、生成图像等。
- 共享状态缓存(SState):为了提高构建效率,OpenEmbedded使用共享状态缓存来存储已经构建的软件包的状态。这样,在后续的构建过程中,如果软件包没有变化,就可以直接使用缓存中的状态,而不需要重新构建。
- 可扩展性:OpenEmbedded允许开发者通过添加新的层或修改现有的recipes来扩展构建系统,以支持新的硬件平台或软件包。
- 跨平台:OpenEmbedded可以在多种操作系统上运行,包括Linux、macOS和Windows。
- 社区支持:OpenEmbedded有一个活跃的社区,提供了大量的文档、教程和支持,帮助开发者解决构建过程中遇到的问题。
OpenEmbedded构建系统广泛应用于嵌入式Linux开发领域,特别是在需要高度定制和优化的系统中。Yocto项目就是基于OpenEmbedded构建系统的一个广泛使用的项目,它提供了额外的工具和流程来简化嵌入式Linux系统的创建过程。
1.6.OpenEmbedded和Yocto的关系
Yocto项目是一个开源项目,它提供工具和流程来帮助创建基于Linux的定制系统,这些系统专为嵌入式产品而设计,不区分硬件体系架构。Yocto项目起源于OpenEmbedded项目,并与之协作,可以看作是OpenEmbedded项目的一个扩展和优化,专注于构建系统本身和针对交叉开发的工具化。
OpenEmbedded是一个更为广泛的项目,它维护了一个构建工具BitBake和一个元数据层,这些元数据层详细描述了构建一个Linux发行版所需要的包及构建过程。OpenEmbedded聚焦在尖端技术、菜谱和一大套针对不同硬件平台的板支持包(BSPs)。
Yocto项目和OpenEmbedded共享一个核心元数据集合,称为OpenEmbedded-Core。Yocto项目专注于为一组核心架构和特定单板提供功能强大、易于使用、可互操作、经过良好测试的工具、元数据和BSPs。
OpenBMC使用Yocto项目作为底层构建和分发生成框架。这意味着OpenBMC项目利用Yocto项目提供的工具和流程来构建和生成其固件。固件本身基于U-Boot,OpenBMC使用D-Bus作为进程间通信(IPC),并且包含一个用于与固件堆栈交互的Web应用程序。此外,OpenBMC添加了对Redfish硬件管理的支持。
总结来说,Yocto项目是构建嵌入式Linux系统的强大工具,它与OpenEmbedded项目紧密相关,但提供了更专注于构建系统和交叉开发工具的框架。OpenBMC通过使用Yocto项目来管理配置以及创建BMC(底板管理控制器)镜像,从而简化了其开发流程。
二、示例平台构建(参考Imagine Miracle博主的文章)
2.1.安装依赖
-
下载bitbake源码
git clone https://github.com/openembedded/bitbake.git #下载到本地后进入bin目录其中有bitbake的二进制可以直接使用,将其添加到环境变量
-
安装依赖
sudo apt install git python3-distutils gcc g++ make file wget \ gawk diffstat bzip2 cpio chrpath zstd lz4 bzip2
2.2.下载源码
-
由于国内网络问题,这边直接用大V打包整理好的,总共13个文件
https://github.com/ImagineMiracle-wxn/OpenBMC/releases/tag/Demo-Romulus
-
这些是拆分后的压缩包文件,需要合并在一起才可以解压
$ cat openbmc-im.tar.gz.* > openbmc-im.tar.gz $ tar -zxvf openbmc-im.tar.gz $ cd openbmc-im/build/romulus/conf $ vim bblayers.conf
-
修改
openbmc-im/build/romulus/conf/bblayers.conf
文件中的项目所在路径,修改为当前项目所在的绝对路径
2.3.构建
-
设置目标硬件平台
#回到起始目录 cd ../../../ #romulus 模拟的是 AST2500 平台 . setup romulus
2.4.编译
-
编译生成镜像
#不可用root用户进行编译 #修改整个openbmc目录权限为777,使用普通用户进行编译 sudo chmod -R 777 /path/to/directory bitbake obmc-phosphor-image #编译完成后的目标目录在 build 下所对应的平台目录 #其所生成的系统镜像以及其它平台相关文件会保存在上述目录的 tmp/deploy/images/romulus #我们下面将要使用到的文件就是所生成的系统镜像文件 obmc-phosphor-image-romulus.static.mtd
2.5.启动系统
-
登录到
BMC
系统,启动BMC
系统,使用映射本地端口方式启动sudo qemu-system-arm -m 256 -M romulus-bmc -nographic -drive file=./tmp/deploy/images/romulus/obmc-phosphor-image-romulus.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=:127.0.0.1:2222-:22,hostfwd=:127.0.0.1:2443-:443,hostname=qemu
-m
指定了内存的大小;-M
指定机器架构;-nographic
表示无图像输出,串口会输出的控制台;-driver file=xx
指定了启动的系统,这里就是我们的openbmc
固件系统;-net
设定网络参数
-
如果说上一步
bitbake obmc-phosphor-image
并没有通过的话,那么也可以下载官方编译好的镜像wget https://jenkins.openbmc.org/job/latest-master/label=docker-builder,target=romulus/lastSuccessfulBuild/artifact/openbmc/build/tmp/deploy/images/romulus/obmc-phosphor-image-romulus.static.mtd #然后执行如下命令,启动 BMC 系统 sudo qemu-system-arm -m 256 -M romulus-bmc -nographic -drive file=./obmc-phosphor-image-romulus.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=:127.0.0.1:2222-:22,hostfwd=:127.0.0.1:2443-:443,hostname=qemu
-
用户为:
root
,密码:0penBmc
2.6.访问WebUI
-
在浏览器导航栏中输入
https://localhost:2443/ #这里的用户名和密码同样分别是 root,0penBmc
2.7.安装SDK
三、启动过程
3.1.OpenBMC启动有哪几个阶段
- Boot 阶段
- Uboot boot
- Kernel boot
- Run Time 阶段
- IPMI & REST API etc service
3.2.OpenBMC启动过程
-
Bootloader:
与大多数嵌入式Linux系统一样,OpenBMC启动的第一步是引导加载程序(Bootloader)。通常,这个Bootloader是U-Boot,它负责初始化硬件(如内存控制器)CPU初始化、它初始化最小的硬件环境,设置内存,加载OpenBMC Linux内核和初始根文件系统到内存中设置网络参数和加载操作系统内核到内存中。 -
内核加载启动:
一旦Bootloader加载并执行了Linux内核,内核将接管并继续系统的引导过程。内核初始化硬件设备、挂载根文件系统并开始运行第一个用户空间程序(通常是init)。 -
init系统:
在OpenBMC中,init系统通常是systemd或者SysVinit - BusyBox的init。这个init系统将负责启动其他用户空间的服务和守护进程。例如,它可以运行网络服务、SSH服务器、传感器监控服务等。AMI 的legacy BMC使用System V init (SysVinit)系统。目前OpenBMC使用最流行的systemd 来作为init系统,它使用 unit 文件来定义服务、挂载点、套接字等,并提供了强大的依赖性管理和并发服务启动,大大加速了启动过程。systemd 的配置文件一般位于 /etc/systemd/system/ 目录和 /lib/systemd/system/ 目录中。
无论SysVinit 或者systemd系统,其核心职责都是初始化和管理用户空间环境,从而为OpenBMC系统上的多用户操作提供基础。 -
系统服务:
随着系统的继续启动,各种服务和守护进程被启动。这些可能包括:
网络:配置IP地址、启动网络接口等。
SSH:启动SSH服务,以允许远程访问。
Web服务器:提供一个Web界面来远程管理BMC。
传感器和监控:启动监控服务器硬件健康状况的服务,比如风扇转速、温度传感器和电压传感器。 -
D-Bus接口:
OpenBMC使用D-Bus作为不同系统组件之间的通信机制。一旦D-Bus守护进程(dbus-daemon)启动,其他服务就可以通过D-Bus接口通信,执行如硬件监控、日志记录和IPMI命令处理等任务。 -
IPMI和REST API:
为了与外部系统通信,OpenBMC提供了基于IPMI的接口以及一个RESTful API。IPMI守护进程和REST服务器在系统启动时被初始化,允许管理员通过这些接口来管理和监控硬件。
在整个启动过程中,OpenBMC利用其模块化的设计,使得各个组件可以独立地启动和运行,同时也便于维护和扩展。每个阶段的具体内容可能会根据OpenBMC项目的不同版本和不同硬件平台略有差异。
四、目录结构及文档语法分析
4.1.目录
以OpenBMC的meta-aspeed为例:
- classes:包含OpenEmbedded构建系统中使用的类(class)定义,这些类定义了如何构建和安装软件包。
- common:包含通用的配置文件或脚本,这些文件或脚本在多个地方被使用。
- conf:包含构建系统的配置文件,如
layer.conf
,定义了层的名称、优先级等信息。 - Documentation:包含项目的文档,如用户指南、开发指南等。
- experimental:包含实验性的特性或功能,这些可能还在开发中或尚未稳定。
- meta-*:这些子目录是OpenEmbedded层,每个层都包含特定于该层的食谱(recipes)和配置。
- test2:可能包含测试相关的代码或脚本。
- tools:可能包含构建或开发过程中使用的工具。
- yocto:可能包含与Yocto项目相关的特定配置或脚本。
4.2..bbclass
-
简介
以
.bbclass
为后缀的文件是类(class)文件,它们定义了可重用的逻辑和功能,可以在多个食谱(recipe)中继承和使用。类文件允许开发者封装构建过程中的特定步骤或功能,以便于在不同的食谱之间共享。 -
常见变量
-
FILES:定义软件包中包含的文件列表。
-
EXPORT_FUNCTIONS:用于导出在类中定义的函数,使得这些函数可以在继承这个类的食谱中被调用。
-
inherit:用于继承其他类文件(
.bbclass
)中定义的函数和变量,允许构建逻辑的重用和扩展。 -
do_():定义特定任务的函数,如
do_compile()
、do_install()
等,这些函数在构建过程中的特定阶段被调用。 -
S:定义源代码的基目录,通常在
.bbclass
文件中设置,以便于在任务函数中使用。 -
BBCLASSEXTEND:允许类在不同的构建环境中使用,如原生(native)或原生SDK(nativesdk)。
-
PARALLEL_MAKE:定义并行构建时的线程数。
-
DL_DIR:指定下载的源代码包存储的目录。
-
TMPDIR:定义构建过程中使用的临时目录。
-
PACKAGE_CLASSES:指定用于生成不同程序包类型的类。
-
PACKAGE_ARCH:定义特定于体系结构的软件包。
-
FILESPATH:定义本地文件的默认目录集。
-
BB_NUMBER_THREADS:定义BitBake使用的线程数。
-
EXTRA_OECONF:传递额外的参数给配置脚本,如autoconf。
-
EXTRA_OEMAKE:传递额外的参数给make命令。
-
-
语法
- 变量定义:使用
VAR ?= value
或VAR = value
来定义变量。问号表示如果变量在其他地方没有定义,则使用这里的值。 - 函数定义:使用
function_name() { ... }
来定义函数。 - 继承:使用
inherit class_name
来继承其他类。 - 导出函数:使用
EXPORT_FUNCTIONS function_name
来导出函数,使得继承这个类的食谱可以调用这些函数。 - 文件关联:使用
FILES:variable += "path"
来关联文件和包。
- 变量定义:使用
-
示例
# A class to install extra Linux kernel header files //继承 inherit kernel_extra_headers_base # User of this class can put header files in LINUX_EXTRA_HEADERS variable. # The do_install() function below will install the extra header files # automatically. # Users can also define their own do_install() to install to # "${D}${LINUX_EXTRA_HEADER_BASE}" //变量定义,如果这个变量在继承的类或食谱中没有被定义,那么这里的定义才会被使用 LINUX_EXTRA_HEADERS ?= "" //函数定义 kernel_extra_headers_do_install() { //定义安装目录 incdir="${D}${LINUX_EXTRA_HEADER_BASE}" //安装 install -d $incdir //遍历LINUX_EXTRA_HEADERS变量中指定的所有文件,并将它们安装到指定的目录 for file in ${LINUX_EXTRA_HEADERS}; do install -D -m 0644 $file ${incdir}/$file done } //导出函数,使得继承这个类的食谱可以调用这些函数 EXPORT_FUNCTIONS do_install //这行代码将额外的头文件目录与特定的包(${PN}-dev)关联起来。${PN}是食谱中定义的包名的变量 FILES:${PN}-dev += "${LINUX_EXTRA_HEADER_BASE}"
注:定义的函数和导出的函数名不同,定义的函数通常会包含类名或功能描述作为前缀,导出函数时,使用的是函数的核心名称。其工作流程是:
- 食谱继承:食谱通过
inherit
指令继承一个或多个类 - 函数调用:食谱可以直接调用继承的类中导出的函数
- BitBake解析:BitBake在构建过程中解析食谱,识别继承的类和导出的函数,并执行相应的函数
- 食谱继承:食谱通过
4.3..inc
-
简介
.inc
文件通常用作包含文件,它们可以被食谱文件(.bb
)或其他.inc
文件包含,以共享变量定义、函数或类。这种机制允许开发者避免代码重复,并保持构建系统的组织性和可维护性。 -
常见变量
-
ROOTFS_POSTPROCESS_COMMAND:用于在根文件系统创建后执行的后处理命令。可以指定一系列Shell命令,以优化文件大小、创建清单文件等。例如,
ROOTFS_POSTPROCESS_COMMAND += "<shell_command>; ..."
用于添加后处理命令。 -
IMAGE_INSTALL:指定在构建的镜像中需要安装的软件包列表。
-
IMAGE_FEATURES:定义镜像中包含的特性,如"x11"、"wayland"等。
-
IMAGE_PREPROCESS_COMMAND:在镜像生成之前执行的预处理命令。
-
IMAGE_POSTPROCESS_COMMAND:在镜像生成之后执行的后处理命令。
-
IMAGE_ROOTFS_EXTRA_SPACE:为根文件系统额外保留的空间大小。
-
INHIBIT_PACKAGE_STRIP:如果设置为"1",则在构建过程中不会剥离二进制文件。
-
BB_NUMBER_THREADS:定义BitBake使用的线程数。
-
DL_DIR:指定下载的源代码包存储的目录。
-
TMPDIR:定义构建过程中使用的临时目录。
-
PACKAGE_CLASSES:指定用于生成不同程序包类型的类。
-
PACKAGE_ARCH:定义特定于体系结构的软件包。
-
FILESPATH:定义本地文件的默认目录集。
-
FILESEXTRAPATHS:在解析食谱文件时,用于添加额外的文件路径。
-
SSTATE_DIR:定义共享状态缓存的目录,用于存储构建过程中的中间结果。
-
-
语法
-
变量赋值:
VARIABLE = "value"
直接为变量设置值。如果需要在值中包含空格,可以使用引号。
-
条件赋值:
VARIABLE ?= "value"
如果变量之前没有被赋值,则设置这个值。
-
追加赋值:
VARIABLE += "value"
在变量现有值的末尾追加新值。
-
覆盖赋值:
VARIABLE:append = "value" VARIABLE:prepend = "value"
在变量值的末尾或开头追加内容。
-
删除赋值:
VARIABLE:remove = "value"
从变量值中移除指定内容。
-
函数定义:
function_name() { # 函数体 }
使用
function
关键字定义一个函数,函数体中的命令使用Shell脚本语法。 -
条件语句:
if [ "condition" ]; then # 如果条件为真执行的代码 else # 如果条件为假执行的代码 fi
使用
if
语句进行条件判断。 -
循环语句:
for variable in list; do # 循环体 done
使用
for
循环遍历列表中的元素。 -
包含其他文件:
include filename.inc
使用
include
关键字包含其他.inc
文件。 -
导出函数:
EXPORT_FUNCTIONS function_name
使用
EXPORT_FUNCTIONS
关键字导出函数,使得继承这个类的食谱可以调用这个函数。 -
文件操作:
echo "content" > file_path
使用
echo
命令将内容写入文件。 -
查找和删除文件:
find directory_path -type f -name "*.pyc" -exec rm -f {} \;
使用
find
命令查找并执行删除操作。
-
-
示例
//这行代码将openbmc_rootfs_fixup函数添加到ROOTFS_POSTPROCESS_COMMAND变量中。 //这个变量是一个列表,用于在根文件系统构建完成后执行的命令序列。+=操作符用于向列表中追加元素 ROOTFS_POSTPROCESS_COMMAND += "openbmc_rootfs_fixup;" //这行代码为OPENBMC_HOSTNAME变量提供了一个默认值"bmc"。 //如果这个变量在食谱或配置文件中没有被定义,那么它将使用这里的默认值 OPENBMC_HOSTNAME ?= "bmc" //这是一个名为openbmc_rootfs_fixup的函数定义。 //在OpenEmbedded中,函数通常用于执行特定的构建任务或处理步骤。 openbmc_rootfs_fixup() { # hostname if [ "${OPENBMC_HOSTNAME}" != "" ]; then //这行代码将OPENBMC_HOSTNAME变量的值写入到根文件系统的/etc/hostname文件中。这是设置系统主机名的一种方法。 echo ${OPENBMC_HOSTNAME} > ${IMAGE_ROOTFS}/etc/hostname else echo ${MACHINE} > ${IMAGE_ROOTFS}/etc/hostname fi # version echo "OpenBMC Release ${OPENBMC_VERSION}" > ${IMAGE_ROOTFS}/etc/issue //>>在文件中追加一个空行 echo >> ${IMAGE_ROOTFS}/etc/issue //这行代码将包含主机名的版本信息写入/etc/issue.net文件,这个文件通常在SSH登录时显示。 echo "OpenBMC Release ${OPENBMC_VERSION} %h" > ${IMAGE_ROOTFS}/etc/issue.net echo >> ${IMAGE_ROOTFS}/etc/issue.net # Remove all *.pyc files find ${IMAGE_ROOTFS} -type f -name "*.pyc" -exec rm -f {} \; }
4.4..conf
-
简介
.conf
文件用于定义构建系统的配置选项。这些文件通常位于各个层的conf
目录中,并且可以被食谱(.bb
文件)、类(.bbclass
文件)或包含文件(.inc
文件)引用。 -
常见变量
- LAYER:定义当前层的名称。
- LAYERVERSION:定义层的版本号。
- LAYERDEPENDS:定义当前层所依赖的其他层。
- BBPATH:定义BitBake搜索食谱文件(
.bb
)的路径。 - BBFILES:定义BitBake在构建过程中需要处理的食谱文件列表。
- BBFILE_COLLECTIONS:定义食谱文件集合,用于组织和分类食谱。
- BBFILE_PATTERN_:为特定的食谱文件集合定义搜索模式。
- BBFILE_PRIORITY_:为特定的食谱文件集合定义优先级。
- LAYERSERIES_COMPAT:定义层与哪些Yocto项目系列兼容。
- INHERIT:定义层继承的类,这些类可以提供额外的构建逻辑。
- MACHINE:定义目标硬件平台。
- MACHINEOVERRIDES:定义机器配置的覆盖规则。
- IMAGE_FEATURES:定义要在构建的镜像中包含的特性。
- IMAGE_INSTALL:定义要安装到镜像的额外软件包。
- IMAGE_ROOTFS_SIZE:定义根文件系统的大小。
- IMAGE_PKGTYPE:定义镜像包的类型,如 RPM 或 DEB。
- DistroFeatures:定义发行版的特性,如 “x11”、“wayland” 等。
- TargetPackageArch:定义目标软件包的架构。
- TargetSDKPackageArch:定义目标SDK软件包的架构。
- PackageArchExclusions:定义应从构建过程中排除的软件包架构。
- AdditionalImageFeatures:定义额外的镜像特性,这些特性可能在特定层中提供。
- AdditionalImageSources:定义额外的镜像源,这些源可能在特定层中提供。
- PARALLEL_MAKE:定义并行构建时的线程数。
- PACKAGECONFIG:定义软件包的可选配置选项。
- EXTRA_OEMAKE:定义传递给
oe_runmake
的额外参数。 - SSTATEDIR:定义共享状态缓存的目录,用于存储构建过程中的中间结果。
- BB_NUMBER_THREADS:定义BitBake使用的线程数。
- BBINCLUDELOGS:控制是否在构建日志中包含包含文件的日志。
-
语法
-
变量赋值:
VARIABLE = "value"
为变量设置值。如果值中包含空格,需要使用引号。
-
条件赋值:
VARIABLE ?= "value"
如果变量之前没有被赋值,则设置这个值。
-
追加赋值:
VARIABLE += "value"
在变量现有值的末尾追加新值。
-
覆盖赋值:
VARIABLE:append = "value" VARIABLE:prepend = "value"
在变量值的末尾或开头追加内容。
-
删除赋值:
VARIABLE:remove = "value"
从变量值中移除指定内容。
-
包含其他配置文件:
include another.conf
使用
include
指令包含其他.conf
文件,这允许将配置分散到多个文件中。 -
层配置:
LAYERVERSION = "1" LAYERNAME = "My Layer" LAYERDEPENDS = "base-layer"
这些是层特有的变量,用于定义层的版本、名称和依赖的其他层。
-
机器配置:
MACHINE = "mymachine" MACHINEOVERRIDES = "mymachine:myvariant"
用于定义目标机器的名称和变体。
变体
(variant)是指在特定机器配置(MACHINE配置)的基础上,为特定的硬件或软件配置提供额外的定制化选项。变体允许开发者在不改变基础机器配置的情况下,通过添加或修改特定的功能来创建不同的构建配置。例如,一个基础的机器配置可能支持一个系列的硬件,而变体则可以用于为该系列中的特定硬件提供额外的驱动程序或配置选项。 -
编译选项:
PARALLEL_MAKE = "-j4"
设置编译时的并行任务数。
-
包管理器配置:
PACKAGE_MANAGER = "rpm"
指定使用的包管理器。
-
镜像配置:
MIRRORS = "http://example.com/mirror"
设置软件包源的镜像地址。
-
调试和日志配置:
BB_NUMBER_THREADS = "1" BB_PARSE_LOGLEVEL = "2"
设置并行构建的线程数和解析日志的详细程度。
BitBake和OpenEmbedded构建系统通常使用以下日志级别:
- ERROR:错误信息,指示构建过程中出现的错误。
- WARNING:警告信息,指出可能的问题或需要注意的情况。
- INFO:一般信息,提供构建过程中的常规信息。
- DEBUG:调试信息,提供更详细的构建过程信息,用于问题诊断。
- Parishable:可解析的日志信息,用于自动化解析构建日志。
- EVENT:事件信息,记录构建过程中的关键事件。
- CRITICAL:临界信息,指示严重的问题,可能导致构建失败。
- DEBUG:更详细的调试信息,用于深入分析问题。
-
-
示例
# We have a conf and classes directory, add to BBPATH //这行代码将当前层的目录(LAYERDIR)追加到BBPATH环境变量中。 //BBPATH是BitBake用来搜索食谱文件(.bb)和其他构建脚本的路径。 BBPATH .= ":${LAYERDIR}" # We have common/recipes-* directories, add to BBFILES //这行代码将当前层中`common`目录下的食谱文件和`.bbappend`文件添加到`BBFILES`变量中。 //`BBFILES`是一个包含所有食谱文件路径的列表,BitBake会根据这个列表来处理食谱。 BBFILES += "\ ${LAYERDIR}/common/recipes-*/*/*.bb \ ${LAYERDIR}/common/recipes-*/*/*.bbappend \ " # Facebook internal common recipes # NOTICE: # order is matter bitbake apply bbappend in order # listed here, so keep internal recipes in last # to make sure it is applied last BBFILES += "\ ${LAYERDIR}/common/facebook/recipes-*/*/*.bb \ ${LAYERDIR}/common/facebook/recipes-*/*/*.bbappend \ " # Any proprietary code. BBFILES += "\ ${LAYERDIR}/proprietary/*/*/*.bb \ ${LAYERDIR}/proprietary/*/*/*.bbappend \ " //这两行代码定义了一个新的食谱集合openbmc,并为这个集合指定了一个模式BBFILE_PATTERN_openbmc,用于匹配层目录下特定路径的食谱文件。 BBFILE_COLLECTIONS += "openbmc" BBFILE_PATTERN_openbmc = "^${LAYERDIR_RE}/(common/(recipes|facebook)|proprietary)" //这行代码为openbmc集合设置了一个优先级。通常,优先级值越低,表示该层的优先级越高。有多个食谱定义了相同的软件包,优先级较高的食谱将被使用。 BBFILE_PRIORITY_openbmc = "6" //这行代码定义了层与哪些Yocto项目系列兼容。这里列出的都是Yocto项目的版本代号,表示这个层可以在这些版本的Yocto项目中使用。 LAYERSERIES_COMPAT_openbmc = "scarthgap nanbield kirkstone dunfell rocko" //这行代码将local-source类添加到层的继承列表中。这意味着这个层将使用local-source类中定义的构建逻辑。 //local-source类通常用于允许开发者在本地开发环境中使用源代码,而不是从远程仓库下载。 INHERIT += "local-source"
4.5..bb
-
简介
.bb
文件是OpenEmbedded构建系统的核心,它们定义了如何获取源代码、如何应用补丁、如何配置、编译和安装软件包。通过这些语法元素,开发者可以精确地控制软件包的构建过程。 -
常见变量
- HOMEPAGE:定义了项目的主页 URL。
- SECTION:定义了软件包在软件仓库中的分类。
- DEPENDS:定义了构建过程中需要的依赖项。
DEPENDS
可以包含多个依赖,用空格分隔。 - LICENSE:定义了项目的许可证类型。
- LIC_FILES_CHKSUM:定义了许可证文件的校验和,用于验证许可证文件的完整性。
- PE:定义了软件包的优先级(Priority)。在 OpenEmbedded 中,这个变量用于指定软件包的优先级,数值越小,优先级越高。
- PV:定义了软件包的版本号(Package Version)。版本号可以包含标签,如
v2019.01+git${SRCPV}
,其中git${SRCPV}
可能表示从源代码仓库中获取的额外版本信息。 - DEFAULT_PREFERENCE:定义了软件包的默认优先级。在没有明确指定优先级的情况下,这个值决定了软件包的默认优先级。
- SRCBRANCH:定义了从源代码仓库中获取代码时使用的分支名称。
- SRCREV:定义了从源代码仓库中获取的特定修订版本。
AUTOINC
表示自动递增修订版本。 - SRC_URI:定义了源代码的获取方式,可以是本地文件、远程仓库或其他协议。
- S:定义了构建目录,即源代码被放置和构建的地方。
- include:用于包含其他
.inc
文件,这些文件可以定义额外的变量、函数或类。 - EXTRA_OEMAKE:定义了传递给
oe_runmake
的额外参数,用于自定义编译过程。 - SUMMARY:提供了软件包的简短描述。
- PROVIDES:定义了软件包提供的组件,这些组件可以被其他软件包作为依赖项使用。
- PACKAGES:定义了构建过程中生成的软件包名称。
- RPROVIDES、RREPLACES 和 RCONFLICTS:定义了软件包的运行时提供、替换和冲突关系,用于解决依赖问题。
- do_compile 和 do_install:定义了构建和安装阶段的自定义命令。
- ALLOW_EMPTY:允许软件包在没有内容的情况下构建。
- FILES:定义了软件包中包含的文件。
- RDEPENDS:定义了软件包的运行时依赖。
- BBCLASSEXTEND:允许食谱在不同的构建环境中使用,如原生(native)或原生SDK(nativesdk)。
-
语法
-
文件头部:
SUMMARY = "A brief description of the package" LICENSE = "License type"
-
继承:
inherit baseclass
食谱可以继承类文件(
.bbclass
)中定义的函数和变量。 -
变量定义:
VARIABLE = "value"
为变量设置值。如果值中包含空格,需要使用引号。
-
条件赋值:
VARIABLE ?= "value"
如果变量之前没有被赋值,则设置这个值。
-
追加赋值:
#字符串追加 VARIABLE += "value" #变量追加 VARIABLE += "${ANOTHER_VARIABLE}" #多值追加 VARIABLE += "value1" "value2" "value3"
在变量现有值的末尾追加新值。
-
覆盖赋值:
VARIABLE:append = "value" VARIABLE:prepend = "value"
在变量值的末尾或开头追加内容。
-
删除赋值:
VARIABLE:remove = "value"
从变量值中移除指定内容。
-
依赖关系:
RDEPENDS_${PN} = "dependency1 dependency2" RRECOMMENDS_${PN} = "recommendation1"
定义软件包的运行时依赖和推荐依赖。
-
源代码信息:
SRC_URI = "file://local-source.tar.gz" SRCREV = "git commit hash or branch"
指定源代码的位置和版本。
-
补丁:
SRC_URI += "file://patch1.patch"
指定要应用到源代码的补丁。
-
编译选项:
EXTRA_OEMAKE = "custom make options"
为编译过程提供额外的选项。
-
函数定义:
#自定义函数 do_something() 需要被显式调用,否则它不会被自动执行。 #在do_compile之前调用 addtask do_something before do_compile do_something() { # 函数体 }
使用
do_
前缀定义一个函数,该函数将在构建过程中的某个阶段被调用。 -
任务:
addtask sometask before do_compile after do_configure
定义一个任务,并指定它在构建过程中的执行顺序。
-
导出函数:
EXPORT_FUNCTIONS do_something
允许其他食谱调用这个食谱中定义的函数。
-
文件和目录操作:
install -d ${D}/path/to/directory install -m 0644 file ${D}/path/to/file
使用
install
命令在目标目录(${D}
)中创建目录或安装文件。 -
环境变量:
export VARIABLE = "value"
设置环境变量,这将在构建过程中的shell环境中生效。
-
条件语句:
ifeq "${VARIABLE}" "value" # 如果变量等于value,则执行这里的代码 endif
使用
ifeq
和endif
进行条件判断。 -
包含其他文件:
include anotherfile.bb
包含其他
.bb
或.inc
文件。 -
PACKAGES
变量用于定义要生成的软件包名称,而FILES
变量则定义了每个软件包应该包含哪些文件。
-
-
常见方法
- do_fetch:下载源代码。
- do_unpack:解压缩源代码。
- do_patch:应用补丁到源代码。
- do_configure:配置源代码,通常运行配置脚本如
./configure
。 - do_compile:编译源代码。
- do_install:将编译好的程序安装到构建目录中。
- do_package:创建软件包。
- do_packagedata:生成软件包的元数据。
- do_package_write_*:写入软件包到不同的格式,如
do_package_write_ipk
用于 IPK 格式,do_package_write_rpm
用于 RPM 格式等。 - do_populate_sysroot:将构建好的库和头文件复制到系统根目录,供其他软件包使用。
- do_populate_staging:与
do_populate_sysroot
类似,但是针对 staging 目录。 - do_clean:清理构建目录。
- do_prepare_recipe_sysroot:为食谱准备系统根目录
-
示例
#定义了项目的主页、分类和许可证类型。 HOMEPAGE = "http://www.denx.de/wiki/U-Boot/WebHome" SECTION = "bootloaders" #指定了构建U-Boot所需的依赖包。 DEPENDS += "flex-native bison-native" LICENSE = "GPLv2+" LIC_FILES_CHKSUM = "file://Licenses/README;md5=30503fd321432fc713238f582193b78e" PE = "1" #定义了U-Boot的版本号、Git分支和修订号。 PV = "v2019.01+git${SRCPV}" DEFAULT_PREFERENCE = "-1" # Use openbmc-uboot clone SRCBRANCH = "openbmc/helium/v2019.01" SRCREV = "AUTOINC" #指定了源代码的获取方式,包括Git仓库和本地文件。 SRC_URI = "git://github.com/facebook/openbmc-uboot.git;branch=${SRCBRANCH};protocol=https \ file://fw_env.config \ " #定义了工作目录 S = "${WORKDIR}/git" #包含了一个额外的配置文件 include common/recipes-bsp/u-boot-fbobmc/use-intree-shipit.inc # 为编译过程添加了额外的选项 EXTRA_OEMAKE += 'KCFLAGS="-Werror"' #提供了软件包的摘要和它所提供的组件 SUMMARY = "U-Boot bootloader tools" DEPENDS += "openssl" PROVIDES = "${MLPREFIX}u-boot-mkimage ${MLPREFIX}u-boot-mkenvimage" PROVIDES:class-native = "u-boot-mkimage-native u-boot-mkenvimage-native" #定义了额外的软件包 PACKAGES += "${PN}-mkimage ${PN}-mkenvimage" # 需要向后兼容 "u-boot-mkimage-xxx.bb" RPROVIDES:${PN}-mkimage = "u-boot-mkimage" RREPLACES:${PN}-mkimage = "u-boot-mkimage" RCONFLICTS:${PN}-mkimage = "u-boot-mkimage" EXTRA_OEMAKE:class-target = 'CROSS_COMPILE="${TARGET_PREFIX}" CC="${CC} ${CFLAGS} ${LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" STRIP=true V=1' EXTRA_OEMAKE:class-native = 'CC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" STRIP=true V=1' EXTRA_OEMAKE:class-nativesdk = 'CROSS_COMPILE="${HOST_PREFIX}" CC="${CC} ${CFLAGS} ${LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" STRIP=true V=1' SED_CONFIG_EFI = '-e "s/CONFIG_EFI_LOADER=.*/# CONFIG_EFI_LOADER is not set/"' SED_CONFIG_EFI:x86 = '' SED_CONFIG_EFI:x86-64 = '' SED_CONFIG_EFI:arm = '' SED_CONFIG_EFI:armeb = '' SED_CONFIG_EFI:aarch64 = '' #定义了编译任务,包括配置和编译U-Boot do_compile () { oe_runmake sandbox_defconfig # Disable CONFIG_CMD_LICENSE, license.h is not used by tools and # generating it requires bin2header tool, which for target build # is built with target tools and thus cannot be executed on host. sed -i -e "s/CONFIG_CMD_LICENSE=.*/# CONFIG_CMD_LICENSE is not set/" ${SED_CONFIG_EFI} .config oe_runmake cross_tools NO_SDL=1 } #定义了安装任务,包括安装U-Boot工具到目标目录 do_install () { install -d ${D}${bindir} # mkimage install -m 0755 tools/mkimage ${D}${bindir}/uboot-mkimage ln -sf uboot-mkimage ${D}${bindir}/mkimage # mkenvimage install -m 0755 tools/mkenvimage ${D}${bindir}/uboot-mkenvimage ln -sf uboot-mkenvimage ${D}${bindir}/mkenvimage # dumpimage install -m 0755 tools/dumpimage ${D}${bindir}/uboot-dumpimage ln -sf uboot-dumpimage ${D}${bindir}/dumpimage # fit_check_sign install -m 0755 tools/fit_check_sign ${D}${bindir}/uboot-fit_check_sign ln -sf uboot-fit_check_sign ${D}${bindir}/fit_check_sign } #定义了软件包包含的文件和运行时依赖。 ALLOW_EMPTY:${PN} = "1" FILES:${PN} = "" FILES:${PN}-mkimage = "${bindir}/uboot-mkimage ${bindir}/mkimage ${bindir}/uboot-dumpimage ${bindir}/dumpimage ${bindir}/uboot-fit_check_sign ${bindir}/fit_check_sign" FILES:${PN}-mkenvimage = "${bindir}/uboot-mkenvimage ${bindir}/mkenvimage" RDEPENDS:${PN}-mkimage += "dtc" RDEPENDS:${PN} += "${PN}-mkimage ${PN}-mkenvimage" RDEPENDS:${PN}:class-native = "" #允许这个食谱在原生(native)和原生SDK(nativesdk)环境中构建。 BBCLASSEXTEND = "native nativesdk"
4.6..bbappend
-
简介
.bbappend
文件在 OpenEmbedded 和 Yocto 项目中用于修改或追加已有食谱(.bb
文件)中的内容。这些文件通常用于对特定食谱进行小的调整,而不需要修改原始食谱本身。.bbappend
文件的语法与.bb
文件类似,但它们的作用是在构建过程中追加或覆盖原始食谱中的变量和任务。 -
常见变量
- SUMMARY:提供软件包的简短描述。
- HOMEPAGE:定义软件包的主页URL。
- LICENSE:指定软件包的许可证类型。
- LIC_FILES_CHKSUM:定义许可证文件的校验和,用于验证许可证文件的完整性。
- DEPENDS:添加或修改软件包的依赖关系。
- RDEPENDS:定义软件包的运行时依赖。
- RRECOMMENDS:定义推荐的运行时依赖。
- SRC_URI:追加或修改源代码的获取方式。
- S:定义源代码的基目录。
- EXTRA_OEMAKE:传递额外的参数给make命令。
- PACKAGE_ARCH:定义特定于体系结构的软件包。
- FILES:定义软件包中包含的文件列表。
- INSANE_SKIP:定义在构建过程中需要跳过的检查。
- BBCLASSEXTEND:允许类在不同的构建环境中使用,如原生(native)或原生SDK(nativesdk)。
- inherit:用于继承其他类文件(
.bbclass
)中定义的函数和变量。 - do_():定义特定任务的函数,如
do_compile()
、do_install()
等,这些函数在构建过程中的特定阶段被调用。 - EXPORT_FUNCTIONS:用于导出在类中定义的函数,使得这些函数可以在继承这个类的食谱中被调用。
- PACKAGES:定义构建过程中生成的软件包名称。
- ALLOW_EMPTY:允许软件包在没有内容的情况下构建。
-
语法
-
依赖关系:
RDEPENDS_${PN} += "new-dependency"
追加新的运行时依赖到软件包。
-
源代码信息:
SRC_URI += "file://new-source-file"
追加额外的源代码文件到食谱。
-
补丁:
SRC_URI += "file://new-patch.patch"
追加额外的补丁到食谱。
-
编译选项:
EXTRA_OEMAKE += "new-compile-option"
追加额外的编译选项。
-
函数定义:
do_custom_task() { # 函数体 }
定义一个自定义任务函数。
-
任务追加:
addtask custom_task after do_compile before do_install
在构建过程中的特定阶段追加一个新任务。
-
环境变量:
export VARIABLE = "value"
设置环境变量,这将在构建过程中的shell环境中生效。
-
继承:
inherit extra-class
继承额外的类,以引入更多的函数和变量。
-
导出函数:
EXPORT_FUNCTIONS do_custom_task
允许其他食谱调用这个
.bbappend
文件中定义的函数。 -
条件语句:
ifeq "${MACHINE}" "mymachine" VARIABLE = "value" endif
使用条件语句根据机器类型或其他条件设置变量。
-
-
示例
#这行代码将当前.bbappend文件所在目录下的files子目录添加到FILESEXTRAPATHS变量的前面。 #这意味着BitBake在查找文件时会优先搜索这个目录。:表示这是一个路径列表,可以包含多个路径。 FILESEXTRAPATHS:prepend := "${THISDIR}/files:" #这行代码追加了三个本地文件到SRC_URI变量中。SRC_URI定义了构建过程中需要的源代码的位置。 SRC_URI += " \ file://openbmc-gpio-1/soc_gpio.py \ file://openbmc-gpio-1/ast2400_gpio_table.py \ file://openbmc-gpio-1/ast2500_gpio_table.py \ "
4.7.各个文件之间的联系和区别
.bbclass
、.conf
、.inc
、.bb
和 .bbappend
文件在 OpenEmbedded 和 Yocto 项目中共享类似的语法基础,但它们的用途和上下文环境有所不同。
共同点:
-
变量赋值:所有文件类型都允许定义变量并赋值。
bash
VARIABLE = "value"
-
变量追加:可以向现有变量追加值。
bash
VARIABLE += "value"
-
条件语句:支持使用条件语句来根据特定条件执行不同的操作。
bash
ifeq "${VARIABLE}" "value" # do something endif
-
函数定义:
.bb
、.bbappend
和.bbclass
文件中可以定义函数来封装构建逻辑。 -
继承:
.bb
和.bbappend
文件可以使用inherit
关键字来继承.bbclass
文件中的逻辑。
区别:
- 用途:
.conf
文件用于定义层的配置,如层的依赖、优先级等。.inc
文件用于包含可重用的配置片段,可以被.bb
或.bbappend
文件包含。.bbclass
文件用于定义类,这些类可以被.bb
或.bbappend
文件继承。.bb
文件是食谱文件,定义了如何构建一个软件包。.bbappend
文件用于追加或修改.bb
文件中的内容,通常用于特定层的定制。
- 作用范围:
.conf
文件中的配置影响整个层。.inc
文件中的变量和函数可以在多个.bb
或.bbappend
文件中重用。.bbclass
文件中的逻辑可以被多个.bb
或.bbappend
文件继承。.bb
文件中的逻辑定义了单个软件包的构建过程。.bbappend
文件中的逻辑追加或修改特定.bb
文件的构建过程。
- 执行时机:
.conf
文件中的配置在层被初始化时处理。.inc
文件在被包含时处理。.bbclass
文件中的逻辑在被继承时处理。.bb
文件中的逻辑在软件包构建时执行。.bbappend
文件在.bb
文件之后执行,允许覆盖或追加.bb
文件中的设置。
- 特殊变量和函数:
.conf
文件可能包含层特定的变量,如LAYERSERIES_COMPAT
。.inc
文件可能包含通用的函数和变量,如do_something()
。.bbclass
文件可能包含可重用的函数和变量,如do_compile()
。.bb
文件包含软件包特定的变量,如SRC_URI
、DEPENDS
。.bbappend
文件可能包含追加到.bb
文件的变量,如追加新的SRC_URI
或DEPENDS
。
4.8.问题拓展
-
.inc
文件有什么用?- 配置共享:
.inc
文件可以用来定义多个配置文件中共同使用的变量和设置。例如,在构建不同的机器配置时,可能会有一些共通的配置项,这些可以通过.inc
文件来共享。 - 代码复用:在不同的构建脚本或配置文件中,如果需要使用相同的代码片段,可以将这些代码放入
.inc
文件中,然后在需要的地方通过require
指令来包含这些文件,这样可以避免代码的重复编写。 - 模块化设计:
.inc
文件有助于实现模块化设计,使得整个项目的构建过程更加清晰和易于管理。通过将特定的功能或配置项封装在单独的.inc
文件中,可以使得主配置文件更加简洁,同时也便于对特定功能进行修改和维护。 - 条件编译:在某些情况下,
.inc
文件还可以用来实现条件编译,例如根据不同的平台或硬件配置来包含不同的代码片段。
因此,
.inc
文件在OpenBMC项目中扮演着重要的角色,它们通过提供代码和配置的复用、模块化设计以及条件编译等功能,使得项目结构更加清晰,维护更加方便。所以,它们并不是可有可无的,而是项目构建和管理中不可或缺的一部分。 - 配置共享:
-
PV从哪儿获取?最后又用到哪个地方?
在OpenBMC的
.bb
文件中,PV
(Package Version)变量定义了软件包的版本号。这个版本号可以从以下几个地方获取:- 源代码仓库:如果软件包是从版本控制系统(如Git)中获取的,
PV
可以包含从源代码仓库中获取的额外版本信息。例如,git${SRCPV}
表示版本号中包含了源代码仓库的版本信息。SRCPV
是在bitbake运行时计算得到的,表示当前软件包的版本,其值由bb.fetch2.get_srcrev(d)
函数计算得出。 - 软件包的tar文件:对于从网络仓库获取的源码tar包,
PV
通常与tar包的版本号相对应。开发者需要根据实际下载的tar包的版本号来设置PV
的值,并更新SRC_URI
中的md5sum
或sha256sum
以确保完整性和一致性。 - 自定义设置:开发者也可以根据需要自定义
PV
的值。在某些情况下,可能需要根据项目的特定需求来设置版本号,或者在没有可用的源代码仓库版本信息时自行指定版本号。
PV
的值在构建过程中用于多个地方:- 软件包标识:
PV
是软件包标识的一部分,用于区分不同版本的软件包。 - 依赖关系解析:在构建系统中,
PV
用于解析软件包之间的依赖关系。 - 包管理:在包管理工具中,
PV
用于管理软件包的安装、升级和卸载。 - 构建历史记录:
PV
也用于记录构建历史,以便追踪软件包的版本变化。
因此,
PV
并不是随意编写的,它需要准确反映软件包的版本状态,并且在整个构建和包管理过程中发挥重要作用。 - 源代码仓库:如果软件包是从版本控制系统(如Git)中获取的,
-
native和nativesdk是什么意思?原生是相对于谁来说的?
在Yocto Project中,
native
和nativesdk
是两个非常重要的概念,它们与构建环境相关:- native:这个术语指的是为构建主机(即运行BitBake的机器)编译的软件包。这些软件包在构建过程中生成,并且可以在构建主机上直接运行。例如,编译工具链或者构建工具(如
cmake
)就是为构建主机编译的,因为它们是在构建过程中使用的,而不是在目标设备上运行的。 - nativesdk:这个术语指的是为软件开发工具链(Software Development Kit, SDK)编译的软件包。这些软件包是为在SDK环境中运行而构建的,SDK环境模拟了目标硬件平台的环境。
nativesdk
类允许开发者在SDK环境中编译出可以在目标设备上运行的应用程序或库。
“原生”是相对于目标设备来说的。在Yocto Project中,构建系统会区分为构建主机(即编译环境)和目标设备(即最终软件运行的环境)。
native
和nativesdk
就是用来区分这两种环境的:- 构建主机(Build Host):指的是运行BitBake和编译过程的机器,通常是开发者的本地机器或者构建服务器。
- 目标设备(Target Device):指的是最终软件将要运行的硬件平台。
使用
BBCLASSEXTEND = "native nativesdk"
可以让同一个食谱(recipe)生成两个变体:一个用于构建主机(native
),一个用于SDK环境(nativesdk
)。这样做的好处是可以在不同的构建环境中重用相同的食谱代码,同时为每种环境定制特定的行为。如果没有指定BBCLASSEXTEND = "native nativesdk"
,那么这个食谱默认只会为目标设备(target)构建软件包。 - native:这个术语指的是为构建主机(即运行BitBake的机器)编译的软件包。这些软件包在构建过程中生成,并且可以在构建主机上直接运行。例如,编译工具链或者构建工具(如
-
.bbappend
文件可以修改.bb
文件中的函数吗?.bbappend
文件提供了一种机制,允许在不直接修改原始.bb
文件的情况下,对.bb
文件中定义的变量、函数进行追加或覆盖。如何修改函数?
在
.bbappend
文件中修改.bb
文件中的函数通常有以下几种方式:-
追加到函数:可以使用
append
变量将额外的命令追加到现有的函数中。inherit something # 追加到 do_something 函数 do_something[append] = " additional_command"
这将在执行
do_something
函数时,在原有命令之后追加additional_command
。 -
覆盖函数:如果需要完全替换
.bb
文件中的函数,可以在.bbappend
文件中重新定义该函数。# 覆盖 do_something 函数 # do_something() 函数需要被显式调用,它的执行时机取决于你在 .bb 文件中如何配置任务和依赖关系 do_something() { # 新的函数实现 echo "New implementation of do_something" }
这将完全替换原始
.bb
文件中的do_something
函数。 -
使用依赖和继承:有时候,
.bbappend
文件可能依赖于.bb
文件中的某些变量或函数。在这种情况下,可以使用DEPENDS
或inherit
来确保.bbappend
文件中的代码在正确的时机执行。
注意事项
- 函数名称冲突:如果多个
.bbappend
文件尝试修改同一个函数,可能会导致冲突。通常,最好的做法是确保每个.bbappend
文件只修改特定的功能,以避免不必要的复杂性。 - 代码维护:过度依赖
.bbappend
文件可能会使代码维护变得困难,因为函数的实现可能分散在多个文件中。因此,在使用.bbappend
文件时,应该保持代码的清晰和可维护性。 - 构建顺序:
.bbappend
文件是在.bb
文件之后处理的,所以它们可以覆盖或追加.bb
文件中的内容。但是,如果.bbappend
文件之间存在依赖关系,它们的应用顺序可能会影响最终的结果。
-
-
.bbclass
文件是怎么给自己的类命名的?.bbclass
文件的命名约定通常是:- 文件名对应于类名。
- 文件扩展名是
.bbclass
。
因此,如果你有一个
.bbclass
文件,比如myclass.bbclass
,那么在.bb
文件中使用inherit myclass
时,BitBake 会自动寻找并使用myclass.bbclass
文件中定义的内容。示例:
例如,
myclass.bbclass
文件可能看起来像这样:# myclass.bbclass #函数命名前通常加上类名 myclass_do_something() { # 一些操作 } myclass_do_another_thing() { # 另一些操作 } # 导出函数,使得它们可以在继承这个类的 .bb 文件中被调用 EXPORT_FUNCTIONS do_something do_another_thing
然后在
.bb
文件中,你可以通过inherit
来使用这些函数:# myrecipe.bb inherit myclass do_something() { # 调用 myclass_do_something 函数 myclass_do_something }
-
.inc .bb .bbclass .bbappend .conf,执行先后顺序又是怎么样的?
在OpenBMC编译过程中,
.inc
、.bb
、.bbclass
、.bbappend
和.conf
文件的执行逻辑顺序如下:- 配置文件(.conf):这些文件首先被处理,用于设置构建环境的配置参数。
- 包含文件(.inc):这些文件包含变量定义和函数,可以在
.bb
文件中通过include
指令包含。这些文件被包含在食谱中,提供共享的函数和变量。 - 类文件(.bbclass):这些文件定义了可以被多个食谱继承的类,它们提供了构建逻辑和代码。当
.bb
文件中使用inherit
指令时,BitBake会解析相应的.bbclass
文件。base.bbclass
始终被包含在内,其他类文件根据INHERIT
变量指定。 - 食谱文件(.bb):这是食谱的主要文件,定义了如何构建软件包。BitBake会解析
.bb
文件,并根据其中的指令(如inherit
、require
等)去解析相应的.bbclass
或.inc
文件。 - 附加文件(.bbappend):这些文件用于修改或扩展现有的
.bb
文件。它们在.bb
文件解析完成后应用,允许在不修改原始.bb
文件的情况下添加或覆盖变量和函数。
综上所述,执行先后顺序为:
.conf
→.inc
→.bb
→.bbclass
→.bbappend
。这个顺序确保了配置文件首先设置环境,然后.inc
文件和.bbclass
文件提供共享代码和逻辑,接着.bb
文件定义构建逻辑,最后.bbappend
文件进行必要的修改或扩展,这些都属于BitBake的解析阶段。 -
当
.bb
文件当中有多个函数do_configure
、do_compile
、do_install
时,执行的顺序是怎么样的?分阶段执行:
do_configure
:这个任务负责配置源代码,通常是运行配置脚本(如./configure
)或者设置编译环境。它等同于在源代码目录中执行配置命令,例如mkdir build/ && cd build/ && cmake ${EXTRA_OECMAKE}
。do_compile
:在do_configure
之后执行,这个任务负责编译源代码。如果项目是基于make
的,那么这个任务会运行oe_runmake
命令。如果有额外的编译选项,可以通过EXTRA_OEMAKE
变量来添加。do_install
:最后执行的是do_install
任务,它负责将编译生成的文件安装到构建目录中,通常是${D}
目录。这个任务等同于执行make install
命令,将文件安装到指定目录。
食谱中的函数调用顺序取决于目前Bitbake所处的阶段:
- 解析阶段:主要负责读取和解析食谱和类文件,以及它们之间的依赖关系。在解析阶段,BitBake会读取这些文件,并构建一个依赖图,这个图描述了各个组件之间的关系。这个依赖图将用于后续的构建阶段,如任务执行和实际的编译过程。解析阶段完成后,BitBake会进入任务执行阶段,开始实际的构建任务。
- 配置阶段(
do_configure
):在配置阶段,BitBake会进入每个相关的.bb
文件,并调用do_configure
任务。这个阶段负责准备构建环境,比如运行配置脚本,设置编译选项等。 - 编译阶段(
do_compile
):一旦配置完成,BitBake会进入编译阶段,调用do_compile
任务。在这个阶段,源代码会被编译成目标平台上的可执行文件或库。 - 安装阶段(
do_install
):编译完成后,BitBake会执行安装阶段,调用do_install
任务。这个阶段将编译生成的文件安装到构建目录中,通常是${D}
目录。 - 打包阶段:最后,BitBake会执行打包阶段,将安装的文件打包成最终的软件包(如DEB、RPM、IPK等)。
每个阶段都是独立的,BitBake会根据构建任务的依赖关系和执行顺序来调度任务。这意味着在配置阶段,BitBake会遍历所有需要配置的食谱,并执行它们的
do_configure
任务;在编译阶段,它会执行所有需要编译的食谱的do_compile
任务;依此类推。此外,BitBake还支持并行构建,这意味着在多核处理器上,不同的任务可以同时执行,以加快构建过程。但是,对于单个食谱而言,这些任务的执行顺序仍然是按照
do_configure
、do_compile
、do_install
的顺序进行的。 -
oe_runmake
这个是什么命令?由什么构建而成?oe_runmake
是 OpenEmbedded (OE) 构建系统中的一个工具函数,它的作用是运行 Makefile 并将生成的文件安装到指定的目录中。 在 OE 环境中,当需要运行 make 命令时,推荐使用oe_runmake
而不是直接调用 make。oe_runmake
的主要特点包括:- 传递额外参数:
oe_runmake
可以将EXTRA_OEMAKE
变量中设置的参数传递给 make。 - 显示 make 命令:
oe_runmake
会显示实际执行的 make 命令,这有助于调试和记录构建过程中的具体操作。 - 错误检查:
oe_runmake
会检查通过调用生成的错误,确保构建过程的正确性。
oe_runmake
通常在.do_compile
和.do_install
任务中使用。在.do_compile
任务中,如果找到 Makefile,oe_runmake
会被调用来编译源代码。在.do_install
任务中,oe_runmake
用于执行make install
命令,并将${D}
作为 DESTDIR 传递进去,从而将编译生成的文件安装到构建目录中。oe_runmake
是由 OpenEmbedded 构建系统构建而成,是 base 类中定义的众多帮助函数之一。 它是基类(base class)的一部分,这个基类被每个.bb
文件隐式继承。 基类包含了一些标准基本任务的定义,例如编译(运行任何存在的 Makefile)和安装(默认为空)。 这些任务通常被其他类(如 autotools 类或 package 类)覆盖或扩展。
。
3. 编译阶段(do_compile
):一旦配置完成,BitBake会进入编译阶段,调用do_compile
任务。在这个阶段,源代码会被编译成目标平台上的可执行文件或库。
4. 安装阶段(do_install
):编译完成后,BitBake会执行安装阶段,调用do_install
任务。这个阶段将编译生成的文件安装到构建目录中,通常是${D}
目录。
5. 打包阶段:最后,BitBake会执行打包阶段,将安装的文件打包成最终的软件包(如DEB、RPM、IPK等)。每个阶段都是独立的,BitBake会根据构建任务的依赖关系和执行顺序来调度任务。这意味着在配置阶段,BitBake会遍历所有需要配置的食谱,并执行它们的
do_configure
任务;在编译阶段,它会执行所有需要编译的食谱的do_compile
任务;依此类推。此外,BitBake还支持并行构建,这意味着在多核处理器上,不同的任务可以同时执行,以加快构建过程。但是,对于单个食谱而言,这些任务的执行顺序仍然是按照
do_configure
、do_compile
、do_install
的顺序进行的。 - 传递额外参数:
-
oe_runmake
这个是什么命令?由什么构建而成?oe_runmake
是 OpenEmbedded (OE) 构建系统中的一个工具函数,它的作用是运行 Makefile 并将生成的文件安装到指定的目录中。 在 OE 环境中,当需要运行 make 命令时,推荐使用oe_runmake
而不是直接调用 make。oe_runmake
的主要特点包括:- 传递额外参数:
oe_runmake
可以将EXTRA_OEMAKE
变量中设置的参数传递给 make。 - 显示 make 命令:
oe_runmake
会显示实际执行的 make 命令,这有助于调试和记录构建过程中的具体操作。 - 错误检查:
oe_runmake
会检查通过调用生成的错误,确保构建过程的正确性。
oe_runmake
通常在.do_compile
和.do_install
任务中使用。在.do_compile
任务中,如果找到 Makefile,oe_runmake
会被调用来编译源代码。在.do_install
任务中,oe_runmake
用于执行make install
命令,并将${D}
作为 DESTDIR 传递进去,从而将编译生成的文件安装到构建目录中。oe_runmake
是由 OpenEmbedded 构建系统构建而成,是 base 类中定义的众多帮助函数之一。 它是基类(base class)的一部分,这个基类被每个.bb
文件隐式继承。 基类包含了一些标准基本任务的定义,例如编译(运行任何存在的 Makefile)和安装(默认为空)。 这些任务通常被其他类(如 autotools 类或 package 类)覆盖或扩展。 - 传递额外参数: