第 3 章 打包软件
3.1. RPM 软件包
本节介绍 RPM 打包格式的基础知识。
3.1.1. RPM 是什么
RPM 软件包是包含其它文件和元数据的文件(系统所需文件的信息)。
					特别是,RPM 软件包由 cpio 归档组成。
				
					cpio 归档包含:
				
- 文件
- RPM 标头(软件包元数据) - rpm软件包管理器使用此元数据来确定依赖项、安装文件的位置和其他信息。
RPM 软件包的类型
RPM 软件包有两种类型。这两种类型都共享文件格式和工具,但内容不同,并实现不同的目的:
- 源 RPM(SRPM) - SRPM 包含源代码和 SPEC 文件,这些文件描述了如何将源代码构建为二进制 RPM。另外,也可以选择包括源代码的补丁。 
- 二进制 RPM - 一个二进制 RPM 包含了根据源代码和补丁构建的二进制文件。 
3.1.2. 列出 RPM 打包工具的工具
					以下流程演示了如何列出 rpmdevtools 软件包提供的工具。
				
先决条件
						为了可以使用 RPM 打包工具,您需要安装 rpmdevtools 软件包,该软件包为打包 RPM 提供了多个实用程序。
					
yum install rpmdevtools
# yum install rpmdevtools流程
- 列出 RPM 打包工具的工具: - rpm -ql rpmdevtools | grep bin - $ rpm -ql rpmdevtools | grep bin- Copy to Clipboard Copied! - Toggle word wrap Toggle overflow 
附加信息
- 有关以上实用程序的更多信息,请参阅其手册页或帮助对话框。
3.1.3. 设置 RPM 打包工作区
					这部分论述了如何使用 rpmdev-setuptree 程序设置属于 RPM 打包工作区的目录布局。
				
先决条件
						在您的系统中必须安装 rpmdevtools 软件包:
					
yum install rpmdevtools
# yum install rpmdevtools流程
- 
							运行 rpmdev-setuptree程序:
创建的目录用于这些目的:
| 目录 | 目的 | 
| BUILD | 
									构建软件包时,会创建各种  | 
| RPMS | 
									此处创建了二进制 RPM,在用于不同架构的子目录中创建,例如在子目录  | 
| 源 | 
									此处,打包商放置了压缩源代码存档和补丁。 | 
| SPECS | 软件包程序在此放置 SPEC 文件。 | 
| SRPMS | 
									当  | 
3.1.4. SPEC 文件是什么
					您可以将 SPEC 文件作为 rpmbuild 实用程序用来构建 RPM 的配方。SPEC 文件通过定义一系列部分中的说明,为构建系统提供必要信息。这些部分在 Preamble 和 Body 部分中定义。Preamble 部分包含一系列在 Body 部分中使用的元数据项。Body 部分代表说明的主要部分。
				
3.1.4.1. Preamble Items
下表介绍了 RPM SPEC 文件的 Preamble 部分中经常使用的一些指令。
| SPEC 指令 | 定义 | 
|---|---|
| 
										 | 软件包的基本名称,应该与 SPEC 文件名匹配。 | 
| 
										 | 软件的上游版本。 | 
| 
										 | 
										发布此软件版本的次数。通常,将初始值设为 1%{?dist},并在每个新版软件包中递增。当软件的一个新 | 
| 
										 | 软件包的一个简短总结. | 
| 
										 | 所打包的软件许可证。 | 
| 
										 | 有关程序的更多信息的完整 URL。大多数情况下,这是所打包软件的上游项目网站。 | 
| 
										 | 上游源代码的压缩存档的路径或 URL(未修补,补丁会在其他位置处理)。这应该指向该存档的可访问且可靠的存储,例如上游页面而不是打包程序的本地存储。如果需要,可以添加更多 SourceX 指令,每次递增数字,例如: Source1、Source2、Source3 等。 | 
| 
										 | 应用于源代码的第一个补丁的名称(如有必要)。 该指令可以通过两种方式应用:带有或不带补丁末尾的数字。 如果没有指定数字,则会在内部分配一个条目。也可以使用 Patch0, Patch1, Patch2, Patch3 明确提供数字。 这些补丁可以通过使用 %patch0、%patch1、%patch2 宏等应用。宏在 RPM SPEC 文件的 Body 部分中的 %prep 指令中应用。或者,您可以使用 %autopatch 宏,以 SPEC 文件中提供的顺序自动应用所有补丁。 | 
