Chapter 3. Packaging software
3.1. RPM packages
An RPM package is a file containing other files and their metadata (information about the files that are needed by the system).
Specifically, an RPM package consists of the cpio
archive.
The cpio
archive contains:
- Files
RPM header (package metadata)
The
rpm
package manager uses this metadata to determine dependencies, where to install files, and other information.
Types of RPM packages
There are two types of RPM packages. Both types share the file format and tooling, but have different contents and serve different purposes:
Source RPM (SRPM)
An SRPM contains source code and a SPEC file, which describes how to build the source code into a binary RPM. Optionally, the patches to source code are included as well.
Binary RPM
A binary RPM contains the binaries built from the sources and patches.
3.2. Listing RPM packaging tool’s utilities
The following procedure describes how to list the utilities provided by the rpmdevtools
package.
Prerequisites
You installed the
rpmdevtools
package, which provides several utilities for packaging RPMs:# dnf install rpmdevtools
Procedure
List RPM packaging tool’s utilities:
$ rpm -ql rpmdevtools | grep bin
For more information about the above utilities, see their manual pages or help dialogs.
3.3. Setting up RPM packaging workspace
You can set up a directory layout that is the RPM packaging workspace by using the rpmdev-setuptree
utility.
Prerequisites
You installed the
rpmdevtools
package, which provides several utilities for packaging RPMs:# dnf install rpmdevtools
Procedure
Run the
rpmdev-setuptree
utility:$ rpmdev-setuptree $ tree ~/rpmbuild/ /home/user/rpmbuild/ |-- BUILD |-- RPMS |-- SOURCES |-- SPECS `-- SRPMS 5 directories, 0 files
The created directories serve the following purposes:
Directory | Purpose |
BUILD |
When packages are built, various |
RPMS |
Binary RPMs are created here, in subdirectories for different architectures, for example in subdirectories |
SOURCES |
Here, the packager puts compressed source code archives and patches. The |
SPECS | The packager puts SPEC files here. |
SRPMS |
When |
3.4. What is a SPEC file
You can understand a SPEC file as a recipe that the rpmbuild
utility uses to build an RPM. A SPEC file provides necessary information to the build system by defining instructions in a series of sections. The sections are defined in the Preamble and the Body part. The Preamble part contains a series of metadata items that are used in the Body part. The Body part represents the main part of the instructions.
The following sections describe each section of a SPEC file.
3.4.1. Preamble items
The table below presents some of the directives that are used frequently in the Preamble section of the RPM SPEC file.
Table 3.1. Items used in the Preamble
section of the RPM SPEC file
SPEC Directive | Definition |
---|---|
| The base name of the package, which should match the SPEC file name. |
| The upstream version number of the software. |
|
The number of times this version of the software was released. Normally, set the initial value to 1%{?dist}, and increment it with each new release of the package. Reset to 1 when a new |
| A brief, one-line summary of the package. |
| The license of the software being packaged. |
| The full URL for more information about the program. Most often this is the upstream project website for the software being packaged. |
| Path or URL to the compressed archive of the upstream source code (unpatched, patches are handled elsewhere). This should point to an accessible and reliable storage of the archive, for example, the upstream page and not the packager’s local storage. If needed, more SourceX directives can be added, incrementing the number each time, for example: Source1, Source2, Source3, and so on. |
| The name of the first patch to apply to the source code if necessary. The directive can be applied in two ways: with or without numbers at the end of Patch. If no number is given, one is assigned to the entry internally. It is also possible to give the numbers explicitly using Patch0, Patch1, Patch2, Patch3, and so on. These patches can be applied one by one using the %patch0, %patch1, %patch2 macro and so on. The macros are applied within the %prep directive in the Body section of the RPM SPEC file. Alternatively, you can use the %autopatch macro which automatically applies all patches in the order they are given in the SPEC file. |
|
If the package is not architecture dependent, for example, if written entirely in an interpreted programming language, set this to |
|
A comma or whitespace-separated list of packages required for building 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 can not operate on a specific processor architecture, you can exclude that architecture here. |
|
|
|
This directive alters the way updates work depending on whether the |
|
If |
The Name
, Version
, and Release
directives comprise the file name of the RPM package. RPM package maintainers and system administrators often call these three directives N-V-R or NVR, because RPM package filenames have the NAME-VERSION-RELEASE
format.
The following example shows how to obtain the NVR information for a specific package by querying the rpm
command.
Example 3.1. Querying rpm to provide the NVR information for the bash package
# 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 final marker is x86_64
, which signals the architecture. Unlike the 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.
3.4.2. Body items
The items used in the Body section
of the RPM SPEC file are listed in the table below.
Table 3.2. Items used in the Body section of the RPM SPEC file
SPEC Directive | Definition |
---|---|
| A full description of the software packaged in the RPM. This description can span multiple lines and can be broken into paragraphs. |
|
Command or series of commands to prepare the software to be built, for example, unpacking the archive in |
| Command or series of commands for building the software into machine code (for compiled languages) or byte code (for some interpreted languages). |
|
Command or series of commands for copying the desired build artifacts from the for details. |
| Command or series of commands to test the software. This normally includes things such as unit tests. |
| The list of files that will be insstalled in the end user’s system. |
|
A record of changes that have happened to the package between different |
3.4.3. Advanced items
The SPEC file can also contain advanced items, such as Scriptlets or Triggers.
They take effect at different points during the installation process on the end user’s system, not the build process.
3.5. BuildRoots
In the context of RPM packaging, buildroot
is a chroot environment. This means that the build artifacts are placed here using the same file system hierarchy as the future hierarchy in the end user’s system, with buildroot
acting as the root directory. The placement of build artifacts should comply with the file system hierarchy standard of the end user’s system.
The files in buildroot
are later put into a cpio
archive, which becomes the main part of the RPM. When RPM is installed on the end user’s system, these files are extracted in the root
directory, preserving the correct hierarchy.
Starting from Red Hat Enterprise Linux 6, the rpmbuild
program has its own defaults. Overriding these defaults leads to several problems; hence, Red Hat does not recommend to define your own value of this macro. You can use the %{buildroot}
macro with the defaults from the rpmbuild
directory.
3.6. RPM macros
An rpm macro is a straight text substitution that can be conditionally assigned based on the optional evaluation of a statement when certain built-in functionality is used. Hence, RPM can perform text substitutions for you.
An example use is referencing the packaged software Version multiple times in a SPEC file. You define Version only once in the %{version}
macro, and use this macro throughout the SPEC file. Every occurrence will be automatically substituted by Version that you defined previously.
If you see an unfamiliar macro, you can evaluate it with the following command:
$ rpm --eval %{_MACRO}
Evaluating the %{_bindir} and the %{_libexecdir} macros
$ rpm --eval %{_bindir} /usr/bin $ rpm --eval %{_libexecdir} /usr/libexec
One of the commonly-used macros is the %{?dist}
macro, which signals which distribution is used for the build (distribution tag).
# On a RHEL 9.x machine $ rpm --eval %{?dist} .el8
3.7. Working with SPEC files
To package new software, you need to create a new SPEC file.
There are two ways to achieve this:
- Writing the new SPEC file manually from scratch
Use the
rpmdev-newspec
utilityThis utility creates an unpopulated SPEC file, and you fill in the necessary directives and fields.
Some programmer-focused text editors pre-populate a new .spec
file with their own SPEC template. The rpmdev-newspec
utility provides an editor-agnostic method.
The following sections use the three example implementations of the Hello World!
program that were described in What is source code.
Each of the programs is also fully described in the table below.
Software Name | Explanation of example |
bello | A program written in a raw interpreted programming language. It demonstrates when the source code does not need to be built, but only needs to be installed. If a pre-compiled binary needs to be packaged, you can also use this method since the binary would also just be a file. |
pello | A program written in a byte-compiled interpreted programming language. It demonstrates byte-compiling the source code and installating the bytecode - the resulting pre-optimized files. |
cello | A program written in a natively compiled programming language. It demonstrates a common process of compiling the source code into machine code and installing the resulting executables. |
The implementations of Hello World!
are:
As a prerequisite, these implementations need to be placed into the ~/rpmbuild/SOURCES
directory.
3.8. Creating a new SPEC file with rpmdev-newspec
The following procedure shows how to create a SPEC file for each of the three aforementioned Hello World!
programs using the rpmdev-newspec
utility.
Procedure
Change to the
~/rpmbuild/SPECS
directory and use therpmdev-newspec
utility:$ cd ~/rpmbuild/SPECS $ rpmdev-newspec bello bello.spec created; type minimal, rpm version >= 4.11. $ rpmdev-newspec cello cello.spec created; type minimal, rpm version >= 4.11. $ rpmdev-newspec pello pello.spec created; type minimal, rpm version >= 4.11.
The
~/rpmbuild/SPECS/
directory now contains three SPEC files namedbello.spec
,cello.spec
, andpello.spec
.Examine the files:
The directives in the files represent those described in What is a SPEC file.
In the following sections, you will populate particular section in the output files of rpmdev-newspec
.
The rpmdev-newspec
utility does not use guidelines or conventions specific to any particular Linux distribution. However, this document targets Red Hat Enterprise Linux, so the %{buildroot}
notation is preferred over the $RPM_BUILD_ROOT
notation when referencing RPM’s Buildroot for consistency with all other defined or provided macros throughout the SPEC file.
3.9. Modifying an original SPEC file for creating RPMs
The following procedure shows how to modify the output SPEC file provided by rpmdev-newspec
for creating the RPMs.
Prerequisites
-
The source code of the particular program has been placed into the
~/rpmbuild/SOURCES/
directory. -
The unpopulated SPEC file
~/rpmbuild/SPECS/<name>.spec
file has been created by therpmdev-newspec
utility.
Procedure
-
Open the output template of the
~/rpmbuild/SPECS/<name>.spec
file provided by therpmdev-newspec
utility: Populate the first section of the SPEC file:
The first section includes these directives that
rpmdev-newspec
grouped together:Name
-
The
Name
was already specified as an argument torpmdev-newspec
. Version
-
Set the
Version
to match the upstream release version of the source code. Release
-
The
Release
is automatically set to1%{?dist}
, which is initially1
. Increment the initial value whenever updating the package without a change in the upstream releaseVersion
- such as when including a patch. ResetRelease
to1
when a new upstream release happens. Summary
-
The
Summary
is a short, one-line explanation of what this software is.
Populate the
License
,URL
, andSource0
directives:The
License
field is the Software License associated with the source code from the upstream release. The exact format for how to label theLicense
in your SPEC file will vary depending on which specific RPM based Linux distribution guidelines you are following.For example, you can use GPLv3+.
The
URL
field provides URL to the upstream software website. For consistency, utilize the RPM macro variable of%{name}
, and usehttps://example.com/%{name}
.The
Source0
field provides URL to the upstream software source code. It should link directly to the specific version of software that is being packaged. Note that the example URLs given in this documentation include hard-coded values that are possible subject to change in the future. Similarly, the release version can change as well. To simplify these potential future changes, use the%{name}
and%{version}
macros. By using these, you need to update only one field in the SPEC file.Populate the
BuildRequires
,Requires
andBuildArch
directives:BuildRequires
specifies build-time dependencies for the package.Requires
specifies run-time dependencies for the package.This is a software written in an interpreted programming language with no natively compiled extensions. Hence, add the
BuildArch
directive with thenoarch
value. This tells RPM that this package does not need to be bound to the processor architecture on which it is built.Populate the
%description
,%prep
,%build
,%install
,%files
, and%license
directives:These directives can be thought of as section headings, because they are directives that can define multi-line, multi-instruction, or scripted tasks to occur.
The
%description
is a longer, fuller description of the software thanSummary
, containing one or more paragraphs.The
%prep
section specifies how to prepare the build environment. This usually involves expansion of compressed archives of the source code, application of patches, and, potentially, parsing of information provided in the source code for use in a later portion of the SPEC file. In this section you can use the built-in%setup -q
macro.The
%build
section specifies how to build the software.The
%install
section contains instructions forrpmbuild
on how to install the software, once it has been built, into theBUILDROOT
directory.This directory is an empty chroot base directory, which resembles the end user’s root directory. Here you can create any directories that will contain the installed files. To create such directories, you can use the RPM macros without having to hardcode the paths.
The
%files
section specifies the list of files provided by this RPM and their full path location on the end user’s system.Within this section, you can indicate the role of various files using built-in macros. This is useful for querying the package file manifest metadata using the
rpm
command. For example, to indicate that the LICENSE file is a software license file, use the%license
macro.The last section,
%changelog
, is a list of datestamped entries for each Version-Release of the package. They log packaging changes, not software changes. Examples of packaging changes: adding a patch, changing the build procedure in the%build
section.Follow this format for the first line:
Start with an
*
character followed byDay-of-Week Month Day Year Name Surname <email> - Version-Release
Follow this format for the actual change entry:
- Each change entry can contain multiple items, one for each change.
- Each item starts on a new line.
-
Each item begins with a
-
character.
You have now written an entire SPEC file for the required program.
3.10. An example SPEC file for a program written in bash
You can use the following example SPEC file for the bello program that was written in bash for your reference.
An example SPEC file for the bello program written in bash
Name: bello Version: 0.1 Release: 1%{?dist} Summary: Hello World example implemented in bash script License: GPLv3+ URL: https://www.example.com/%{name} Source0: https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz Requires: bash BuildArch: noarch %description The long-tail description for our Hello World Example implemented in bash script. %prep %setup -q %build %install mkdir -p %{buildroot}/%{_bindir} install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name} %files %license LICENSE %{_bindir}/%{name} %changelog * Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1-1 - First bello package - Example second item in the changelog for version-release 0.1-1
The BuildRequires
directive, which specifies build-time dependencies for the package, was deleted because there is no building step for bello
. Bash is a raw interpreted programming language, and the files are just installed to their location on the system.
The Requires
directive, which specifies run-time dependencies for the package, include only bash
, because the bello
script requires only the bash
shell environment to execute.
The %build
section, which specifies how to build the software, is blank, because a bash
does not need to be built.
For installing bello
you only need to create the destination directory and install the executable bash
script file there. Hence, you can use the install
command in the %install
section. RPM macros allow to do this without hardcoding paths.
Additional resources
3.11. An example SPEC file for a program written in Python
Example SPEC file for the pello program written in the Python programming language follows.
An example SPEC file for the pello program written in Python
%global python3_pkgversion 3.11 1 Name: python-pello 2 Version: 1.0.2 Release: 1%{?dist} Summary: Example Python library License: MIT URL: https://github.com/fedora-python/Pello Source: %{url}/archive/v%{version}/Pello-%{version}.tar.gz BuildArch: noarch BuildRequires: python%{python3_pkgversion}-devel 3 # Build dependencies needed to be specified manually BuildRequires: python%{python3_pkgversion}-setuptools # Test dependencies needed to be specified manually # Also runtime dependencies need to be BuildRequired manually to run tests during build BuildRequires: python%{python3_pkgversion}-pytest >= 3 %global _description %{expand: Pello is an example package with an executable that prints Hello World! on the command line.} %description %_description %package -n python%{python3_pkgversion}-pello 4 Summary: %{summary} %description -n python%{python3_pkgversion}-pello %_description %prep %autosetup -p1 -n Pello-%{version} %build # The macro only supported projects with setup.py %py3_build 5 %install # The macro only supported projects with setup.py %py3_install %check 6 %{pytest} # Note that there is no %%files section for the unversioned python module %files -n python%{python3_pkgversion}-pello %doc README.md %license LICENSE.txt %{_bindir}/pello_greeting # The library files needed to be listed manually %{python3_sitelib}/pello/ # The metadata files needed to be listed manually %{python3_sitelib}/Pello-*.egg-info/
- 1
- By defining the
python3_pkgversion
macro, you set which Python version this package will be built for. To build for the default Python version 3.9, either set the macro to its default value3
or remove the line entirely. - 2
- When packaging a Python project into RPM, always add the
python-
prefix to the original name of the project. The original name here ispello
and, therefore, the name of the Source RPM (SRPM) ispython-pello
. - 3
- BuildRequires specifies what packages are required to build and test this package. In BuildRequires, always include items providing tools necessary for building Python packages:
python3-devel
(orpython3.11-devel
) and the relevant projects needed by the specific software that you package, for example,python3-setuptools
(orpython3.11-setuptools
) or the runtime and testing dependencies needed to run the tests in the %check section. - 4
- When choosing a name for the binary RPM (the package that users will be able to install), add a versioned Python prefix. Use the
python3-
prefix for the default Python 3.9 or thepython3.11-
prefix for Python 3.11. You can use the%{python3_pkgversion}
macro, which evaluates to3
for the default Python version 3.9 unless you set it to an explicit version, for example,3.11
(see footnote 1). - 5
- The %py3_build and %py3_install macros run the
setup.py build
andsetup.py install
commands, respectively, with additional arguments to specify installation locations, the interpreter to use, and other details. - 6
- The %check section should run the tests of the packaged project. The exact command depends on the project itself, but it is possible to use the %pytest macro to run the
pytest
command in an RPM-friendly way.
3.12. An example SPEC file for a program written in C
You can use the following example SPEC file for the cello program that was written in the C programming language for your reference.
An example SPEC file for the cello program written in C
Name: cello Version: 1.0 Release: 1%{?dist} Summary: Hello World example implemented in C License: GPLv3+ URL: https://www.example.com/%{name} Source0: https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz Patch0: cello-output-first-patch.patch BuildRequires: gcc BuildRequires: make %description The long-tail description for our Hello World Example implemented in C. %prep %setup -q %patch0 %build make %{?_smp_mflags} %install %make_install %files %license LICENSE %{_bindir}/%{name} %changelog * Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 1.0-1 - First cello package
The BuildRequires
directive, which specifies build-time dependencies for the package, includes two packages that are needed to perform the compilation build process:
-
The
gcc
package -
The
make
package
The Requires
directive, which specifies run-time dependencies for the package, is omitted in this example. All runtime requirements are handled by rpmbuild
, and the cello
program does not require anything outside of the core C standard libraries.
The %build
section reflects the fact that in this example a Makefile
for the cello program was written, hence the GNU make command provided by the rpmdev-newspec
utility can be used. However, you need to remove the call to %configure
because you did not provide a configure script.
The installation of the cello program can be accomplished by using the %make_install
macro that was provided by the rpmdev-newspec
command. This is possible because the Makefile
for the cello program is available.
Additional resources
3.13. Building RPMs
RPMs are built with the rpmbuild
command. This command expects a certain directory and file structure, which is the same as the structure that was set up by the rpmdev-setuptree
utility.
Different use cases and desired outcomes require different combinations of arguments to the rpmbuild
command. The two main use cases are:
- Building source RPMs
Building binary RPM
- Rebuilding a binary RPM from a source RPM
- Building a binary RPM from the SPEC file
- Building a binary RPM from a source RPM
This following sections describe how to build an RPM after a SPEC file for a program has been created.
3.14. Building source RPMs
The following procedure describes how to build a source RPM.
Prerequisites
- A SPEC file for the program that we want to package must already exist.
Procedure
Run the
rpmbuild
command with the specified SPEC file:$ rpmbuild -bs SPECFILE
Substitute SPECFILE with the SPEC file. The
-bs
option stands for the build source.
The following example shows building source RPMs for the bello
, pello
, and cello
projects.
Building source RPMs for bello, pello, and cello.
$ cd ~/rpmbuild/SPECS/ 8$ rpmbuild -bs bello.spec Wrote: /home/admiller/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm $ rpmbuild -bs pello.spec Wrote: /home/admiller/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm $ rpmbuild -bs cello.spec Wrote: /home/admiller/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm
Verification steps
-
Make sure that the
rpmbuild/SRPMS
directory includes the resulting source RPMs. The directory is a part of the structure expected byrpmbuild
.
3.15. Rebuilding a binary RPM from a source RPM
The following procedure shows how to rebuild a binary RPM from a source RPM (SRPM).
Procedure
To rebuild
bello
,pello
, andcello
from their SRPMs, run:$ rpmbuild --rebuild ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm [output truncated] $ rpmbuild --rebuild ~/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm [output truncated] $ rpmbuild --rebuild ~/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm [output truncated]
Invoking rpmbuild --rebuild
involves:
-
Installing the contents of the SRPM - the SPEC file and the source code - into the
~/rpmbuild/
directory. - Building using the installed contents.
- Removing the SPEC file and the source code.
To retain the SPEC file and the source code after building, you can:
-
When building, use the
rpmbuild
command with the--recompile
option instead of the--rebuild
option. Install the SRPMs using these commands:
$ rpm -Uvh ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm Updating / installing… 1:bello-0.1-1.el8 [100%] $ rpm -Uvh ~/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm Updating / installing… …1:pello-0.1.2-1.el8 [100%] $ rpm -Uvh ~/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm Updating / installing… …1:cello-1.0-1.el8 [100%]
The output generated when creating a binary RPM is verbose, which is helpful for debugging. The output varies for different examples and corresponds to their SPEC files.
The resulting binary RPMs are in the ~/rpmbuild/RPMS/YOURARCH
directory where YOURARCH
is your architecture or in the ~/rpmbuild/RPMS/noarch/
directory, if the package is not architecture-specific.
3.16. Building a binary RPM from the SPEC file
The following procedure shows how to build bello
, pello
, and cello
binary RPMs from their SPEC files.
Procedure
Run the
rpmbuild
command with thebb
option:$ rpmbuild -bb ~/rpmbuild/SPECS/bello.spec $ rpmbuild -bb ~/rpmbuild/SPECS/pello.spec $ rpmbuild -bb ~/rpmbuild/SPECS/cello.spec
3.17. Building binary RPMs from source RPMs
It is also possible to build any kind of RPM from a source RPM. To do so, use the following procedure.
Procedure
Run the
rpmbuild
command with one of the below options and with the source package specified:# rpmbuild {-ra|-rb|-rp|-rc|-ri|-rl|-rs} [rpmbuild-options] SOURCEPACKAGE
Additional resources
-
rpmbuild(8)
man page
3.18. Checking RPMs for sanity
After creating a package, it is necessary to check the quality of the package.
The main tool for checking package quality is rpmlint.
The rpmlint
tool does the following:
- Improves RPM maintainability.
- Enables sanity checking by performing static analysis of the RPM.
- Enables error checking by performing static analysis of the RPM.
The rpmlint
tool can check binary RPMs, source RPMs (SRPMs), and SPEC files, so it is useful for all stages of packaging, as shown in the following sections.
Note that rpmlint
has very strict guidelines; hence it is sometimes acceptable to skip some of its errors and warnings, as shown in the following examples.
In the examples described in the following sections, rpmlint
is run without any options, which produces a non-verbose output. For detailed explanations of each error or warning, you can run rpmlint -i
instead.
3.19. Checking bello for sanity
Warnings and errors can occur when checking RPM sanity on the example of the bello SPEC file and bello binary RPM.
3.19.1. Checking the bello SPEC File
Example 3.2. Output of running the rpmlint
command on the SPEC file for bello
$ rpmlint 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.
For bello.spec
, there is only one warning, which says that the URL listed in the Source0
directive is unreachable. This is expected, because the specified example.com
URL does not exist. Presuming that we expect this URL to work in the future, we can ignore this warning.
Example 3.3. Output of running the rpmlint
command on the SRPM for bello
$ rpmlint ~/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.
For the bello
SRPM, there is a new warning, which says that the URL specified in the URL
directive is unreachable. Assuming the link will be working in the future, we can ignore this warning.
3.19.2. Checking the bello binary RPM
When checking binary RPMs, rpmlint
checks for the following items:
- Documentation
- Manual pages
- Consistent use of the filesystem hierarchy standard
Example 3.4. Output of running the rpmlint
command on the binary RPM for bello
$ rpmlint ~/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.
The no-documentation
and no-manual-page-for-binary
warnings say that he RPM has no documentation or manual pages, because we did not provide any. Apart from the above warnings, the RPM passed rpmlint
checks.
3.20. Checking pello for sanity
This section shows possible warnings and errors that can occur when checking RPM sanity on the example of the pello SPEC file and pello binary RPM.
3.20.1. Checking the pello SPEC File
Example 3.5. Output of running the rpmlint
command on the SPEC file for pello
$ rpmlint pello.spec pello.spec:30: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name} pello.spec:34: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.pyc pello.spec:39: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name}/ pello.spec:43: E: hardcoded-library-path in /usr/lib/%{name}/ pello.spec:45: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.py* pello.spec: W: invalid-url Source0: https://www.example.com/pello/releases/pello-0.1.2.tar.gz HTTP Error 404: Not Found 0 packages and 1 specfiles checked; 5 errors, 1 warnings.
The invalid-url Source0
warning says that the URL listed in the Source0
directive is unreachable. This is expected, because the specified example.com
URL does not exist. Presuming that this URL will work in the future, you can ignore this warning.
The hardcoded-library-path
errors suggest to use the %{_libdir}
macro instead of hard-coding the library path. For the sake of this example, you can safely ignore these errors. However, for packages going into production make sure to check all errors carefully.
Example 3.6. Output of running the rpmlint
command on the SRPM for pello
$ rpmlint ~/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm pello.src: W: invalid-url URL: https://www.example.com/pello HTTP Error 404: Not Found pello.src:30: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name} pello.src:34: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.pyc pello.src:39: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name}/ pello.src:43: E: hardcoded-library-path in /usr/lib/%{name}/ pello.src:45: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.py* pello.src: W: invalid-url Source0: https://www.example.com/pello/releases/pello-0.1.2.tar.gz HTTP Error 404: Not Found 1 packages and 0 specfiles checked; 5 errors, 2 warnings.
The new invalid-url URL
error here is about the URL
directive, which is unreachable. Assuming that the URL will be valid in the future, you can safely ignore this error.
3.20.2. Checking the pello binary RPM
When checking binary RPMs, rpmlint
checks for the following items:
- Documentation
- Manual pages
- Consistent use of the Filesystem Hierarchy Standard
Example 3.7. Output of running the rpmlint
command on the binary RPM for pello
$ rpmlint ~/rpmbuild/RPMS/noarch/pello-0.1.2-1.el8.noarch.rpm pello.noarch: W: invalid-url URL: https://www.example.com/pello HTTP Error 404: Not Found pello.noarch: W: only-non-binary-in-usr-lib pello.noarch: W: no-documentation pello.noarch: E: non-executable-script /usr/lib/pello/pello.py 0644L /usr/bin/env pello.noarch: W: no-manual-page-for-binary pello 1 packages and 0 specfiles checked; 1 errors, 4 warnings.
The no-documentation
and no-manual-page-for-binary
warnings say that the RPM has no documentation or manual pages, because you did not provide any.
The only-non-binary-in-usr-lib
warning says that you provided only non-binary artifacts in /usr/lib/
. This directory is normally reserved for shared object files, which are binary files. Therefore, rpmlint
expects at least one or more files in /usr/lib/
directory to be binary.
This is an example of an rpmlint
check for compliance with Filesystem Hierarchy Standard. Normally, use RPM macros to ensure the correct placement of files. For the sake of this example, you can safely ignore this warning.
The non-executable-script
error warns that the /usr/lib/pello/pello.py
file has no execute permissions. The rpmlint
tool expects the file to be executable, because the file contains the shebang. For the purpose of this example, you can leave this file without execute permissions and ignore this error.
Apart from the above warnings and errors, the RPM passed rpmlint
checks.
3.21. Checking cello for sanity
Warnings and errors can occur when checking RPM sanity on the example of the cello SPEC file and pello binary RPM.
3.21.1. Checking the cello SPEC File
Example 3.8. Output of running the rpmlint
command on the SPEC file for cello
$ rpmlint ~/rpmbuild/SPECS/cello.spec /home/admiller/rpmbuild/SPECS/cello.spec: W: invalid-url Source0: https://www.example.com/cello/releases/cello-1.0.tar.gz HTTP Error 404: Not Found 0 packages and 1 specfiles checked; 0 errors, 1 warnings.
For cello.spec
, there is only one warning, which says that the URL listed in the Source0
directive is unreachable. This is expected, because the specified example.com
URL does not exist. Presuming that this URL will work in the future, you can ignore this warning.
Example 3.9. Output of running the rpmlint
command on the SRPM for cello
$ rpmlint ~/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm cello.src: W: invalid-url URL: https://www.example.com/cello HTTP Error 404: Not Found cello.src: W: invalid-url Source0: https://www.example.com/cello/releases/cello-1.0.tar.gz HTTP Error 404: Not Found 1 packages and 0 specfiles checked; 0 errors, 2 warnings.
For the cello
SRPM, there is a new warning, which says that the URL specified in the URL
directive is unreachable. Assuming the link will be working in the future, you can ignore this warning.
3.21.2. Checking the cello binary RPM
When checking binary RPMs, rpmlint
checks for the following items:
- Documentation
- Manual pages
- Consistent use of the filesystem hierarchy standard
Example 3.10. Output of running the rpmlint
command on the binary RPM for cello
$ rpmlint ~/rpmbuild/RPMS/x86_64/cello-1.0-1.el8.x86_64.rpm cello.x86_64: W: invalid-url URL: https://www.example.com/cello HTTP Error 404: Not Found cello.x86_64: W: no-documentation cello.x86_64: W: no-manual-page-for-binary cello 1 packages and 0 specfiles checked; 0 errors, 3 warnings.
The no-documentation
and no-manual-page-for-binary
warnings say that he RPM has no documentation or manual pages, because you did not provide any. Apart from the above warnings, the RPM passed rpmlint
checks.
3.22. Logging RPM activity to syslog
Any RPM activity or transaction can be logged by the System Logging protocol (syslog).
Prerequisites
To enable the logging of RPM transactions to syslog, make sure that the
syslog
plug-in is installed on the system:# dnf install rpm-plugin-syslog
NoteThe default location for the syslog messages is the
/var/log/messages
file. However, you can configure syslog to use another location to store the messages.
To see the updates on RPM activity, follow the described procedure.
Procedure
-
Open the file that you configured to store the syslog messages, or if you use the default syslog configuration, open the
/var/log/messages
file. -
Search for new lines including the
[RPM]
string.
3.23. Extracting RPM content
In particular cases, for example, if a package required by RPM is damaged, it is necessary to extract the content of the package. In such cases, if an RPM installation is still working despite the damage, you can use the rpm2archive
utility to convert an .rpm file to a tar archive to use the content of the package.
If the RPM installation is severely damaged, you can use the rpm2cpio
utility to convert the RPM package file to a cpio archive.
The following procedure describes how to convert an rpm payload to a tar archive using the rpm2archive
utility.
Procedure
Run the following command:
$ rpm2archive filename.rpm
Replace filename with the name of the .rpm file.
The resulting file has the
.tgz
suffix. For example, to archive thebash
package:$ rpm2archive bash-4.4.19-6.el8.x86_64.rpm $ bash-4.4.19-6.el8.x86_64.rpm.tgz bash-4.4.19-6.el8.x86_64.rpm.tgz