Yocto Project概念(一)
此文为机器辅助翻译,仅供个人学习使用,如有翻译不当之处欢迎指正
原文链接:https://docs.yoctoproject.org/overview-manual/concepts.html#
4 Yocto Project概念
本章对 Yocto Project的概念进行了阐释,这些内容超越了 “操作方法” 层面的信息以及参考(或查阅)资料的范畴。诸如组件、OpenEmbedded Build System 工作流程、交叉开发工具链、共享状态缓存等概念都将在本章进行详细解释。
4.1 Yocto Project 组件
BitBake 任务执行器与各类配置文件共同构成了 OpenEmbedded-Core (OE-Core)。本节将通过描述这些组件的用途以及它们之间的交互方式,对其进行概述。
BitBake 负责解析和执行数据文件。这些数据有多种类型:
-
Recipes(recipes,也被翻译为菜谱):提供有关特定软件的详细信息。
-
Class Data(类数据):抽象出通用的构建信息(例如,如何构建 Linux 内核)。
-
Configuration Data(配置数据):定义机器特定的设置、策略决策等。配置数据起到将所有内容结合在一起的纽带作用。
BitBake 知道如何将多个数据源组合在一起,并将每个数据源视为一个层。有关层的信息,请参阅 Yocto 项目开发任务手册中的“ 了解和创建图层” 部分。
以下是有关这些核心组件的一些简要详细信息。为 有关这些组件在构建过程中如何交互的其他信息, 请参阅 “OpenEmbedded 构建系统概念” 部分。
4.1.1 BitBake
BitBake 是 OpenEmbedded Build System 的核心工具,负责解析元数据,从中生成任务列表,然后执行这些任务。
本节将简要介绍 BitBake。如果您想了解更多信息 BitBake,请参阅 BitBake 用户手册。
要查看 BitBake 支持的选项列表,请使用 以下命令:
$ bitbake -h
$ bitbake --help
BitBake 最常见的用法是bitbake recipename
,其中recipename
是您要构建的recipes名称(称为 “目标”)。目标通常对应于recipes文件名的第一部分(例如,对于名为foo_1.3.0-r0.bb
的recipes,目标为 “foo” )。因此,要处理matchbox-desktop_1.2.3.bb
recipes文件,您可能会输入以下命令:
$ bitbake matchbox-desktop
可能存在多个不同版本的matchbox-desktop
。BitBake 会根据发行版配置选择其中一个。您可以在《BitBake 用户手册》的“首选项”部分中,了解有关 BitBake 如何在不同目标版本和提供者之间进行选择的更多详细信息。
BitBake 还会尝试先执行任何依赖任务。例如,在构建matchbox-desktop
之前,如果尚未构建交叉编译器和 glibc,BitBake 会先构建它们。
一个值得考虑的有用的 BitBake 选项是-k
或--continue
选项。该选项指示 BitBake 在遇到错误后,尽可能继续处理任务。当发生错误时,失败的目标及其依赖的目标将无法重新构建。但是,使用此选项时,其他依赖项仍可以继续处理 。
4.1.2 recipes(配方)
后缀为.bb
的文件是 “recipes” 文件。一般来说,一个recipes包含关于单个软件的信息。这些信息包括从何处下载未修改的源代码、是否需要对该源代码应用任何源补丁、应应用哪些特殊配置选项、如何编译源文件以及如何打包编译输出。
术语 “package” 有时用于指代recipes。然而,由于 “package” 一词在 OpenEmbedded 构建系统中用于表示打包输出(即.ipk
或.deb
文件),因此本文档在提及recipes时避免使用 “package” 这个术语。
4.1.3 Classes(类)
类文件(.bbclass
)包含可在recipes文件之间共享的信息。例如,autotools*
类包含使用 GNU Autotools 构建的任何应用程序的通用设置。《Yocto 项目参考手册》中的 “类” 一章提供了有关类及其使用方法的详细信息。
4.1.4 Configurations(配置)
配置文件(.conf
)定义了各种配置变量,用于控制 OpenEmbedded 构建过程。这些文件分为几个领域,定义了机器配置选项、发行版配置选项、编译器调整选项、通用配置选项以及在构建目录中的conf/local.conf
文件中的用户配置选项。
4.2 Layers(层)
层是包含相关元数据(即指令集)的存储库,这些元数据告诉 OpenEmbedded 构建系统如何构建目标。Yocto 项目层模型促进了 Yocto 项目开发环境中的协作、共享、定制和重用。层在逻辑上为您的项目分离信息。例如,您可以使用一个层来保存特定硬件的所有配置。将特定于硬件的配置隔离开来,这样您就可以通过使用不同的层来共享其他元数据,因为这些元数据可能在多个硬件之间是通用的。
在 Yocto 项目开发环境中有许多层在发挥作用。Yocto 项目兼容层索引和 OpenEmbedded 层索引都包含可供使用或利用的层。
按照惯例,Yocto 项目中的层遵循特定的形式。遵循已知的结构可以让 BitBake 在构建过程中对元数据的位置做出假设。您可以在 Yocto 项目开发任务手册的 “理解和创建层” 部分找到创建适合 Yocto 项目的层的步骤和相关工具(即 bitbake-layers
)。
4.3 OpenEmbedded 构建系统概念
本节更详细地介绍了 OpenEmbedded 构建系统所使用的构建过程,这是 Yocto 项目特有的构建系统。构建系统的核心是任务执行器 BitBake。
以下图表展示了构建的高级工作流程。本节的其余部分将扩展构成该工作流程的基本输入、输出、过程和元数据逻辑模块。
通常,构建的工作流程由几个功能区域组成:
-
User Configuration(用户配置):您可以用来控制构建过程的元数据。
-
Metadata Layers(元数据层):提供软件、机器和发行版元数据的各个层。
-
Sources(源文件):上游版本、本地项目和软件配置管理(SCM)。
-
Build System(构建系统):在 BitBake 的控制下进行的过程。此模块详细说明了 BitBake 如何获取源文件、应用补丁、完成编译、分析输出以生成软件包、创建和测试软件包、生成镜像以及生成交叉开发工具。
-
Package Feeds(包源):包含输出包的目录(RPM、DEB 或 IPK),这些 IPK 随后用于构建图像或 软件开发工具包 (SDK),由构建系统生成。这些 还可以使用 Web 服务器或其他方式复制和共享源 为了便于扩展或更新设备上的现有映像,请访问 runtime (如果启用了 runtime 包管理)。
-
Images(镜像):工作流生成的镜像。
-
应用开发 SDK:与镜像一起或单独使用 BitBake 生成的交叉开发工具。
4.3.1 User Configuration(用户配置)
用户配置有助于定义构建。通过用户配置,您可以告诉 BitBake 要为其构建镜像的目标架构、存储下载源的位置以及其他构建属性。
以下图表展示了一般工作流程图中 “用户配置” 框的扩展表示:
BitBake 需要一些基本的配置文件才能完成构建。这些文件是.conf
文件。最低限度必要的文件作为示例文件存在于源目录的build/conf
目录中。为简单起见,本节将源目录称为 “Poky 目录”。
当您克隆 Poky Git 存储库或下载并解压 Yocto 项目版本时,您可以将源目录设置为任何您想要的名称。在本讨论中,克隆的存储库使用默认名称poky
。
[!NOTE]
Poky存储库主要是现有存储库的集合,它并非规范的上游源。
Poky 内部的 meta-poky 层包含一个conf
目录,其中有示例配置文件。当您执行构建环境脚本oe-init-build-env
时,这些示例文件将作为创建实际配置文件的基础。
执行构建环境脚本会在不存在构建目录的情况下创建一个构建目录。BitBake 在构建过程中会将构建目录用于所有工作。构建目录有一个conf
目录,其中包含local.conf
和bblayers.conf
配置文件的默认版本。只有在执行构建环境设置脚本时,构建目录中不存在这些版本的情况下,才会创建这些默认配置文件。
由于 Poky 存储库本质上是现有存储库的聚合,一些用户可能熟悉在单独的 OpenEmbedded-Core(OE-Core)和 BitBake 存储库的上下文中运行oe-init-build-env
脚本,而不是在单个 Poky 存储库中。本讨论假设该脚本是在克隆或解压的 Poky 版本中执行的。
根据脚本的执行位置,会调用不同的子脚本来设置构建目录(Yocto 或 OpenEmbedded)。具体来说,poky 目录中的 scripts/oe-setup-builddir
脚本会设置构建目录,并在必要时用适合 Yocto 项目开发环境的配置文件为该目录进行初始化。
[!NOTE]
scripts/oe-setup-builddir
脚本使用$TEMPLATECONF
变量来确定要查找的示例配置文件。
local.conf
文件提供了许多定义构建环境的基本变量。以下是其中一些变量的列表。要查看由构建环境脚本创建的local.conf
文件中的默认配置,请参阅meta-poky
层中的local.conf.sample
文件:
-
目标机器选择:由 MACHINE 变量控制。
-
下载目录:由 DL_DIR 变量控制。
-
共享状态目录:由 SSTATE_DIR 变量控制。
-
构建输出:由 TMPDIR 变量控制。
-
发行版策略:由 DISTRO 变量控制。
-
打包格式:由 PACKAGE_CLASSES 变量控制。
-
SDK 目标架构:由 SDKMACHINE 变量控制。
-
额外镜像包:由 EXTRA_IMAGE_FEATURES 变量控制。
[!NOTE]
在conf/local.conf
文件中设置的配置也可以在conf/site.conf
和conf/auto.conf
配置文件中进行设置。
bblayers.conf
文件告诉 BitBake 在构建过程中要考虑哪些层。默认情况下,此文件中列出的层包括构建系统最少需要的层。但是,您必须手动添加您创建的任何自定义层。您可以在 Yocto 项目开发任务手册的 “启用您的层” 部分中找到有关使用bblayers.conf
文件的更多信息。
site.conf
和auto.conf
文件不是由环境初始化脚本创建的。如果您需要site.conf
文件,则需要自己创建它。auto.conf
文件通常由自动构建器创建:
-
site.conf:您可以使用
conf/site.conf
配置文件来配置多个构建目录。例如,假设您有几个构建环境,并且它们共享一些共同的功能。您可以在此处设置这些默认构建属性。一个很好的例子可能是通过PACKAGE_CLASSES
变量设置要使用的打包格式。 -
- auto.conf:该文件通常由自动构建器创建并写入。放入该文件中的设置通常与您在
conf/local.conf
或conf/site.conf
文件中找到的设置相同。
- auto.conf:该文件通常由自动构建器创建并写入。放入该文件中的设置通常与您在
您可以编辑所有配置文件以进一步定义任何特定的构建环境。此过程由图中的 “User Configuration Edits(用户配置编辑)” 框表示。
当您使用bitbake target
命令启动构建时,BitBake 会整理配置,最终定义您的构建环境。重要的是要理解,OpenEmbedded 构建系统按特定顺序读取配置文件:site.conf
、auto.conf
和local.conf
。并且,构建系统应用《BitBake 用户手册》“语法和操作符” 一章中描述的正常赋值语句规则。由于文件是按特定顺序解析的,因此同一变量的赋值可能会受到影响。例如,如果auto.conf
文件和local.conf
将variable1
设置为不同的值,由于构建系统在auto.conf
之后解析local.conf
,variable1
将被赋予local.conf
文件中的值。
4.3.2 元数据、计算机配置和策略配置
上一节介绍了定义 BitBake 全局行为的用户配置。本节将深入探讨构建系统用于进一步控制构建过程的各个层。这些层为软件、机器和策略提供元数据。
一般来说,有三种类型的层输入。在通用工作流程图 <overview-manual/concepts:openembedded build system concepts> 中 “User Configuration” 框的下方,你可以看到它们。
-
元数据 (.bb + Patches(补丁)):包含用户提供的配方文件、补丁和追加文件的软件层。一个很好的软件层示例可能是来自 OpenEmbedded 层索引的
meta-qt5
层,该层用于流行的 Qt 跨平台应用开发框架的 5.0 版本,适用于桌面、嵌入式和移动设备。 -
机器 BSP 配置:板级支持包(BSP)层(即下图中的 “BSP Layer”),提供特定于机器的配置。这类信息特定于特定的目标架构。参考发行版(Poky)中 BSP 层的一个很好的例子是
meta-yocto-bsp
层。 -
策略配置:发行版层(即下图中的 “Distro Layer”),为特定发行版正在构建的镜像或 SDK 提供顶级或通用策略。例如,在 Poky 参考发行版中,发行版层是
meta-poky
层。在发行版层内的conf/distro
目录中包含发行版配置文件(例如poky.conf
,其中包含许多针对 Poky 发行版的策略配置)。
下图显示了这三个的扩展表示 常规工作流图中的 layers:
一般来说,所有的层都有相似的结构。如果层要分发,它们都包含一个许可文件(例如COPYING.MIT
);作为良好实践,特别是如果层要分发,还会包含一个README
文件;此外还有一个配置目录和配方目录。你可以在 Yocto 项目开发任务手册的 “创建自己的层” 部分了解 Yocto 项目使用的层的一般结构。关于层以及可以使用的众多层的一般讨论,请参阅本手册前面的 “层” 和 “Yocto 项目层模型” 部分。
如果你浏览了前面的链接,就会发现有很多与 Yocto 项目一起工作的层。源存储库还展示了在 “Yocto 元数据层” 类别下的层。
[!NOTE]
Yocto 项目源存储库中有些层在 OpenEmbedded 层索引中找不到。这类层要么是已弃用的,要么是实验性质的。
BitBake 使用conf/bblayers.conf
文件(这是用户配置的一部分)来查找它在构建过程中应该使用的层。
4.3.2.1 Distro Layers(发行版层)
发行版层为你的发行版提供策略配置。最佳实践建议将这类配置隔离到它们自己的层中。你在conf/distro/distro.conf
中提供的设置会覆盖 BitBake 在构建目录的conf/local.conf
文件中找到的类似设置。
以下列表对在发行版层中通常会找到的内容进行了解释和参考:
-
类:类文件(
.bbclass
)包含可以在发行版的配方之间共享的通用功能。当你的配方继承一个类时,它们会采用该类的设置和功能。你可以在《Yocto 参考手册》的 “类” 一章中了解更多关于类文件的信息。 -
conf:这个区域包含层的配置文件(
conf/layer.conf
)、发行版的配置文件(conf/distro/distro.conf
)以及任何发行版范围的包含文件。 -
recipes-:影响发行版通用功能的配方和追加文件。这个区域可能包括添加发行版特定配置、初始化脚本、自定义镜像配方等的配方和追加文件。
recipes-\*
目录的示例有recipes-core
和recipes-extra
。recipes-\*
目录的层次结构和内容可能会有所不同。一般来说,这些目录包含配方文件(*.bb
)、配方追加文件(*.bbappend
)、特定于发行版的配置文件目录等。
4.3.2.2 BSP 层
BSP 层提供针对特定 硬件。此层中的所有内容都特定于 您正在构建映像或 SDK。常见的结构或形式是 为 BSP 层定义。您可以在 Yocto Project Board Support Package Developer’s Guide 中了解有关此结构的更多信息。
[!NOTE]
为了使 BSP 层符合 Yocto 项目的要求,它必须满足一些结构要求。
BSP 层的配置目录包含机器的配置文件(conf/machine/machine.conf
),当然还有层的配置文件(conf/layer.conf
)。
该层的其余部分按功能专门用于特定的配方:recipes-bsp
、recipes-core
、recipes-graphics
、recipes-kernel
等。可能有针对多种外形因素、图形支持系统等的元数据。
[!NOTE]
虽然图中显示了几个recipes-\*
目录,但并非所有这些目录都会出现在所有 BSP 层中。
4.3.2.3 软件层
软件层为构建过程中使用的额外软件包提供元数据。该层不包括特定于发行版或机器的元数据,这些元数据可以在各自的层中找到。
该层包含你的项目所需的任何配方、追加文件和补丁。
4.3.3 Sources(源文件)
为了让 OpenEmbedded 构建系统创建镜像或任何 target,它必须能够访问源文件。一般工作流程 figure 表示使用 “Upstream Project Releases”、“Local Projects“和”SCM (optional)“框。图中用 “Source Materials” 框表示镜像,它在定位源文件时也起着作用。
源文件最终的组织方式取决于项目。例如,对于已发布的软件,项目倾向于使用 tarball 或其他归档文件来捕获版本状态,以保证其静态表示。另一方面,对于更具动态性或实验性质的项目,可能会将源文件保存在由软件配置管理工具(如 Git)控制的存储库中。从存储库中获取源文件可以让你控制要从哪个存储库版本构建软件。也可以将两者结合使用。
无论源文件位于何处,BitBake 都使用SRC_URI
变量来指向它们。每个配方都必须有一个SRC_URI
变量,用于指向源文件。
另一个在源文件来源方面起重要作用的区域由DL_DIR
变量指定。这个区域是一个缓存,可以保存先前下载的源文件。你还可以通过使用BB_GENERATE_MIRROR_TARBALLS
变量,指示 OpenEmbedded 构建系统从 Git 存储库创建 tarball 文件,并将它们存储在DL_DIR
中,不过这不是默认行为。
明智地使用DL_DIR
目录可以节省构建系统在查找文件时访问互联网的开销。使用下载目录的一个好方法是让DL_DIR
指向构建目录之外的区域。这样,如果需要,你可以安全地删除构建目录,而不必担心删除任何已下载的源文件。
本节的其余部分将更深入地探讨源文件和镜像。以下是对一般工作流程图中源文件区域的更详细介绍:
4.3.3.1 Upstream Project Releases(上游项目版本)
上游项目版本以归档文件(例如 tarball 或 zip 文件)的形式存在于任何地方。这些文件对应于各个配方。例如,图中分别展示了 BusyBox、Qt 和 Dbus 的特定版本。归档文件可以是任何可以使用配方构建的已发布产品的文件。
4.3.3.2 Local Projects(本地项目)
本地项目是用户提供的自定义软件部分。这些部分位于项目本地的某个位置,例如用户检入项目的目录(例如,一个包含团队使用的开发源树的本地目录)。
包含本地项目的标准方法是使用externalsrc
类来包含该本地项目。你可以使用local.conf
或配方的追加文件来覆盖或设置配方,使其指向你磁盘上的本地目录,以拉入整个源树。
4.3.3.3 源代码控制管理器(可选)
构建系统获取源文件的另一个来源是使用各种软件配置管理工具(如 Git 或 Subversion)的获取器。在这种情况下,会克隆或检出一个存储库。BitBake 内部的do_fetch
任务使用SRC_URI
变量及其参数前缀来确定正确的获取器模块。
[!NOTE]
有关如何让 OpenEmbedded 构建系统生成 tarballs 并将其放在 DL_DIR 目录中,请参阅 Yocto Project Reference Manual 中的 BB_GENERATE_MIRROR_TARBALLS 变量。
在获取存储库时,BitBake 使用 SRCREV 变量来确定要构建的特定版本。
4.3.3.4 源镜像
有两种类型的镜像:预镜像和常规镜像。PREMIRRORS 和 MIRRORS 变量分别指向它们。BitBake 在查找上游源文件之前会先检查预镜像。当你有一个不是由DL_DIR
变量定义的共享目录时,预镜像就很适用。预镜像通常指向你所在组织内部的共享目录。
常规镜像可以是互联网上的任何站点,当主站点由于某种原因无法正常工作时,可作为源代码的备用位置。
4.3.4 包源
当 OpenEmbedded 构建系统生成一个镜像或 SDK 时,它会从构建目录中的包源区域获取软件包。一般工作流程图在右上角展示了这个包源区域。
本节将更深入地了解构建系统使用的包源区域。以下是对该区域的更详细介绍:
包源是构建过程中的一个中间步骤。OpenEmbedded 构建系统提供了用于生成不同软件包类型的类,你可以通过PACKAGE_CLASSES
变量指定要启用的类。在将软件包放入包源之前,构建过程会通过insane
类使用生成的输出质量保证检查来验证它们。
包订阅源区域位于 Build Directory 中。目录 build 系统用于临时存储软件包的 变量和正在使用的特定包管理器的组合。看 图中的 “Package Feeds” 框,并将信息记在 该区域的右侧。具体而言,下面定义了其中 软件包文件被保留:
-
DEPLOY_DIR:在构建目录中定义为
tmp/deploy
。 -
DEPLOY_DIR_*
:根据所使用的软件包管理器,为软件包类型子文件夹。对于 RPM、IPK 或 DEB 打包以及 tarball 创建,分别使用DEPLOY_DIR_RPM
、DEPLOY_DIR_IPK
或DEPLOY_DIR_DEB
变量。 -
PACKAGE_ARCH:定义特定于架构的子文件夹。例如,软件包可能适用于 i586 或 qemux86 架构。
BitBake 使用do_package_write_*
任务来生成软件包,并将它们放入软件包存储区域(例如,对于 IPK 软件包,使用do_package_write_ipk
任务)。有关更多信息,请参阅 Yocto 项目参考手册中的do_package_write_deb
、do_package_write_ipk
和do_package_write_rpm
部分。例如,假设使用 IPK 软件包管理器,并且同时支持 i586 和 qemux86 架构的软件包。那么,适用于 i586 架构的软件包将被放置在build/tmp/deploy/ipk/i586
目录中,而适用于 qemux86 架构的软件包将被放置在build/tmp/deploy/ipk/qemux86
目录中 。
4.3.5 BitBake 工具
OpenEmbedded 构建系统使用 BitBake 来生成镜像和软件开发工具包(SDK)。从一般工作流程图中可以看出,BitBake 区域由几个功能区域组成。本节将更深入地研究每个区域。
[!NOTE]
BitBake 工具的文档可单独获取。有关 BitBake 的参考资料,请参阅 BitBake 用户手册。
4.3.5.1 源获取
构建recipes的第一阶段是获取并解压源代码:
do_fetch 和 do_unpack 任务负责获取源文件并将其解压到构建目录中。
[!NOTE]
对于配方的SRC_URI
语句中包含的每个本地文件(例如file://
),OpenEmbedded 构建系统会为该文件计算校验和,并将其插入到do_fetch
任务的签名中。如果任何本地文件被修改,do_fetch
任务以及所有依赖于它的任务都将重新执行。
默认情况下,所有操作都在构建目录中完成,构建目录具有特定的结构。有关构建目录的更多常规信息,请参阅 Yocto 项目参考手册中的 “build/” 部分。
每个配方在构建目录中都有一个存放解压后源代码的区域。UNPACKDIR
变量指向该区域,其默认名称为sources-unpack
。上图和以下列表描述了构建目录的层次结构:
-
TMPDIR:OpenEmbedded 构建系统在构建过程中执行所有工作的基础目录。默认的基础目录是
tmp
目录。 -
PACKAGE_ARCH: 构建的软件包或多个软件包的架构。根据软件包的最终目标(即机器架构、构建主机、SDK 或特定机器),
PACKAGE_ARCH
会有所不同。有关该变量的详细描述,请查看其说明。 -
TARGET_OS:目标设备的操作系统。典型的值为 “linux”(例如 “qemux86 poky-linux”)。
-
PN:用于构建软件包的配方名称。该变量可能有多种含义。然而,在输入文件的上下文中,
PN
代表配方名称。 -
WORKDIR:OpenEmbedded 构建系统构建配方(即创建软件包的工作)的位置。
- PV:用于构建软件包的配方版本。
-
UNPACKDIR:包含给定配方的解压后源文件。
-
S:包含源代码的最终位置。
BP 的默认值为
${BPN}-${PV}
,其中:-
BPN:用于构建软件包的配方名称。
BPN
变量是PN
变量的一个版本,但去除了常见的前缀和后缀。 -
PV:用于构建软件包的配方版本。
-
[!NOTE]
在前面的图中,有两个示例层次结构:一个基于软件包架构(即PACKAGE_ARCH
),另一个基于机器(即MACHINE
)。它们的底层结构是相同的,区别在于 OpenEmbedded 构建系统使用什么作为构建目标(例如,通用架构、构建主机、SDK 或特定机器)。
4.3.5.2 Patching(补丁)
获取并解压缩源代码后,BitBake 会找到补丁文件 并将它们应用于源文件:
do_patch 任务使用 recipe 的 SRC_URI 语句和 FILESPATH 变量以查找适用的补丁文件。
默认情况下,补丁文件的处理假设文件类型为*.patch
或*.diff
。你可以使用SRC_URI
参数来更改构建系统识别补丁文件的方式。有关更多信息,请查看do_patch
任务。
BitBake 在 它查找修补程序的顺序。FILESPATH 变量定义构建系统用于的默认目录集搜索 Patch Files。找到后,补丁将应用于recipes的源文件,位于 S 目录中。
有关如何创建源目录的更多信息,请参阅 “Source Fetching”部分。有关如何创建补丁以及构建系统如何处理补丁的更多信息,请参阅《Yocto 项目开发任务手册》中的“Patching Code ”部分。您还可以查看《Yocto 项目应用开发和可扩展软件开发工具包(SDK)手册》中的“Use devtool modify to Modify the Source of an Existing Component”部分以及《Yocto 项目 Linux 内核开发手册》中的“Using Traditional Kernel Development to Patch the Kernel”部分。
4.3.5.3 配置、编译和暂存
源代码打补丁之后,BitBake 会执行配置和编译源代码的任务。编译完成后,文件会被复制到一个暂存区域(进行暂存),为打包做准备:
构建过程的这一步包含以下任务::
-
do_prepare_recipe_sysroot: 此任务会在 ${ WORKDIR} 中设置两个系统根目录(即
recipe-sysroot
和recipe-sysroot-native
),这样在打包阶段,这些系统根目录就能包含该任务所在配方所依赖的其他配方的 do_populate_sysroot 任务的内容。目标和在主机系统上运行的原生二进制文件都有各自的系统根目录。 -
do_configure:此任务通过启用或禁用正在构建的软件的构建时配置选项来对源代码进行配置。这些配置可能来自配方本身,也可能来自继承的类。此外,软件本身也可能会根据其构建目标进行自我配置。
do_configure任务所处理的配置是针对该配方正在构建的源代码的特定配置。
如果你正在使用
autotools*
类,你可以通过使用EXTRA_OECONF
或PACKAGECONFIG_CONFARGS
变量来添加额外的配置选项。有关该变量在该类中如何工作的信息,请参阅此处的 autotools*类相关内容。 -
do_compile:满足配置任务后, BitBake 使用 do_compile 任务编译源代码。 编译发生在 B 变量指向的目录中。请注意,默认情况下,B 目录与 S 目录相同。
-
do_install:编译完成后,BitBake 执行 do_install 任务。 此任务从 B 目录复制文件,并将它们放在 D 变量指向的保持区域。稍后使用此 Holding 中的文件进行打包 目录。
4.3.5.4 Package Splitting(包拆分)
在源代码完成配置、编译和暂存后,构建系统会分析结果并将输出拆分为多个软件包:
do_package 和 do_packagedata 任务共同对在 D 目录中找到的文件进行分析,并根据可用的软件包和文件将其拆分为多个子集。分析内容除其他事项外,还包括:分离调试符号、检查软件包之间的共享库依赖关系以及查看软件包之间的关联。
do_packagedata 任务会根据分析结果创建软件包元数据,以便构建系统生成最终的软件包。do_populate_sysroot任务会将 do_install 任务安装的一部分文件暂存(复制)到相应的系统根目录(sysroot)中。分析和软件包拆分过程中的工作数据、暂存数据和中间结果会使用多个区域。
-
PKGD:在软件包被拆分成单个软件包之前,它是软件包的目标目录(即
package
)。 -
PKGDESTWORK: 一个临时工作区域(即
pkgdata
),do_package 任务用它来保存软件包元数据。 -
PKGDEST:软件包拆分后的父目录(即
packages-split
)。 -
PKGDATA_DIR:一个共享的全局状态目录,用于保存软件包构建过程中生成的打包元数据。打包过程会将元数据从 PKGDESTWORK 复制到 PKGDATA_DIR 区域,使其全局可用。
-
STAGING_DIR_HOST: 组件构建后在其上运行的系统的系统根目录路径(即 recipe-sysroot)。
-
STAGING_DIR_NATIVE: 构建主机组件时使用的系统根目录路径(即 recipe-sysroot-native)。
-
STAGING_DIR_TARGET: 当一个组件构建后在某系统上执行且为另一台机器生成代码时所使用的系统根目录路径(例如交叉编译的情况)。
一个配方的软件包列在 PACKAGES 变量中。bitbake.conf 配置文件定义了以下默认的软件包列表:
PACKAGES = "${PN}-src ${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN}"
每个包都包含一个由FILES变量定义的默认文件列表。例如,包${PN}-dev
表示对依赖 ${PN}
开发应用程序有用的文件。默认的文件列表对于同样定义在bitbake.conf中的 ${PN}-dev
,定义如下
FILES:${PN}-dev = "${includedir} ${FILES_SOLIBSDEV} ${libdir}/*.la \${libdir}/*.o ${libdir}/pkgconfig ${datadir}/pkgconfig \${datadir}/aclocal ${base_libdir}/*.o \${libdir}/${BPN}/*.la ${base_libdir}/*.la \${libdir}/cmake ${datadir}/cmake"
此列表中的路径必须是从目标根文件系统角度的绝对路径,并且不能引用变量 D 或任何与 WORKDIR 相关的变量。一个正确的示例是:
${sysconfdir}/foo.conf
[!NOTE]
软件包的文件列表是使用覆盖语法定义的,通过在 FILES 和软件包名称之间用冒号(:)分隔。
一个给定的文件只能属于一个软件包。通过从 PACKAGES 中最左边的软件包迭代到最右边的软件包,与相应 FILES 定义中任何模式匹配的每个文件都会被包含在该软件包中。
[!NOTE]
注意,要找出哪个软件包安装了某个文件,可以使用 oe-pkgdata-util 命令行实用程序:
$ oe-pkgdata-util find-path '/etc/fstab'
base-files: /etc/fstab`
有关 oe-pkgdata-util 实用程序的更多信息,请参阅《Yocto 项目开发任务手册》中 “使用 oe-pkgdata-util 查看软件包信息” 部分。
要添加${PN}
配方的自定义包变体,命名为${PN}-extra
(名称可以任意),可以将其添加到PACKAGE_BEFORE_PN变量:
PACKAGE_BEFORE_PN += "${PN}-extra"
或者,也可以使用前置操作符(=+)将自定义软件包添加到 PACKAGES 变量中:
PACKAGES =+ "${PN}-extra"
根据正在创建的软件包类型(RPM、DEB 或 IPK),do_package_write_* 任务会创建实际的软件包,并将它们放置在软件包馈送区域,即 ${TMPDIR}/deploy
。有关构建过程中该部分的更多详细信息,请参阅 “Package Feeds” 部分。
``
[!NOTE]
不存在直接从deploy/*
目录创建馈送的支持。创建此类馈送通常需要某种馈送维护机制,该机制会将新软件包上传到官方软件包馈送(例如 Ångström 发行版)中。此功能高度依赖于特定的发行版,因此不会默认提供。
4.3.5.5 镜像生成
一旦软件包被拆分并存储在软件包源(Package Feeds)区域中,构建系统会使用 BitBake 来生成根文件系统镜像:
镜像生成过程包含多个阶段,并且依赖于多个任务和变量。do_rootfs 任务会为镜像创建根文件系统(文件和目录结构)。此任务会使用几个关键变量来帮助确定实际要安装的软件包列表:
-
IMAGE_INSTALL:列出要从软件包源区域安装的基本软件包集。
-
PACKAGE_EXCLUDE: 指定不应安装到镜像中的软件包。
-
IMAGE_FEATURES: 指定要包含在镜像中的功能。这些功能大多映射到要安装的其他软件包。
-
PACKAGE_CLASSES: 指定要使用的软件包后端(例如 RPM、DEB 或 IPK),从而帮助确定在软件包源区域中查找软件包的位置。
-
IMAGE_LINGUAS: 确定要安装额外语言支持软件包的语言。
-
PACKAGE_INSTALL: 传递给软件包管理器以安装到镜像中的最终软件包列表。
在 IMAGE_ROOTFS 指向正在构建的文件系统位置,并且 PACKAGE_INSTALL 变量提供要安装的最终软件包列表的情况下,根文件系统得以创建。
无论目标是否启用软件包管理,软件包的安装都由软件包管理器(例如 dnf/rpm、opkg 或 apt/dpkg)控制。在该过程结束时,如果目标未启用软件包管理,则会从根文件系统中删除软件包管理器的数据文件。作为软件包安装最后阶段的一部分,软件包中的安装后脚本将会运行。在构建主机上未能运行的任何脚本,会在目标系统首次启动时在目标上运行。如果使用的是只读根文件系统,则所有安装后脚本必须在构建主机上的软件包安装阶段成功运行,因为目标上的根文件系统是只读的。
do_rootfs 任务的最后阶段负责后期处理。后期处理包括创建清单文件和进行优化。
清单文件(.manifest)与根文件系统镜像位于同一目录中。该文件逐行列出已安装的软件包。例如,清单文件对 testimage 类很有用,可用于确定是否运行特定测试。有关更多信息,请参见 IMAGE_MANIFEST 变量。
在整个镜像上运行的优化过程包括 mklibs 以及由 ROOTFS_POSTPROCESS_COMMAND 变量定义的任何其他后期处理命令。mklibs 过程会优化库的大小。
在根文件系统构建完成后,通过 do_image 任务开始对镜像进行处理。构建系统会运行由 IMAGE_PREPROCESS_COMMAND 变量定义的任何预处理命令。此变量指定在构建系统创建最终镜像输出文件之前要调用的函数列表。
构建系统会根据 IMAGE_FSTYPES 变量中指定的镜像类型,根据需要动态创建 do_image_* 任务。该过程会将所有内容转换为一个或一组镜像文件,并且可以压缩根文件系统镜像以减小镜像的总体大小。根文件系统使用的格式取决于 IMAGE_FSTYPES 变量。是否压缩则取决于这些格式是否支持压缩。
例如,在创建特定镜像类型时,动态创建的任务将采用以下形式:
do_image_type
因此,如果 IMAGE_FSTYPES 指定的类型为 ext4,则动态生成的任务将如下所示:
do_image_ext4
镜像创建中涉及的最后一个任务是 do_image_complete 任务。此任务通过应用由 IMAGE_POSTPROCESS_COMMAND 变量定义的任何镜像后期处理来完成镜像的构建。该变量指定在构建系统创建最终镜像输出文件后要调用的函数列表。
[!NOTE]
整个镜像生成过程是在 Pseudo 下运行的。在 Pseudo 下运行可确保根文件系统中的文件具有正确的所有权。
4.3.5.6 SDK 生成
OpenEmbedded 构建系统使用 BitBake 为标准 SDK 和可扩展 SDK(eSDK)生成软件开发工具包安装脚本:
[!NOTE]
有关交叉开发工具链生成的更多信息,请参阅 “Cross-Development Toolchain Generation” 部分。有关使用 do_populate_sdk 任务构建交叉开发工具链的优势,请参阅《Yocto 项目应用开发和可扩展软件开发工具包(eSDK)手册》中的 “Building an SDK Installer” 部分。
与镜像生成类似,SDK 脚本过程也包含多个阶段,并且依赖许多变量。do_populate_sdk 和 do_populate_sdk_ext 任务使用这些关键变量来确定实际要安装的软件包列表。有关图中列出的变量的信息,请参阅 “Application Development SDK” 部分。
do_populate_sdk 任务负责创建标准 SDK,它处理两个部分:目标部分和主机部分。目标部分是为目标硬件构建的,包括库和头文件。主机部分是 SDK 在 SDKMACHINE 上运行的部分。
do_populate_sdk_ext 任务负责创建可扩展 SDK,它对主机和目标部分的处理方式与标准 SDK 的对应任务有所不同。对于可扩展 SDK,该任务封装了构建系统,其中包含 SDK 所需的所有内容(主机和目标)。
无论构建哪种类型的 SDK,这些任务在完成后都会进行一些清理工作,然后创建交叉开发环境设置脚本和所需的配置文件。最终输出的是交叉开发工具链安装脚本(.sh
文件),其中包含环境设置脚本。
4.3.5.7 标记文件和任务的重新运行
对于每个成功完成的任务,BitBake 会在STAMPS_DIR
目录中写入一个标记文件。标记文件的文件名开头由STAMP
变量决定,结尾由任务名称和当前输入校验和组成。
[!NOTE]
此命名方案假定 BB_SIGNATURE_HANDLER 为 “OEBasicHash”,在当前的 OpenEmbedded 中几乎总是这种情况。
为了确定某个任务是否需要重新运行,BitBake 会检查该任务是否存在具有匹配输入校验和的标记文件。在这种情况下,任务的输出被认为是存在且仍然有效的。否则,该任务将被重新运行 。
[!NOTE]
标记机制比 “场景设置任务和共享状态” 部分中描述的共享状态(sstate)缓存机制更通用。BitBake 会避免重新运行任何具有有效标记文件的任务,而不仅仅是那些可以通过 sstate 缓存加速的任务。
然而,应该意识到标记文件仅作为已完成某些工作的标记,这些文件不会记录任务输出。实际的任务输出通常位于TMPDIR
中的某个位置(例如,在某些配方的WORKDIR
中)。sstate 缓存机制增加了一种缓存任务输出的方式,以便在构建机器之间共享。
由于STAMPS_DIR
通常是TMPDIR
的子目录,删除TMPDIR
也会删除STAMPS_DIR
,这意味着任务将被正确地重新运行以重新填充TMPDIR
。
如果希望某个任务始终被视为 “过时”,可以使用nostamp
变量标志来标记它。如果其他某个任务依赖于这样的任务,那么该任务也将始终被视为过时,这可能并非你所期望的。
有关如何查看任务签名信息的详细信息,请参阅《Yocto 项目开发任务手册》中的 “查看任务变量依赖关系” 部分。
4.3.5.8 场景设置任务和共享状态
到目前为止,对任务的描述都假设 BitBake 需要构建所有内容,且不存在可用的预构建对象。如果有预构建对象可用,BitBake 确实支持跳过某些任务。这些对象通常以共享状态(sstate)缓存的形式提供。
[!NOTE]
有关影响 sstate 的变量的信息,请参阅 SSTATE_DIR 和 SSTATE_MIRRORS 变量。
场景设置任务(即 do_taskname_setscene)的概念是,BitBake 可以直接跳到最终结果,根据需要将一组文件放置到特定位置,而无需实际构建。在某些情况下,场景设置任务变体是有意义的(例如在 do_package_write_* 任务中生成软件包文件)。而在其他情况下,它可能没有意义(例如 do_patch 任务或 do_unpack 任务),因为所涉及的工作与底层任务相当或更多。
在构建系统中,具有 setscene 变体的常见任务包括 do_package、do_package_write_* 、do_deploy、do_packagedata 和 do_populate_sysroot。 请注意,这些任务代表了大多数输出为最终结果的任务。
构建系统了解这些任务与其他前置任务之间的关系。例如,如果 BitBake 对某个内容运行 do_populate_sysroot_setscene,那么运行 do_fetch、do_unpack、do_patch、do_configure、do_compile 和 do_install 任务就没有意义了。但是,如果需要运行 do_package ,则 BitBake 需要运行上述其他任务。
如果所有内容都能从共享状态缓存(sstate cache)中获取,情况就会变得更加复杂,因为有些对象根本就不需要。例如,如果没有任何内容需要编译或打补丁,就不需要编译器或像 quilt 这样的本地工具。如果 do_package_write_* 相关的软件包可从共享状态缓存中获取,BitBake 就不再需要 do_package 任务的数据。
为了处理所有这些复杂情况,BitBake 分两个阶段运行。第一阶段是 “场景设置” 阶段。在此阶段,BitBake 首先检查 sstate 缓存中是否有计划构建的目标。BitBake 会进行快速检查,查看对象是否存在,而不是进行完整的下载。如果没有找到任何对象,则第二阶段(即场景设置阶段)完成,主构建过程继续进行。
如果在 sstate 缓存中找到了对象,构建系统会从用户指定的最终目标反向工作。例如,如果正在构建一个镜像,构建系统首先会查找该镜像所需的软件包以及构建镜像所需的工具。如果这些都可用,就不需要编译器了。因此,编译器甚至不会被下载。如果发现某个对象不可用,或者下载或场景设置任务失败,构建系统会尝试从缓存中安装依赖项,例如编译器。
sstate 缓存中对象的可用性由 BB_HASHCHECK_FUNCTION 变量指定的函数处理,该函数返回可用对象的列表。BB_SETSCENE_DEPVALID 变量指定的函数用于确定是否需要跟踪给定的依赖项,以及对于任何给定的关系是否需要传递该函数。该函数返回 True 或 False 值。
4.3.6 镜像
构建系统生成的镜像,是根文件系统的压缩形式,可直接在目标设备上启动。从通用工作流程图中可以看到,BitBake 的部分输出就是镜像。本节将更深入地介绍这些输出:
[!NOTE]
有关 Yocto Project 提供的示例镜像列表,请参阅《Yocto 项目参考手册》中的 “镜像” 章节。
构建过程将镜像输出到构建目录下的 tmp/deploy/images/machine/
文件夹中,如图所示。该文件夹包含所有预期会加载到目标设备上的文件。DEPLOY_DIR 变量指向 deploy 目录,而 DEPLOY_DIR_IMAGE 变量则指向包含当前配置镜像的相应目录。
-
kernel-image:内核二进制文件。KERNEL_IMAGETYPE 变量决定了内核镜像文件的命名方案。根据该变量的设置,文件名可能会以各种不同的字符串开头。
deploy/images/machine
目录中可能包含针对该机器的多个镜像文件。 -
root-filesystem-image:目标设备的根文件系统(例如,
_.ext3
或_.bz2
文件)。IMAGE_FSTYPES 变量决定了根文件系统镜像的类型。deploy/images/machine
目录中可能包含针对该机器的多个根文件系统。 -
kernel-modules:包含为内核构建的所有模块的 tar 包。出于传统原因保留了内核模块 tar 包,可以通过将 MODULE_TARBALL_DEPLOY 变量设置为 “0” 来禁止生成。
deploy/images/machine
目录中可能包含针对该机器的多个内核模块 tar 包。 -
bootloaders:如果目标机器适用,则会有支持该镜像的引导加载程序。
deploy/images/machine
目录中可能包含针对该机器的多个引导加载程序。 -
symlinks:
deploy/images/machine
文件夹包含一个符号链接,它指向每个机器最近构建的文件。这些链接对于需要获取每个文件最新版本的外部脚本可能很有用。
4.3.7 应用程序开发 SDK
在通用工作流程图中,标记为 “应用开发 SDK” 的输出代表一个软件开发工具包(SDK)。SDK 的生成过程会因构建的是可扩展 SDK(例如使用bitbake -c populate_sdk_ext imagename
命令)还是标准 SDK(例如使用bitbake -c populate_sdk imagename
命令)而有所不同。本节将更详细地介绍这一输出:
这种输出的具体形式是一组文件,其中包括一个自解压的 SDK 安装程序(*.sh
)、主机和目标清单文件,以及用于 SDK 测试的文件。运行 SDK 安装程序文件时,它会安装 SDK。SDK 由一个交叉开发工具链、一组库和头文件,以及一个 SDK 环境设置脚本组成。运行这个安装程序基本上就设置好了交叉开发环境。可以把交叉工具链看作是 “主机” 部分,因为它在 SDK 机器上运行;可以把库和头文件看作是 “目标” 部分,因为它们是为目标硬件构建的。添加环境设置脚本是为了在使用这些工具之前能够初始化环境。
[!NOTE]
Yocto Project 支持多种设置交叉开发环境的方法。这些方法包括下载预构建的 SDK 安装程序,或者构建并安装自己的 SDK 安装程序。
有关跨开发工具链的背景信息,请参阅 Yocto Project 开发环境中,请参阅 “跨开发工具链生成” 部分。
有关设置跨开发环境的信息,请参阅 Yocto 项目应用程序开发和可扩展软件开发工具包 (eSDK) 手册。
SDK 的所有输出文件都被写入到构建目录下的 deploy/sdk 文件夹中,如前面的图所示。根据 SDK 的类型,有几个变量可用于配置这些文件。与可扩展 SDK 相关的变量如下:
-
DEPLOY_DIR:指向 deploy 目录。
-
SDK_EXT_TYPE:控制是否将共享状态工件复制到可扩展 SDK 中。默认情况下,所有必需的共享状态工件都会被复制到 SDK 中。
-
SDK_INCLUDE_PKGDATA:指定是否在 “world” 目标的所有配方中,将打包数据包含在可扩展 SDK 中。
-
SDK_INCLUDE_TOOLCHAIN: 指定在构建可扩展 SDK 时是否包含工具链。
-
ESDK_LOCALCONF_ALLOW: 一个变量列表,允许从构建系统配置传递到可扩展 SDK 配置中。
-
ESDK_LOCALCONF_REMOVE: 一个变量列表,不允许从构建系统配置传递到可扩展 SDK 配置中。
-
ESDK_CLASS_INHERIT_DISABLE: 一个类列表,用于在可扩展 SDK 配置中全局删除 INHERIT 值中的类。
下面列出的是与标准 SDK 相关的变量:
-
DEPLOY_DIR:指向
deploy
目录。 -
SDKMACHINE:指定运行交叉开发工具以创建目标硬件软件包的机器架构。
-
SDKIMAGE_FEATURES: 列出要包含在 SDK “目标” 部分的功能。
-
TOOLCHAIN_HOST_TASK: 列出构成 SDK 主机部分(即在 SDKMACHINE 上运行的部分)的软件包。当使用
bitbake -c populate_sdk imagename
命令创建 SDK 时,会应用一组默认软件包。该变量允许添加更多软件包。 -
TOOLCHAIN_TARGET_TASK: 列出构成 SDK 目标部分(即为目标硬件构建的部分)的软件包。
-
SDKPATHINSTALL:定义安装脚本提供的默认 SDK 安装路径。
-
SDK_HOST_MANIFEST: 列出构成 SDK 主机部分的所有已安装软件包。该变量在可扩展 SDK 开发中也起次要作用,但主要用于标准 SDK。
-
SDK_TARGET_MANIFEST: 列出构成 SDK 目标部分的所有已安装软件包。该变量在可扩展 SDK 开发中也起次要作用,但主要用于标准 SDK。