使用的Linux系统
- Redhat
- Centos
- Fedora
- Mandriva
- SuSE
环境安装初始化
1. 安装 rpmdevtools 软件包
1 | yum install rpmdevtools |
2. 运行 rpmdev-setuptree 程序:
1 | rpmdev-setuptree |
3. 创建的目录说明
目录 | 目的 |
---|---|
BUILD | 构建软件包时,会创建各种 %buildroot 目录。如果日志输出没有足够的信息,这可用于调查失败的构建。 |
RPMS | 此处创建了二进制 RPM,在用于不同架构的子目录中创建,例如在子目录 x86_64 和 noarch 中。 |
SOURCES | 此处,打包商放置了压缩源代码存档和补丁。rpmbuild 命令将在此处查找它们。 |
SPECS | 软件包程序在此放置 SPEC 文件。 |
SRPMS | 当 rpmbuild 用于构建 SRPM 而不是二进制 RPM 时,会创建生成的 SRPM。 |
打包SPEC配置
1. RPM SPEC文件的Preamble部分中使用的项目
SPEC 指令 | 定义 |
---|---|
Name | 软件包的基本名称,应该与 SPEC 文件名匹配。 |
Version | 软件的上游版本。 |
Release | 发布此软件版本的次数。通常,将初始值设为 1%{?dist},并在每个新版软件包中递增。当软件的一个新版本构建时,将重置为 1。 |
Summary | 软件包的一个简短总结。 |
License | 所打包的软件许可证。 |
URL | 有关程序的更多信息的完整 URL。大多数情况下,这是所打包软件的上游项目网站。 |
Source0 | 上游源代码的压缩存档的路径或 URL(未修补,补丁会在其他位置处理)。这应该指向该存档的可访问且可靠的存储,例如上游页面而不是打包程序的本地存储。如果需要,可以添加更多 SourceX 指令,每次递增数字,例如: Source1、Source2、Source3 等。 |
Patch | 应用于源代码的第一个补丁的名称(如有必要)。该指令可以通过两种方式应用:带有或不带补丁末尾的数字。如果没有指定数字,则会在内部分配一个条目。也可以使用 Patch0, Patch1, Patch2, Patch3明确提供数字。这些补丁可以通过使用 %patch0、%patch1、%patch2 宏等应用。宏在 RPM SPEC 文件的 Body 部分中的 %prep 指令中应用。或者,您可以使用 %autopatch 宏,以 SPEC 文件中提供的顺序自动应用所有补丁。 |
BuildArch | 如果软件包没有架构依赖,例如,如果完全使用解释编程语言编写,则将其设置为 BuildArch: noarch。如果没有设置,软件包会自动继承构建机器的架构,如 x86_64。 |
BuildRequires | 使用编译语言构建程序所需的逗号或空格分开的软件包列表。BuildRequires 可以有多个条目,每个条目都在 SPEC 文件中的独立的行中。 |
Requires | 安装之后,软件需要以逗号或空格分开的软件包列表。Requires 可以有多个条目,每个条目都在 SPEC 文件中的独立的行中。 |
ExcludeArch | 如果某一软件不能在特定处理器架构上运行,您可以在此处排除该架构。 |
Conflicts | Conflicts 与 Requires 相反。如果存在与 Conflicts 匹配的软件包,则软件包是否可以安装取决于,带有 Conflict 标签的软件包是否位于已安装的软件包中,还是准备要被安装到的软件包中。 |
Obsoletes | 这个指令会改变更新的工作方式,具体取决于 rpm 命令是否直接在命令行中使用,或者更新是由更新还是依赖项解析程序执行。当在命令行中使用时,RPM 会删除与正在安装的软件包的过时匹配的所有软件包。当使用更新或依赖项解析器时,包含匹配 Obsoletes: 的软件包会作为更新添加并替换匹配的软件包。 |
Provides | 如果向软件包添加了 Provides,则软件包可以通过名称以外的依赖项引用。 |
Name、Version 和 Release 指令包含 RPM 软件包的文件名。RPM 软件包维护者和系统管理员经常调用这三个指令 N-V-R 或 NVR,因为 RPM 软件包文件名具有 NAME-VERSION-RELEASE 格式。
2. 表 3.2. RPM SPEC 文件的 Body 部分中使用的项目
SPEC 指令 | 定义 |
---|---|
%description | RPM 中打包的软件的完整描述。此描述可跨越多行,并且可以分为几个段落。 |
%prep | 用于准备要构建的软件的命令或一系列命令,例如,在 Source0 中解压缩存档。此指令可以包含 shell 脚本。 |
%build | 将软件构建到机器代码(用于编译的语言)或字节代码(用于某些解释语言)的命令或一系列命令。 |
%install | 命令或一系列命令,用于将所需的构建工件从 %builddir (构建发生位置)复制到 %buildroot 目录(其中包含要打包文件的目录结构)。这通常意味着将文件从 ~/rpmbuild/BUILD 复制到 ~/rpmbuild/BUILDROOT,并在 ~/rpmbuild/BUILDROOT 中创建必要的目录。这仅在创建软件包时运行,而不是当最终用户安装软件包时。 |
%check | 用于测试软件的命令或一系列命令。这通常包括单元测试等内容。 |
%files | 将在最终用户系统中安装的文件列表。 |
%changelog | 在不同 Version 或 Release 之间软件包所发生的更改记录。 |
3. RPM 宏
rpm 宏 是一种直接文本替换,在使用特定内置功能时,可以根据声明的可选评估来有条件地分配。因此,RPM 可以为您执行文本替换。
如果您看到不熟悉的宏,您可以使用以下命令评估它:
1
2
3
4
5
6
7
8rpm --eval %{_MACRO}
评估 %{_bindir} 和 %{_libexecdir} 宏
rpm --eval %{_bindir}
/usr/bin
rpm --eval %{_libexecdir}
/usr/libexec如在 %{version} 宏中定义 Version 一次,并在 SPEC 文件中使用此宏。每次出现时都会自动替换为您之前定义的 Version。
常用的宏是 %{?dist} 宏,它向哪个发行版发出用于构建的信号(分配标签)。
1
2
3On a RHEL 8.x machine
rpm --eval %{?dist}
.el8
打包流程说明
1. 使用 rpmdev-newspec 创建新的 SPEC 文件
进入 ~/rpmbuild/SPECS 目录并使用 rpmdev-newspec 实用程序:
1 | cd ~/rpmbuild/SPECS |
2. 修改 rpmdev-newspec 提供的输出 SPEC 文件以创建 RPM。
先决条件
- 特定程序的源代码已放入 ~/rpmbuild/SOURCES/ 目录中。
- 未填充的 SPEC 文件 ~/rpmbuild/SPECS/
.spec 已被 rpmdev-newspec 创建。
步骤
打开 rpmdev-newspec 程序提供的 ~/rpmbuild/SPECS/
.spec 文件的输出模板: 填充 SPEC 文件的第一个部分:
- 2.1 第一部分包括 rpmdev-newspec 分组在一起的这些指令:
- Name: Name 已指定为 rpmdev-newspec 的参数。
- Version: 将 Version 设置为与源代码的上游版本匹配。
- Release: Release 自动设置为 1%{?dist},它最初是 1。每当更新软件包而上游发行版本的 Version 没有更改时(例如当包含补丁时),增加初始的值。当出现新的上游版本时,Release 被重置为 1。
- Summary: Summary 是该软件的简短说明。
- 2.2 完成后SPEC文件长这样
1
2
3
4Name: bello
Version: 0.1
Release: 1%{?dist}
Summary: Hello World example implemented in bash script
- 2.1 第一部分包括 rpmdev-newspec 分组在一起的这些指令:
填充 License、URL 和 Source0 指令:
- License 字段是与上游发行版本中源代码关联的软件许可证。如何在 SPEC 文件中标记 License 的具体格式将有所不同,具体取决于您遵循的基于哪个基于 RPM 的 Linux 发行版准则。例如,您可以使用 GPLv3+。
- URL 字段提供上游软件网站的 URL。为实现一致性,请使用 RPM 宏变量 %{name} ,并使用 https://example.com/%{name}。
- Source0 字段提供上游软件源代码的 URL。它应直接链接到被打包的特定版本。请注意,本文档中给出的示例 URL 包括可在以后更改的硬编码值。同样,发行版本也可以更改。要简化这些潜在的更改,请使用 %{name} 和 %{version} 宏。通过使用以上,您仅需要在 SPEC 文件中更新一个字段。
- 完成后SPEC文件长这样
1
2
3License: GPLv3+
URL: https://example.com/%{name}
Source0: https://example.com/%{name}/release/%{name}-%{version}.tar.gz
填充 BuildRequires、Requires 和 BuildArch 指令:
- BuildRequires: 指定软件包的构建时依赖项。
- Requires: 指定软件包的运行时依赖项。
- BuildArch: 这是使用没有原生编译扩展的解释编程语言编写的软件。因此,使用 noarch 值添加 BuildArch 指令。这告知 RPM 不需要将这个软件包绑定到构建它的处理器架构。
- 完成后SPEC文件长这样
1
2Requires: bash
BuildArch: noarch
填充 %description、%prep、%build、%install、%files 和 %license 指令:这些指令可被视为部分标题,因为它们是可以定义多行、多结构或脚本化任务的指令。
- %description 是一个比 Summary 更长的软件的信息,其中包含一个或多个段落。
- %prep 部分指定如何准备构建环境。这通常涉及对源代码的压缩存档、补丁应用程序以及可能解析源代码中提供的信息的扩展,以便在 SPEC 文件以后的部分中使用。在本节中,您可以使用内置的 %setup -q 宏。
- %build 部分指定如何构建软件。
- %install 部分包含在 BUILDROOT 目录中构建软件后如何安装软件的 rpmbuild 指令。该目录是一个空的 chroot 基础目录,类似于最终用户的根目录。您可以在此处创建包含安装文件的目录。要创建这样的目录,您可以使用 RPM 宏,而无需硬编码路径。
- %files 部分指定此 RPM 提供的文件列表及其终端用户系统的完整路径位置。
- 在本节中,您可以使用内置宏来指示各种文件的角色。这对于使用 command[]rpm 命令查询软件包文件清单元数据很有用。例如,要表示 LICENSE 文件是软件许可证文件,请使用 %license 宏。
最后一个部分( %changelog )是软件包的每个 Version-Release 的带有日期戳的条目列表。它们记录打包更改,而非软件更改。打包更改示例:添加补丁,更改 %build 部分中的构建流程。
- 在第一行使用此格式:以一个 * 字符开头,后跟 Day-of-Week Month Day Year Name Surname
- Version-Release - 使用以下格式进行实际更改条目:
- 每个更改条目都可以包含多个项目,每个代表一个改变。
- 每个项目在新行中开始。
- 每个项目以 - 字符开头。
- 在第一行使用此格式:以一个 * 字符开头,后跟 Day-of-Week Month Day Year Name Surname
至此,您已为所需的程序编写了整个 SPEC 文件。
3. 完整SPEC文件示例
1 | Name: bello |
4. 构建RPM包
使用指定的 SPEC 文件运行 rpmbuild 命令:
1
2使用 SPECfile 替换 SPECFILE。-bs 选项代表构建源。
rpmbuild -bs SPECFILE从源 RPM(SRPM)重建二进制 RPM。
1
2rpmbuild --rebuild ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm
[output truncated]从SPEC 文件构建二进制 RPM
1
2使用 bb 选项运行 rpmbuild 命令:
rpmbuild -bb ~/rpmbuild/SPECS/bello.spec从源 RPM 构建 RPM
1
2使用以下选项之一运行 rpmbuild 命令,并使用指定的源软件包:
rpmbuild {-ra|-rb|-rp|-rc|-ri|-rl|-rs} [rpmbuild-options] SOURCEPACKAGE常用打包命令
1
2
3
4常用打包命令
rpmdev-setuptree
rpmbuild -ba hello-world.spec
命令 rpmdev-setuptree 会创建几个工作目录。由于这些目录永久存储在 $HOME 中,因此不需要再次使用此命令
5. 检查 RPM 健全性
rpmlint 工具可以检查二进制 RPM、源 RPM (SRPMs)和 SPEC 文件,因此它对打包的所有阶段都很有用,如下例所示。
在适用于 bello 的 SPEC 文件中运行 rpmlint 命令的输出
1
2
3
4rpmlint bello.spec
bello.spec: W: invalid-url Source0: https://www.example.com/bello/releases/bello-0.1.tar.gz HTTP Error 404: Not Found
0 packages and 1 specfiles checked; 0 errors, 1 warnings.
对于 bello.spec,只有一个警告,表示 Source0 指令中列出的 URL 不可访问。这是正常的,因为指定的 example.com URL 不存在。假设我们预期此 URL 在未来工作,我们可以忽略这个警告。在 SRPM forllo 上运行 rpmlint 命令的输出
1
2
3
4
5rpmlint ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm
bello.src: W: invalid-url URL: https://www.example.com/bello HTTP Error 404: Not Found
bello.src: W: invalid-url Source0: https://www.example.com/bello/releases/bello-0.1.tar.gz HTTP Error 404: Not Found
1 packages and 0 specfiles checked; 0 errors, 2 warnings.
对于 bello SRPM,有一个新的警告,表示 URL 指令中指定的 URL 不可访问。假设链接将在以后工作,我们可以忽略此警告。在 bello 的二进制 RPM 上运行 rpmlint 命令的输出
1
2
3
4
5
6rpmlint ~/rpmbuild/RPMS/noarch/bello-0.1-1.el8.noarch.rpm
bello.noarch: W: invalid-url URL: https://www.example.com/bello HTTP Error 404: Not Found
bello.noarch: W: no-documentation
bello.noarch: W: no-manual-page-for-binary bello
1 packages and 0 specfiles checked; 0 errors, 3 warnings.
no-documentation 和 no-manual-page-for-binary 警告表示 RPM 没有文档或手册页,因为我们没有提供任何文档或手册页。除以上警告外,RPM 会传递 rpmlint 检查。