第 6 章 Packaging software
In the following sections, learn the basics of the packaging process with the RPM package manager.
6.1. About spec files 复制链接链接已复制到粘贴板!
A spec file is a file with instructions that the rpmbuild utility uses to build an RPM package. This file provides necessary information to the build system by defining instructions in a series of sections. These sections are defined in the Preamble and the Body part of the spec file:
- The Preamble section contains a series of metadata items that are used in the Body section.
- The Body section represents the main part of the instructions.
6.1.1. Preamble items of a spec file 复制链接链接已复制到粘贴板!
The following are some of the directives that you can use in the Preamble section of the RPM spec file.
| Directive | Definition |
|---|---|
|
|
A base name of the package that must match the |
|
| An upstream version number of the software. |
|
| The number of times the version of the package was released.
Set the initial value to |
|
| A brief one-line summary of the package. |
|
| A license of the software being packaged.
The exact format for how to label the |
|
| A full URL for more information about the software, for example, an upstream project website for the software being packaged. |
|
| A path or URL to the compressed archive of the unpatched upstream source code. This link must point to an accessible and reliable storage of the archive, for example, the upstream page, not the packager’s local storage.
You can apply the |
|
| A name of the first patch to apply to the source code, if necessary.
You can apply the
You can apply the patches individually by using the |
|
| An architecture that the software will be built for.
If the software is not architecture-dependent, for example, if you wrote the software entirely in an interpreted programming language, set the value to |
|
|
A comma- or whitespace-separated list of packages required to build the program written in a compiled language. There can be multiple entries of |
|
|
A comma- or whitespace-separated list of packages required by the software to run once installed. There can be multiple entries of |
|
|
If a piece of software cannot operate on a specific processor architecture, you can exclude this architecture in the |
|
|
A comma- or whitespace-separated list of packages that must not be installed on the system in order for your software to function properly when installed. There can be multiple entries of |
|
|
The
|
|
|
If you add the |
6.1.2. Body items of a spec file 复制链接链接已复制到粘贴板!
The following are the items used in the Body section of the RPM spec file.
| Directive | Definition |
|---|---|
|
| A full description of the software packaged in the RPM. This description can span multiple lines and can be broken into paragraphs. |
|
|
A command or series of commands to prepare the software for building, for example, for unpacking the archive in the |
|
| A command or series of commands to configure the software for building. |
|
| A command or series of commands for building the software into machine code (for compiled languages) or bytecode (for some interpreted languages). |
|
|
A command or series of commands that the
The
Note that |
|
| A command or series of commands for testing the software, for example, unit tests. |
|
| A list of files, provided by the RPM package, to be installed in the user’s system and their full path location on the system.
During the build, if there are files in the
Within the |
|
|
A record of changes that happened to the package between different |
6.1.3. Advanced spec file items 复制链接链接已复制到粘贴板!
A spec file can contain advanced items, such as Scriptlets, File triggers and Triggers. These directives influence not only the spec file, but also the target operating system on which the resulting RPM is installed by updating the system with information from the RPM. Scriptlets, File Triggers and Triggers take effect at different points during the installation process on the target system, not the build process:
- Scriptlets are unconditionally executed before or after the package is installed or deleted.
- Triggers are conditionally executed when their specified trigger condition matches other packages on the installed system or in a transaction.
- File triggers are conditionally executed when their specified path prefix matches other files on the installed system or in a transaction.
6.1.3.1. Scriptlets directives 复制链接链接已复制到粘贴板!
Scriptlets are arbitrary programs that execute at pre-determined slots related to a package’s lifetime, for example, before or after the package is installed or deleted. By default, scriptlets are short shell scripts declared by the various %pre or %post directives in a spec file. Use scriptlets only for tasks that cannot be done at build time or in a startup script.
Common scriptlet directives are similar to the spec file section headers, such as %build or %install. They are defined by multi-line segments of code, which are often written as a standard POSIX shell script. However, they can also be written in other programming languages that RPM accepts for the target machine’s distribution.
6.1.3.2. Scriptlets directives execution order 复制链接链接已复制到粘贴板!
Scriptlets directives have different order of execution:
-
%preand%postare executed before and after you installed a package. -
%preunand%postunare executed before and after you uninstalled the package. -
%pretransand %posttrans are executed at start and end of the transaction that installs the package, respectively.
During the package upgrade, the scriptlets are executed in the following order:
| Directive | Description |
|---|---|
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
6.1.3.3. Turning off scriptlets execution 复制链接链接已复制到粘贴板!
You can turn off the execution of any scriptlet by using the --no option with the scriptlet name.
You can also use the --noscripts option, which is equivalent to turning off the execution of all the following scriptlets:
-
--nopre -
--nopost -
--nopreun -
--nopostun -
--nopretrans -
--noposttrans -
--nopreuntrans -
--nopostuntrans
For more information, see the rpm man page on your system.
Procedure
Turn off the scriptlet execution:
# rpm --no<scriptlet_name>For example, to turn off the execution of the
%pretransscriptlet, enter:# rpm --nopretrans
6.1.3.4. Example macros for scriptlets 复制链接链接已复制到粘贴板!
The following are example macros that you can use for scriptlets in a spec file. These macros are real-world macros provided by the systemd-rpm-macros package. You can use these macros for packaging systemd-related things. You can also apply similar principles to other packages.
Packages that contain systemd unit files must use scriptlets to properly handle systemd services. systemd packages provide a set of macros to handle systemd scriptlet operations. For example:
%post
%systemd_post httpd.service
%preun
%systemd_preun httpd.service
These macros expand to the following in a package:
$ rpm --eval "%systemd_preun httpd.service"
if [ $1 -eq 0 ] && [ -x "/usr/lib/systemd/systemd-update-helper" ]; then
# Package removal, not upgrade
/usr/lib/systemd/systemd-update-helper remove-system-units httpd.service || :
fi
The way macros behave is subject to change. For example, macros' behavior can change with a package’s development.
6.1.4. The Epoch directive 复制链接链接已复制到粘贴板!
If setting the Version spec file directive is not enough for comparing package versions, you can use an Epoch directive. For example, you can use Epoch to resolve upgrade path issues that, for example, occurred because of the upstream change in a version numbering scheme in an incompatible manner.
Epoch is a numeric field. If you assign a value to Epoch, it adds a qualifier that RPM uses when comparing package versions. Not having the Epoch directive listed in a spec file means Epoch is not set. This is contrary to the common belief that not setting Epoch results in an Epoch of 0. However, for processing purposes, if you do not set Epoch, RPM treats it the same as if the Epoch was set to 0, and vice versa.
Using Epoch in a spec file is usually omitted because, in the majority of cases, introducing an Epoch value distorts the expected RPM behavior when comparing versions of packages. Therefore, consider using Epoch as a last resort.
For example, you installed the foobar package with Epoch: 1 and Version: 1.0. Another packager packages foobar with Version: 2.0, but without the Epoch directive. As a result, the new version is never considered an update because the Epoch version is preferred over the traditional Name-Version-Release marker that signifies versioning for RPM packages.
6.1.5. Package versioning essentials 复制链接链接已复制到粘贴板!
The essential part of the package description is the information defined in the Name, Version, and Release (NVR) spec file directives. RPM uses this information to compare package versions and track package dependencies.
When working with RPMs, you can also see mentions of EVR (epoch-version-release), NEVR (name-epoch-version-release), and NEVRA (name-epoch-version-release-architecture). EVR is the full version information of the package that RPM always uses for comparison. RPM compares one component at a time, starting from the first component. RPM stops the comparison when it finds a difference in components. For example, if Epoch differs, RPM does not compare the rest of the EVR components.
You can display the NVR information for a specific package by querying the RPM database, for example:
# rpm -q bash
bash-4.4.19-7.el8.x86_64
Here, bash is the package name, 4.4.19 is the version, and 7.el8 is the release. The x86_64 marker is the package architecture. Unlike NVR, the architecture marker is not under direct control of the RPM packager, but is defined by the rpmbuild build environment. The exception to this is the architecture-independent noarch package.
The rpm -q command displays the package information in the NEVRA format by default.