Assimilating Packaging Support
本章介绍了解 Poky 和 BitBake 打包相关方面的关键概念。我们将了解支持的二进制包格式、共享状态缓存、包版本控制组件、如何设置和使用二进制包馈以支持我们的开发流程等。
This chapter presents the key concepts for understanding the aspects of Poky and BitBake related to packaging. We will learn about the supported binary package formats, shared state cache, package versioning components, how to set up and use binary package feeds to support our development process, and more.
1, Using supported package formats
从 Yocto 项目的角度来看,一个配方可以生成一个或多个输出包。软件包将一组文件和元数据封装起来,以便将来使用。它们可以安装到一个或多个镜像中,也可以部署以供日后使用。
From a Yocto Project perspective, a recipe may generate one or more output packages. A package wraps a set of files and metadata in a way that makes them available in the future. They can be installed into one or more images or deployed for later use.
软件包对 Poky 至关重要,因为它们能让构建系统生成不同类型的工件,如映像和工具链。
Packages are critical to Poky, as they enable the build system to produce diverse types of artifacts, such as images and toolchains.
List of supported package formats
目前,BitBake 支持四种不同的软件包格式:
* Red Hat Package Manager (RPM): 最初名为 Red Hat 软件包管理器,但自从被其他几个 Linux 发行版采用后,现在被称为 RPM 软件包格式,这是一种在 SuSE、OpenSuSE、Red Hat、Fedora 和 CentOS 等 Linux 发行版中使用的流行格式。
* Debian 软件包管理器(DEB): 这是在 Debian 和其他几个基于 Debian 的发行版中广泛使用的格式,其中 Ubuntu Linux 和 Linux Mint 最广为人知。
* Itsy 软件包管理系统(IPK): 这是一种为嵌入式设备设计的轻量级软件包管理系统,与 Debian 的软件包格式相似。支持 IPK 格式的 opkg 软件包管理器在多个发行版中使用,如 OpenEmbedded Core、OpenWRT 和 Poky。
* Tar: 源于磁带存档,是一种广泛使用的 tarball 文件类型,用于将多个文件合并为一个文件。
Currently, BitBake supports four different package formats:
*
Red Hat Package Manager (RPM): Originally named Red Hat Package Manager but now known as the RPM package format since its adoption by several other Linux distributions, this is a popular format in use in Linux distributions such as SuSE, OpenSuSE, Red Hat, Fedora, and CentOS.
*
Debian Package Manager (DEB): This is a widespread format used in Debian and several other Debian-based distributions – Ubuntu Linux and Linux Mint are the most widely known.
*
Itsy Package Management System (IPK): This was a lightweight package management system designed for embedded devices that resembled Debian’s package format. The
opkg package manager, which supports the IPK format, is used in several distributions such as OpenEmbedded Core, OpenWRT, and Poky.
*
Tar: This is derived from the Tape Archive, a widely used
tarball file type used to group several files into just a single file.
Choosing a package format
对格式的支持是通过一组类(即 package_rpm、package_deb 和 package_ipk)来实现的。我们可以使用 PACKAGE_CLASSES 变量选择一种或多种格式,如下例所示:
The support for formats is provided using a set of classes (i.e.,
package_rpm,
package_deb, and
package_ipk). We can select one or more formats using the
PACKAGE_CLASSES variable, as shown in the following example:
[ Figure 7.1 – The variable used to configure which package format to use ]
你可以在 build/conf/local.conf 文件中配置一种或多种软件包格式。
You can configure one or more package formats – for example, in the
build/conf/local.conf file.
Tip
PACKAGE_CLASSES 中的第一种软件包格式是用于生成镜像的格式。
The first package format in
PACKAGE_CLASSES is the one used for image generation.
Poky 默认使用 RPM 软件包格式,它使用 DNF 软件包管理器。不过,格式选择取决于多个因素,如特定于软件包格式的功
能、内存和资源使用情况。OpenEmbedded Core 默认使用 IPK 和 opkg 作为软件包管理器,因为它占用的内存和资源更少。
Poky defaults to the RPM package format, which uses the DNF package manager. However, the format choice depends on several factors, such as package format-specific features, memory, and resource usage. OpenEmbedded Core defaults to the IPK and opkg as the package manager, as it offers a smaller memory and resource usage footprint.
另一方面,熟悉基于 Debian 系统的用户可能更倾向于为其产品使用 APT 和 DEB 软件包格式。
On the other hand, users familiar with Debian-based systems may prefer to use the APT and DEB package formats for their products.
2, Running code during package installation
软件包可以使用脚本作为安装和删除程序的一部分。包含的脚本定义如下:
* preinst: 在解压缩软件包之前执行。如果软件包有服务,则必须在安装或升级时停止服务。
* postinst: 解压缩后,通常会完成软件包所需的配置。许多 postinst 脚本会在安装或升级后执行启动或重启服务所需的命令。
* prerm: 在删除与软件包相关的文件之前,它通常会停止与软件包相关的守护进程。
* postrm: 通常会修改软件包创建的链接或其他文件。
Packages can use scripts as part of their installation and removal process. The included scripts are defined as follows:
*
preinst: This executes before unpacking the package. If the package has services, it must stop them for installation or upgrade.
*
postinst: After unpacking, this typically completes any required configuration of the package. Many
postinst scripts execute any command necessary to start or restart a service after installation or upgrade.
*
prerm: It usually stops any daemon associated with a package before removing files associated with the package.
*
postrm: This commonly modifies links or other files created by the package.
preinst 和 prerm 脚本针对复杂的用例,例如更新软件包时的数据迁移。在 Yocto 项目中,postinst 和 postrm 还负责停止和启动 systemd 或 sysvinit 服务。当我们使用 systemd 和 update-rc.d 类时,会提供一个默认脚本。可以对其进行定制,以包括任何特殊情况。
The
preinst and
prerm scripts target complex use cases, such as data migration when updating packages. In the Yocto Project case,
postinst and
postrm are also responsible for stopping and starting the systemd or sysvinit services. A default script is provided when we use the
systemd and
update-rc.d classes. It can be customized to include any particular case.
软件包安装后 (postinst) 脚本在创建根文件系统时运行。如果脚本返回成功值,则软件包被标记为已安装。要为软件包添加 postinst 脚本,我们可以使用下面的方法:
The post-package installation (
postinst) scripts are run during the
root filesystem creation. The package is marked as installed if the script returns a success value. To add a
postinst script for a package, we can use the following:
[ Figure 7.2 – An example of the pkg_postinst script
]
有时,我们需要确保 postinst 在目标设备内部运行。这可以使用 postinst_ontarget 变体来实现,例如下面的命令:
Sometimes, we need to ensure that
postinst runs inside the target device itself. This can be done using the
postinst_ontarget variant, such as the following:
[ Figure 7.3 – An example of the pkg_postinst_ontarget script ]
Tip
我们可以使用 PN 变量来自动扩展配方的软件包名称,而不是使用软件包名称本身。
Instead of using the package name itself, we can use the PN variable, which automatically expands the package name of the recipe.
在 IMAGE_FEATURES 中生成只读 rootfs 的映像时,所有安装后脚本都必须成功。由于不可能在只读 rootfs 中写入内容,因此必须在构建时进行检查。这可确保我们在构建镜像时发现问题,而不是在目标设备的初始启动操作期间。如果需要在目标设备中运行任何脚本,do_rootfs 任务就会失败。
All post-installation scripts must succeed when we generate an image with
read-only-rootfs in
IMAGE_FEATURES. Because it is impossible to write in a read-only
rootfs, the check must occur during build time. It ensures that we identify the problem while building the image, rather than during the initial boot operation in the target device. If there is a requirement to run any script inside the target device, the
do_rootfs task fails.
Tip
最终,将整个映像作为只读映像是行不通的。例如,某些项目可能需要持久化某些数据,甚至允许某些应用程序写入易失性目录。此类用例不在本书讨论范围之内。不过,你可能会在《Yocto 项目参考手册》中找到一些关于 overlayfs (
5 Classes — The Yocto Project ® 4.0.4 documentation) 和 overlayfs-etc (
5 Classes — The Yocto Project ® 4.0.4 documentation) 类的有用信息。
Eventually, using a whole image as read-only is not an option. For example, some projects may need to persist some data or even allow some applications to write to a volatile directory. Such use cases are outside the scope of this book. However, you might find some helpful information in the Yocto Project Reference Manual for the
overlayfs
(
5 Classes — The Yocto Project ® 4.0.4 documentation
) and
overlayfs-etc
(
5 Classes — The Yocto Project ® 4.0.4 documentation
) classes.
在创建安装后脚本时,一个常见的疏忽是在绝对路径前缺少 D 变量。D 有两个特性:
One common oversight when creating post-installation scripts is the lack of the
D variable in front of absolute paths.
D has two traits:
* 在生成 rootfs 时,D 被设置为工作目录的根目录
* 在设备内部,D 为空
* During rootfs generation, D is set to the root of the working directory
* Inside the device, D is empty
因此,这可以确保路径在主机和目标机环境中都有效。例如,请看下面的代码
Consequently, this ensures that paths are valid in both host and target environments. For example, consider the following code:
[ Figure 7.4 – Sample source code using the D variable ]
在图 7.4 中的示例中,touch命令使用了 D 变量,因此它可以根据 D 变量的值进行通用操作。
In the example in Figure 7.4, the
touch command uses the D variable, so it works generically depending on its value.
另一个常见错误是试图运行特定于或依赖于目标架构的进程。在这种情况下,最简单的解决办法是将脚本的执行推迟到目标(使用 pkg_postinst_ontarget)。不过,如前所述,这样做无法使用只读文件系统。
Another common mistake is attempting to run processes specific to or dependent on the target architecture. The easiest solution, in this case, is to postpone the script execution to the target (using
pkg_postinst_ontarget). However, as mentioned before, this prevents the use of read-only filesystems.
3, Understanding shared state cache
Poky 的默认行为是从头开始构建所有内容,除非 BitBake 认为某个配方不需要重建。一切从头开始的主要好处是,结果是全新的,不会有以前的数据导致问题的风险。不过,重建所有内容需要计算时间和资源。
The default behavior of Poky is to build everything from scratch unless BitBake determines that a recipe does not need to be rebuilt. The main advantage of building everything from scratch is that the result is fresh, and there is no risk of previous data causing problems. However, rebuilding everything requires computational time and resources.
确定是否必须重建配方的策略非常复杂。BitBake 会尽可能多地跟踪构建过程中使用的每个任务、变量和代码的信息。然后,BitBake 会为每个任务使用的信息生成校验和,包括来自其他任务的依赖关系。总之,BitBake 会递归跟踪已使用的变量、任务源代码、配方及其依赖关系。
The strategy to determine whether a recipe must be rebuilt is complex. BitBake tries to track as much information as possible about every task, variable, and piece of code used in the build process. BitBake then generates a checksum for the information used by every task, including dependencies from other tasks. In summary, BitBake recursively tracks used variables, task source code, and dependencies for the recipes and their dependencies.
Poky 利用 BitBake 提供的所有这些信息,将这些任务的快照存储为一组打包数据,并在名为共享状态缓存(
sstate-cache)的缓存中生成。该缓存将每个任务输出的内容打包成包,存储在 SSTATE_DIR 目录中。每当 BitBake 准备运行一个任务时,它会首先检查是否存在与所需计算校验和相匹配的 sstate-cache 包。如果软件包存在,BitBake 就会使用预编译的软件包。
Poky uses all this information provided by BitBake to store snapshots of those tasks as a set of packaged data, generated in a cache called the shared state cache (
sstate-cache
). This cache wraps the contents of each task output in packages stored in the
SSTATE_DIR
directory. Whenever BitBake prepares to run a task, it first checks the existence of a sstate-cache package that matches the required computed checksum. If the package is present, BitBake uses the prebuilt package.
整个共享状态机制包含相当复杂的代码,前面的解释将其简化。如需详细说明,建议查阅《Yocto 项目概述与概念手册》(
4 Yocto Project Concepts — The Yocto Project ® 4.0.4 documentation)中的共享状态缓存部分。
The whole shared state mechanism encompasses quite complex code, and the previous explanation simplifies it. For a detailed description, it is advised that you go through the Shared State Cache section of the Yocto Project Overview and Concepts Manual (
4 Yocto Project Concepts — The Yocto Project ® 4.0.4 documentation ).
在多次构建过程中使用 Poky 时,我们必须记住需要不时清理 sstate-cache,因为它在每次构建后都会不断增长。有一种直接的方法可以清理它。在 Poky 目录中使用以下命令:
When using Poky for several builds, we must remember that
sstate-cache needs cleaning from time to time, since it keeps growing after every build. There is a straightforward way of cleaning it. Use the following command from the
poky directory:
[ Figure 7.5 – The command line to remove a duplicated Shared State Cache ]
Tip
当我们需要从头开始重建时,可以执行以下任一操作:
* 删除 build/tmp,以便使用 sstate-cache 加快构建速度
* 同时移除 build/tmp 和 sstate-cache,这样就不会在构建过程中重复使用缓存了
When we need to rebuild from scratch, we can do either of the following:
* Remove
build/tmp so that we can use
sstate-cache to speed up the build
* Remove both
build/tmp and
sstate-cache so that no cache is reused during the build
4,Explaining package versioning
软件包版本管理用于区分生命周期中不同阶段的同一软件包。从 Poky 的角度来看,它也是 BitBake 生成校验和以验证任务是否必须重建的等式的一部分。
Package versioning is used to differentiate the same package in distinct stages of its life cycle. From Poky’s perspective, it is also used as part of the equation that generates the checksum used by BitBake to verify whether a task must be rebuilt.
软件包版本(也称为
PV)在我们选择构建哪个配方时起着主导作用。正如第 5 章 “掌握 BitBake 工具 ”中所述,除非有不同的明确偏好,否则 Poky 的默认行为总是优先选择最新的配方版本。例如,假设我们有两个版本的 myrecipe 配方:
The package version, also known as
PV, plays a leading role when we select which recipe to build. The default behavior of Poky is always to prefer the newest recipe version unless there is a different explicit preference, as discussed in Chapter 5, Grasping the BitBake Tool. For example, let’s suppose that we have two versions of the
myrecipe recipe:
* myrecipe_1.0.bb
* myrecipe_1.1.bb
BitBake 默认以 1.1 版本构建配方。在配方中,我们可能还有其他变量,与 PV 变量一起组成软件包版本。它们是软件包的时间(PE)和软件包的修订版本(PR)。
BitBake, by default, builds the recipe with version
1.1. Inside the recipe, we may have other variables that compose package versioning with the
PV variable. These are the package epoch, known as
PE, and the package revision, known as
PR.
这些变量通常遵循这种模式:
Those variables normally follow this pattern:
[ Figure 7.6 – A complete versioning pattern ]
PE 变量的默认值为零。它在软件包版本模式发生变化时使用,打破了通常排序的可能性。在软件包版本中,PE 会作为前缀,在需要时强制使用一个更高的数字。
The PE variable has a default value of zero. It is used when the package version schema is changed, breaking the possibility of usual ordering. PE is prepended in the package version, forcing a higher number when needed.
例如,假设一个软件包使用日期来组成 PV 变量,如 20220101,而版本模式发生变化,发布了 1.0 版本。无法确定 1.0 版本是否高于 20220101 版本。因此,使用 PE =“1 ”来更改配方时间,迫使 1.0 版本高于 20220101,因为 1:1.0 大于 0:20220101。
For example, suppose a package uses the date to compose
PV variables such as
20220101, and there is a version schema change to release the
1.0 version. It is impossible to determine whether version
1.0 is higher than version
20220101. So,
PE = "1" is used to change the recipe epoch, forcing version 1.0 to be higher than
20220101, since
1:1.0 is greater than
0:20220101.
PR 变量的默认值为 r0,是软件包版本控制的一部分。更新后,BitBake 会强制重建特定配方的所有任务。我们可以在配方元数据中手动更新它,以强制重建我们知道需要的任务。尽管如此,它仍然很脆弱,因为它依赖于人与人之间的互动和知识。BitBake 使用任务校验和来控制需要重建的内容。只有在任务校验和没有变化的极少数情况下,才会使用手动 PR 增量。
The
PR variable has a default value of
r0 and is a part of package versioning. When it is updated, it forces BitBake to rebuild all tasks of a specific recipe. We can update it manually in the recipe metadata to force a rebuild we know is needed. Still, it is fragile because it relies on human interaction and knowledge. BitBake uses task checksums to control what needs to be rebuilt. The manual
PR increment is only used in rare cases when the task checksum does not change.
5,Specifying runtime package dependencies
大多数配方的结果都是由软件包管理器管理的软件包。正如我们在前面几节所看到的,它需要所有这些软件包的信息以及它们之间的关系。例如,一个软件包可能依赖于另一个软件包,也可能与另一个软件包冲突。
The results of most recipes are packages managed by the package manager. As we saw in the previous sections, it requires information about all those packages and how they relate. For example, a package may depend on or conflict with another.
在多个软件包关系中都存在制约因素;不过,这些制约因素是特定于软件包格式的,因此 BitBake 有特定的元数据来抽象这些制约因素。
Constraints exist within multiple package relationships; however, those constraints are package format-specific, so BitBake has specific metadata to abstract those constraints.
下面列出了最常用的软件包运行时限制:
* RDEPENDS:运行时必须可用的软件包列表,以及定义它的软件包。
* RPROVIDES: 这是软件包提供的符号名称列表。默认情况下,软件包总是将软件包名称作为符号名称。它也可以包括该软件包提供的其他符号名称。
* RCONFLICTS: 这是已知与软件包冲突的软件包列表。最终映像不得包含冲突的软件包。
* RREPLACES: 这是软件包可替换的符号名称列表。
Here is a list of the most used package runtime constraints:
* RDEPENDS: The list of packages must be available at runtime, along with the package that defines it.
* RPROVIDES: This is the list of symbolic names a package provides. By default, a package always includes the package name as a symbolic name. It can also include alternative symbolic names provided by that package.
* RCONFLICTS: This is the list of packages known to conflict with the package. The final image must not include conflicting packages.
* RREPLACES: This is a list of symbolic names that the package can replace.
来自 meta/recipes-devtools/python/python3-dbus_1.2.18.bb 的完整配方如下:
A full recipe, from
meta/recipes-devtools/python/python3-dbus_1.2.18.bb, is as follows:
[ Figure 7.7 – An example of how to use RDEPENDS ]
图 7.6 中的配方显示,在第 21 行,python3-dbus 软件包的运行时依赖关系列表中包含了多个 Python 模块。
The recipe from Figure 7.6 shows that the
python3-dbus package has a list of runtime dependencies on several Python modules, on line 21.
6, Using packages to generate a rootfs image
Poky 最常见的用途之一是生成 rootfs 映像。rootfs 映像应被视为目标机的一个随时可用的根文件系统。镜像可以由一个或多个文件系统组成。它还可能包含生成过程中可用的其他工件,如 Linux 内核、设备树和引导加载器二进制文件。生成映像的过程由几个步骤组成。其最常见的用途如下:
One of the most common uses of Poky is the
rootfs image generation. The
rootfs image should be seen as a ready-to-use root filesystem for a target. The image can be composed of one or more filesystems. It may include other artifacts available during its generation, such as the Linux kernel, the device tree, and bootloader binaries. The process of generating the image is composed of several steps. Its most common uses are as follows:
1. 生成 rootfs 目录
2. 创建所需文件
3. 根据具体要求封装最终文件系统(它可能是一个包含多个分区和内容的磁盘文件)
4. 最后,酌情压缩
1. Generating the rootfs directory
2. Creating the required files
3. Wrapping the final filesystem according to the specific requirements (it may be a disk file with several partitions and contents)
4. Finally, compressing it, if applicable
do_rootfs 的子任务会执行所有这些步骤。rootfs 是一个安装了所需软件包的目录,之后会应用所需的调整。这些调整会对 rootfs 的内容进行细微调整,例如,在构建开发映像时,rootfs 会被调整为允许我们以 root 身份登录,而无需密码。
The sub-tasks of
do_rootfs perform all these steps.
rootfs is a directory with the desired packages installed, with the required tweaks applied afterward. The tweaks make minor adjustments to the
rootfs contents – for example, when building a development image,
rootfs is adjusted to allow us to log in as
root without a password.
要安装到 rootfs 中的软件包列表由 IMAGE_INSTALL 列出的软件包和 IMAGE_FEATURES 包含的软件包联合定义;第 12 章 “创建自定义层 ”将详细介绍镜像的自定义功能。每个映像功能都可以包含额外的安装包,例如,dev-pkgs 用于安装开发库和 rootfs 中列出的所有软件包的头文件。
The list of packages to be installed into
rootfs is defined by a union of packages listed by
IMAGE_INSTALL and the packages included with
IMAGE_FEATURES; image customization is detailed in Chapter 12, Creating Custom Layers. Each image feature can include extra packages for installation – for example,
dev-pkgs, which installs development libraries and headers of all packages listed to be installed in rootfs.
要安装的软件包列表现在可以通过 PACKAGE_EXCLUDE 变量进行过滤,该变量列出了不应安装的软件包。PACKAGE_EXCLUDE 中列出的软件包只会被排除在要明确安装的软件包列表之外。
The list of packages to be installed is now filtered by the
PACKAGE_EXCLUDE variable, which lists the packages that should not be installed. The packages listed in
PACKAGE_EXCLUDE are only excluded from the list of packages to be explicitly installed.
有了最终要安装的软件包集,do_rootfs 任务就可以启动解包和配置过程,将每个软件包及其所需的依赖关系导入 rootfs 目录。rootfs 生成过程使用本地软件包源,我们将在下一节介绍。
With the final set of packages to install, the
do_rootfs task can initiate the process of unpacking and configuring each package, and its required dependencies, into the
rootfs directory. The
rootfs generation uses the local package feed, which we will cover in the next section.
在 rootfs 内容解压缩后,必须运行所引用软件包的非目标安装后脚本,以避免在首次启动时运行这些脚本而出错。
With the
rootfs contents unpacked, the non-target post-installation scripts of the referred packages must run to avoid the penalty of running them during the first boot.
现在,目录已准备好生成文件系统。IMAGE_FSTYPES 列出了要生成的文件系统,例如 EXT4 或 UBIFS。
Now, the directory is ready to generate the filesystem.
IMAGE_FSTYPES lists the filesystem to be generated – for example, EXT4 or UBIFS.
do_rootfs 任务完成后,生成的映像文件将放置在 build/tmp/deploy/image/<machine>/ 目录中。创建映像的过程以及 IMAGE_FEATURES 和 IMAGE_FSTYPES 的可能值将在第 12 章 “创建自定义图层 ”中介绍。
After the
do_rootfs task has finished, the generated image file is placed in
build/tmp/deploy/image/<machine>/. The process of creating our image and the possible values for
IMAGE_FEATURES and
IMAGE_FSTYPES are described in Chapter 12, Creating Custom Layers.
7,Package feeds
正如第 5 章 “掌握 BitBake 工具 ”中所讨论的,软件包扮演着至关重要的角色,因为映像和软件开发工具包(SDK)都依赖于它们。事实上,
do_rootfs 在生成这些工件时,会使用本地资源库来获取二进制软件包。这个资源库被称为软件包源(package feed)。
As discussed in Chapter 5, Grasping the BitBake Tool, packages play a vital role, as images and Software Development Kits (SDKs) rely on them. In fact, do_rootfs uses a local repository to fetch binary packages when generating those artifacts. This repository is known as a package feed.
没有理由只将该资源库用于镜像或 SDK 构建步骤。无论是在我们的内部开发环境中,还是在公开场合,远程访问该资源库都有几个合理的理由。其中一些原因如下:
There is no reason for this repository to be used just for the images or SDK build steps. Several valid reasons exist for making this repository remotely accessible, either internally in our development environment or publicly. Some of these reasons are as follows:
* 你可以在开发阶段轻松测试更新的应用程序,而无需重新安装整个系统
* 可以使附加软件包更加灵活,以便将其安装到运行映像中
* 可以在现场更新产品
* You can easily test an updated application during the development stage, without requiring a complete system re-installation
* You can make additional packages more flexible so that they can be installed in a running image
* You can update products in the field
要生成可靠的软件包源,我们必须确保每次软件包变更时,软件包修订版本都有一致的增量。要做到这一点,手动几乎是不可能的,Yocto 项目专门设计了一项 PR 服务来帮助实现这一点。
To produce a solid package feed, we must ensure that we have consistent increments in the package revision every time the package is changed. It is almost impossible to do this manually, and the Yocto Project has a
PR service specifically designed to help with this.
PR 服务是 BitBake 的一部分,每当 BitBake 检测到任务中的校验和发生变化时,它就会在无需人工交互的情况下递增 PR。它会在 PR 中注入 ${PR}.X 格式的后缀。例如,如果我们的 PR = “r34”,在随后的 PR 服务交互后,PR 值会变成 r34.1、r34.2、r34.3,依此类推。PR 服务的使用对于稳固的软件包馈送至关重要,因为它要求版本线性增加。
The PR service, part of BitBake, is used to increment
PR without human interaction every time BitBake detects a checksum change in a task. It injects a suffix in
PR in the
${PR}.X format. For example, if we have
PR = "r34" after subsequent
PR service interactions, the
PR value becomes
r34.1, r34.2, r34.3, and so on. The use of the
PR service is critical for solid package feeds, as it requires the version to increase linearly.
Tip
尽管我们应该使用 PR 服务来实现可靠的软件包版本控制,但这并不排除在特殊情况下手动设置 PR 的需要。
Even though we ought to use the
PR service to have solid package versioning, it does not preclude the need to set
PR manually in exceptional cases.
默认情况下,PR 服务没有启用或运行。我们可以在 BitBake 配置中(例如 build/conf/local.conf 中)添加 PRSERV_HOST 变量,使其在本地运行,如下所示:
By default, the
PR service is not enabled or running. We can enable it to run locally by adding the
PRSERV_HOST variable in the BitBake configuration – for example, in
build/conf/local.conf, as in the following:
[ Figure 7.8 – How to configure a PR service to run locally ]
这种方法适用于在一台计算机上构建软件包源中的每个软件包的情况。BitBake 会在每次构建时启动和停止服务器,并自动增加所需的 PR 值。
This approach is adequate when the build happens on a single computer, which builds every package of the package feed. BitBake starts and stops the server at each build and automatically increases the required
PR values.
对于更复杂的设置,即多台计算机针对一个共享的软件包源工作,我们必须运行一个 PR 服务,供与软件包源相关的所有构建系统使用。在这种情况下,我们需要使用 bitbake-prserv 命令在服务器中启动 PR 服务,如下所示:
For a more complex setup, with multiple computers working against a shared package feed, we must have a single
PR service running, used by all building systems associated with the package feed. In this case, we need to start the PR service in the server using the
bitbake-prserv command, shown as follows:
[ Figure 7.9 – The command line to initiate the PR service server ]
除了手动启动服务外,我们还需要更新每个构建系统的 BitBake 配置文件(例如 build/conf/local.conf),如前所述,该配置文件使用 PRSERV_HOST 变量连接服务器,因此每个系统都指向服务器 IP 和端口。
In addition to manually-starting the service, we need to update the BitBake configuration file (for example,
build/conf/local.conf) of each build system, which connects to a server using the
PRSERV_HOST variable, as described earlier, so that each system points to the server
IP and
port.
Using package feeds
要使用软件包源,需要以下两个组件:
* 服务器提供对软件包的访问
* 客户端访问服务器并下载所需的软件包
To use package feeds, the following two components are required:
* The server provides access to the packages
* The client accesses the server and downloads the required packages
软件包源提供的软件包集由我们构建的配方决定。我们可以创建一个或多个配方并提供它们,也可以创建一组图像来生成所需的软件包。一旦对所提供的软件包感到满意,我们就必须创建软件包源提供的软件包索引。下面的命令可以完成这项工作:
The set of packages offered by the package feed is determined by the recipes we build. We can build one or more recipes and offer them, or build a set of images to generate the desired packages. Once satisfied with the packages offered, we must create the package index provided by the package feeds. The following command performs this:
[ Figure 7.10 – The command line to create the package index ]
这些软件包位于 build/tmp/deploy 目录中。我们必须根据所选的软件包格式选择相应的子目录。Poky 默认使用 RPM,因此我们必须提供 build/tmp/deploy/rpm 目录中的内容。
The packages are available inside the
build/tmp/deploy directory. We must choose the respective sub-directory depending on the package format chosen. Poky uses RPM by default, so we must serve the content of the
build/tmp/deploy/rpm directory.
Tip
确保在编译完所有软件包后运行 bitbake package-index,否则软件包索引将不包含这些软件包。
Make sure to run
bitbake package-index after building all packages; otherwise, the package index will not include them.
软件包索引和软件包必须通过 HTTP 等传输协议提供。我们可以使用任何服务器来完成这项任务,如
Apache、
Nginx 和
Lighttpd。在本地开发中,通过 HTTP 提供软件包的便捷方法是使用 Python 简单 HTTP 服务器,如下所示:
The package index and packages must be made available through a transfer protocol such as HTTP. We can use any server we wish for this task, such as Apache, Nginx, and Lighttpd. A convenient way to make the packages available through HTTP for local development is by using the Python simple HTTP server, shown as follows:
[ Figure 7.11 – How to provide the package feed by using the Python simple HTTP server ]
要在映像中添加对软件包管理的支持,我们需要做一些更改。我们需要在 EXTRA_IMAGE_FEATURES 中添加软件包管理,并在 PACKAGE_FEED_URIS 中设置用于获取软件包的 URI。例如,我们可以在 build/conf/local.conf 中添加以下内容:
To add support for package management to the image, we have a couple of changes to make. We need to add
package-management in
EXTRA_IMAGE_FEATURES and set the URI for package fetching on
PACKAGE_FEED_URIS. For example, we can add this to our
build/conf/local.conf:
[ Figure 7.12 – How to configure a remote package feed ]
我们将在第 12 章 “创建自定义图层 ”中详细介绍 IMAGE_FEATURES 和 EXTRA_IMAGE_FEATURES 变量。如果我们想要一个不支持软件包管理的缩减镜像,就应该取消 EXTRA_IMAGE_FEATURES 中的软件包管理。
We will detail the
IMAGE_FEATURES and
EXTRA_IMAGE_FEATURES variables in Chapter 12, Creating Custom Layers. If we want a small image with no package management support, we should omit
package-management from
EXTRA_IMAGE_FEATURES.
PACKAGE_FEED_URIS 和 EXTRA_IMAGE_FEATURES 配置可确保客户端的映像能够访问服务器,并具备安装、删除和升级其软件包所需的实用程序。完成这些步骤后,我们就可以在目标设备中使用运行时软件包管理了。
The
PACKAGE_FEED_URIS and
EXTRA_IMAGE_FEATURES configurations guarantee that the image on the client side can access the server and has the utilities needed to install, remove, and upgrade its packages. After these steps, we can use the runtwime package management in the target device.
例如,如果我们为镜像选择 RPM 软件包格式,就可以使用以下命令获取软件源信息:
For example, if we choose the RPM package format for the image, we can fetch the repository information using the following command:
[ Figure 7.13 – Command line to fetch the package feed repository ]
使用 dnf search <package> 和 dnf install <package> 命令从软件源中查找并安装软件包。
Use the dnf search <package>, and dnf install <package> commands to find and install packages from the repositories.
根据所选软件包格式的不同,目标程序更新软件包索引、搜索和安装软件包的命令也不同。请参见下表中每种软件包格式的可用命令行:
Depending on the package format chosen, the commands for the target to update the package index, search for, and install a package are different. See the available command lines for each package format in the following table:
Package format
|
RPM
|
IPK
|
DEB
|
Update the package index
|
dnf check-updates
|
opkg update
|
apt-get update
|
Search for a package
|
dnf search <package>
|
opkg search <package>
|
apt-cache search <package>
|
Install a package
|
dnf install <package>
|
opkg install <package>
|
apt-get install <package>
|
System upgrade
|
dnf upgrade
|
opkg upgrade
|
apt-get dist-upgrade
|
[ Table 7.1 – A package management command comparison ]
在本地开发阶段,使用软件包源是个不错的选择,因为它能让我们在已部署的映像中安装软件包。
The use of package feeds are great to use in a local development phase because they enable us to install packages in an already deployed image.
Note
在现场使用软件包进行系统升级需要进行大量的测试工作,以确保系统不会陷入崩溃状态。要验证所有不同的升级方案,测试工作量非常大。通常情况下,全镜像升级在生产使用中更为安全。
The use of package feeds for system upgrades in the field requires a huge test effort to guarantee that a system does not fall into a broken state. The testing effort is enormous to verify all different upgrade scenarios. Usually, full image upgrades are safer for production use.
软件包联接的管理要复杂得多。它涉及多个其他方面,如软件包依赖链和不同的升级方案。创建一个复杂的软件包源外部服务器不在本书的讨论范围之内,因此请参考 Yocto 项目文档以了解更多详情。
The management of a package feed is much more complex. It involves several other aspects, such as package dependency chains and different upgrade scenarios. Creating a complex package feed external server is out of this book’s scope, so please refer to the Yocto Project documentation for further details.
Summary
本章介绍了打包的基本概念,它在 Poky 和 BitBake(软件包版本控制)中扮演着重要角色,以及这在重建软件包和软件包源时如何影响 Poky 的行为。本章还向我们展示了如何配置映像,以便使用远程服务器提供的预编译包进行更新。
This chapter presented the basic concepts of packaging, which has a significant role in Poky and BitBake (package versioning), and how this impacts Poky’s behavior when rebuilding packages and package feeds. It also showed us how to configure an image to be updated using prebuilt packages provided by a remote server.
在下一章中,我们将学习 BitBake 元数据语法及其运算符,以及如何追加、预追加和删除变量、变量扩展等内容。这样,我们就能更好地理解 Yocto Project 引擎中使用的语言。
In the next chapter, we will learn about the BitBake metadata syntax and its operators and how to append, prepend, and remove content from variables, variable expansions, and so on. We will then be able to better understand the language used in Yocto Project engines.