| 
										 | 
										如果软件包没有架构依赖,例如,如果完全使用解释编程语言编写,则将其设置为  | 
| 
										 | 
										使用编译语言构建程序所需的逗号或空格分开的软件包列表。 | 
| 
										 | 
										安装之后,软件需要以逗号或空格分开的软件包列表。 | 
| 
										 | 如果某一软件不能在特定处理器架构上运行,您可以在此处排除该架构。 | 
| 
										 | 
										 | 
| 
										 | 
										这个指令会改变更新的工作方式,具体取决于  | 
| 
										 | 
										如果向软件包添加了  | 
						Name、Version 和 Release 指令包含 RPM 软件包的文件名。RPM 软件包维护者和系统管理员经常调用这三个指令 N-V-R 或 NVR,因为 RPM 软件包文件名具有 NAME-VERSION-RELEASE 格式。
					
						以下示例演示了如何通过查询 rpm 命令获取特定软件包的 NVR 信息。
					
例 3.1. 查询 rpm 为 bash 软件包提供 NVR 信息
rpm -q bash
$ rpm -q bash
bash-4.2.46-34.el7.x86_64
						在这里,bash 是软件包名称,4.2.46 是版本,34.el7 是发行版本。最后的标记是 x86_64,它向架构发出信号。与 NVR 不同,架构标记不直接控制 RPM 打包程序,而是由 rpmbuild 构建环境进行定义。这种情况的例外是独立于架构的 noarch 软件包。
					
3.1.4.2. 正文项目
						下表列出 RPM SPEC 文件的 Body 部分中使用的项目。
					
| SPEC 指令 | 定义 | 
|---|---|
| 
										 | RPM 中打包的软件的完整描述。此描述可跨越多行,并且可以分为几个段落。 | 
| 
										 | 
										用于准备要构建的软件的命令或一系列命令,例如,在  | 
| 
										 | 将软件构建到机器代码(用于编译的语言)或字节代码(用于某些解释语言)的命令或一系列命令。 | 
| 
										 | 
										命令或一系列命令,用于将所需的构建工件从  | 
| 
										 | 用于测试软件的命令或一系列命令。这通常包括单元测试等内容。 | 
| 
										 | 将在最终用户系统中安装的文件列表。 | 
| 
										 | 
										在不同  | 
3.1.4.3. 高级 items
SPEC 文件还可以包含高级项目,如 Scriptlets 或 Triggers。它们在安装过程中对最终用户系统而不是构建过程的不同点生效。
3.1.5. BuildRoots
					在 RPM 打包上下文中,buildroot 是 chroot 环境。这意味着,构建工件被放在使用与最终用户系统中未来层次结构相同的文件系统层次结构,并将 buildroot 用作根目录。构建工件的放置应遵守最终用户系统的文件系统层次结构标准。
				
					buildroot 中的文件稍后放入 cpio 存档,后者成为 RPM 的主要部分。当在最终用户的系统中安装 RPM 时,这些文件将提取到 root 目录中,保留正确的层次结构。
				
						从 6 开始,rpmbuild 程序有自己的默认值。覆盖这些默认设置会导致几个问题,因此 {RH} 不推荐定义这个宏的值。您可以在 rpmbuild 目录中使用 %{buildroot} 宏。
					
3.1.6. RPM 宏
rpm 宏 是一种直接文本替换,在使用特定内置功能时,可以根据声明的可选评估来有条件地分配。因此,RPM 可以为您执行文本替换。
					示例用法是在 SPEC 文件中多次引用打包软件 Version。您仅在 %{version} 宏中定义 Version 一次,并在 SPEC 文件中使用此宏。每次出现时都会自动替换为您之前定义的 Version。
				
如果您看到不熟悉的宏,您可以使用以下命令评估它:
rpm --eval %{_MACRO}
$ rpm --eval %{_MACRO}评估 %{_bindir} 和 %{_libexecdir} 宏
rpm --eval %{_bindir}
rpm --eval %{_libexecdir}
$ rpm --eval %{_bindir}
/usr/bin
$ rpm --eval %{_libexecdir}
/usr/libexec
					常用的宏是 %{?dist} 宏,它向哪个发行版发出用于构建的信号(分配标签)。
				
On a RHEL 8.x machine
rpm --eval %{?dist}
# On a RHEL 8.x machine
$ rpm --eval %{?dist}
.el8