Chapter 4. Packaging software


In the following sections, learn the basics of the packaging process with the RPM package manager.

4.1. Setting up RPM packaging workspace

To build RPM packages, you must first create a special workspace that consists of directories used for different packaging purposes.

4.1.1. Configuring RPM packaging workspace

To configure the RPM packaging workspace, you can set up a directory layout by using the rpmdev-setuptree utility.

Prerequisites

  • You installed the rpmdevtools package, which provides 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

4.1.2. RPM packaging workspace directories

The following are the RPM packaging workspace directories created by using the rpmdev-setuptree utility:

Table 4.1. RPM packaging workspace directories
DirectoryPurpose

BUILD

Contains build artifacts compiled from the source files from the SOURCES directory.

RPMS

Binary RPMs are created under the RPMS directory in subdirectories for different architectures. For example, in the x86_64 or noarch subdirectory.

SOURCES

Contains compressed source code archives and patches. The rpmbuild command then searches for these archives and patches in this directory.

SPECS

Contains spec files created by the packager. These files are then used for building packages.

SRPMS

When you use the rpmbuild command to build an SRPM instead of a binary RPM, the resulting SRPM is created under this directory.

4.2. 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.

4.2.1. Preamble items

The following are some of the directives that you can use in the Preamble section of the RPM spec file.

Table 4.2. The Preamble section directives
DirectiveDefinition

Name

A base name of the package that must match the spec file name.

Version

An upstream version number of the software.

Release

The number of times the version of the package was released.

Set the initial value to 1%{?dist} and increase it with each new release of the package. Reset to 1 when a new Version of the software is built.

Summary

A brief one-line summary of the package.

License

A license of the software being packaged.

The exact format for how to label the License in your spec file varies depending on which RPM-based Linux distribution guidelines you are following, for example, GPLv3+.

URL

A full URL for more information about the software, for example, an upstream project website for the software being packaged.

Source

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 Source directive either with or without numbers at the end of the directive name. If there is no number given, the number is assigned to the entry internally. You can also give the numbers explicitly, for example, Source0, Source1, Source2, Source3, and so on.

Patch

A name of the first patch to apply to the source code, if necessary.

You can apply the Patch directive either with or without numbers at the end of the directive name. If there is no number given, the number is assigned to the entry internally. You can also give the numbers explicitly, for example, Patch0, Patch1, Patch2, Patch3, and so on.

You can apply the patches individually by using the %patch0, %patch1, %patch2 macro, and so on. Macros are applied within the %prep directive in the Body section of the RPM spec file. Alternatively, you can use the %autopatch macro that automatically applies all patches in the order they are given in the spec file.

BuildArch

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 BuildArch: noarch. If you do not set this value, the software automatically inherits the architecture of the machine on which it is built, for example, x86_64.

BuildRequires

A comma- or whitespace-separated list of packages required to build the program written in a compiled language. There can be multiple entries of BuildRequires, each on its own line in the SPEC file.

Requires

A comma- or whitespace-separated list of packages required by the software to run once installed. There can be multiple entries of Requires, each on its own line in the spec file.

ExcludeArch

If a piece of software cannot operate on a specific processor architecture, you can exclude this architecture in the ExcludeArch directive.

Conflicts

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 Conflicts, each on its own line in the spec file.

Obsoletes

The Obsoletes directive changes the way updates work depending on the following factors:

  • If you use the rpm command directly on a command line, it removes all packages that match obsoletes of packages being installed, or the update is performed by an updates or dependency solver.
  • If you use the updates or dependency resolver (DNF), packages containing matching Obsoletes: are added as updates and replace the matching packages.

Provides

If you add the Provides directive to the package, this package can be referred to by dependencies other than its name.

The Name, Version, and Release (NVR) directives comprise the file name of the RPM package in the name-version-release format.

You can display the NVR information for a specific package by querying RPM database by using the rpm command, 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.

4.2.2. Body items

The following are the items used in the Body section of the RPM spec file.

Table 4.3. The Body section items
DirectiveDefinition

%description

A full description of the software packaged in the RPM. This description can span multiple lines and can be broken into paragraphs.

%prep

A command or series of commands to prepare the software for building, for example, for unpacking the archive in the Source directive. The %prep directive can contain a shell script.

%build

A command or series of commands for building the software into machine code (for compiled languages) or bytecode (for some interpreted languages).

%install

A command or series of commands that the rpmbuild utility will use to install the software into the BUILDROOT directory once the software has been built. These commands copy the desired build artifacts from the %_builddir directory, where the build happens, to the %buildroot directory that contains the directory structure with the files to be packaged. This includes copying files from ~/rpmbuild/BUILD to ~/rpmbuild/BUILDROOT and creating the necessary directories in ~/rpmbuild/BUILDROOT.

The %install 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 RPM macros without having to hardcode the paths.

Note that %install is only run when you create a package, not when you install it. For more information, see Working with spec files.

%check

A command or series of commands for testing the software, for example, unit tests.

%files

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 %buildroot directory that are not listed in %files, you will receive a warning about possible unpackaged files.

Within the %files section, you can indicate the role of various files by using built-in macros. This is useful for querying the package file manifest metadata by using the rpm command. For example, to indicate that the LICENSE file is a software license file, use the %license macro.

%changelog

A record of changes that happened to the package between different Version or Release builds. These changes include a list of date-stamped entries for each Version-Release of the package. These entries log packaging changes, not software changes, for example, adding a patch or changing the build procedure in the %build section.

4.2.3. Advanced items

A spec file can contain advanced items, such as Scriptlets or Triggers.

Scriptlets and Triggers take effect at different points during the installation process on the end user’s system, not the build process.

4.3. BuildRoots

In the context of RPM packaging, buildroot is a chroot environment. The build artifacts are placed here by 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 must 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.

Note

The rpmbuild program has its own defaults. Overriding these defaults can cause certain issues. Therefore, avoid defining your own value of the buildroot macro. Use the default %{buildroot} macro instead.

4.4. 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. Therefore, RPM can perform text substitutions for you.

For example, you can define Version of the packaged software only once in the %{version} macro, and use this macro throughout the spec file. Every occurrence is automatically substituted by Version that you defined in the macro.

Note

If you see an unfamiliar macro, you can evaluate it with the following command:

$ rpm --eval %{MACRO}

For example, to evaluate the %{_bindir} and %{_libexecdir} macros, enter:

$ rpm --eval %{_bindir}
/usr/bin

$ rpm --eval %{_libexecdir}
/usr/libexec

Additional resources

4.5. Working with spec files

To package new software, you must create a spec file. You can create the spec file either of the following ways:

  • Write the new spec file manually from scratch.
  • Use the rpmdev-newspec utility. This utility creates an unpopulated spec file, where you fill the necessary directives and fields.
Note

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.

4.5.1. Creating a new spec file for sample Bash, Python, and C programs

You can create a spec file for each of the three implementations of the Hello World! program by using the rpmdev-newspec utility.

Prerequisites

Procedure

  1. Navigate to the ~/rpmbuild/SPECS directory:

    $ cd ~/rpmbuild/SPECS
  2. Create a spec file for each of the three implementations of the Hello World! program:

    $ 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 named bello.spec, cello.spec, and pello.spec.

  3. Examine the created files.

    The directives in the files represent those described in About spec files. In the following sections, you will populate particular section in the output files of rpmdev-newspec.

4.5.2. Modifying an original spec file

The original output spec file generated by the rpmdev-newspec utility represents a template that you must modify to provide necessary instructions for the rpmbuild utility. rpmbuild then uses these instructions to build an RPM package.

Prerequisites

Procedure

  1. Open the ~/rpmbuild/SPECS/<name>.spec file provided by the rpmdev-newspec utility.
  2. Populate the following directives of the spec file Preamble section:

    Name
    Name was already specified as an argument to rpmdev-newspec.
    Version
    Set Version to match the upstream release version of the source code.
    Release
    Release is automatically set to 1%{?dist}, which is initially 1.
    Summary
    Enter a one-line explanation of the package.
    License
    Enter the software license associated with the source code.
    URL
    Enter the URL to the upstream software website. For consistency, utilize the %{name} RPM macro variable and use the https://example.com/%{name} format.
    Source

    Enter the URL to the upstream software source code. Link directly to the software version being packaged.

    Note

    The example URLs in this documentation include hard-coded values that could possibly 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 macros, you need to update only one field in the spec file.

    BuildRequires
    Specify build-time dependencies for the package.
    Requires
    Specify run-time dependencies for the package.
    BuildArch
    Specify the software architecture.
  3. Populate the following directives of the spec file Body section. You can think of these directives as section headings, because these directives can define multi-line, multi-instruction, or scripted tasks to occur.

    %description
    Enter the full description of the software.
    %prep
    Enter a command or series of commands to prepare software for building.
    %build
    Enter a command or series of commands for building software.
    %install
    Enter a command or series of commands that instruct the rpmbuild command on how to install the software into the BUILDROOT directory.
    %files
    Specify the list of files, provided by the RPM package, to be installed on your system.
    %changelog

    Enter the list of datestamped entries for each Version-Release of the package.

    Start the first line of the %changelog section with an asterisk (*) character followed by Day-of-Week Month Day Year Name Surname <email> - Version-Release.

    For the actual change entry, follow these rules:

    • Each change entry can contain multiple items, one for each change.
    • Each item starts on a new line.
    • Each item begins with a hyphen (-) character.

You have now written an entire spec file for the required program.

4.5.3. An example spec file for a sample Bash program

You can use the following example spec file for the bello program 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, includes 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 the bash script does not need to be built.
Note

To install bello, you must create the destination directory and install the executable bash script file there. Therefore, you can use the install command in the %install section. You can use RPM macros to do this without hardcoding paths.

Additional resources

4.5.4. An example SPEC file for a program written in Python

You can use the following example spec file for the pello program written in the Python programming language for your reference.

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 value 3 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 is pello and, therefore, the name of the Source RPM (SRPM) is python-pello.
3
The BuildRequires directive 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 (or python3.11-devel or python3.12-devel) and the relevant projects needed by the specific software that you package, for example, python3-setuptools (or python3.11-setuptools or python3.12-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, the python3.11- prefix for Python 3.11, or the python3.12- prefix for Python 3.12. You can use the %{python3_pkgversion} macro, which evaluates to 3 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 and setup.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.

4.5.5. An example spec file for a sample C program

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 the following packages required to perform the compilation build process:

    • gcc
    • make
  • 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 the Makefile file for the cello program was written. Therefore, you can use the GNU make command. However, you must remove the call to %configure because you did not provide a configure script.

You can install the cello program by using the %make_install macro. This is possible because the Makefile file for the cello program is available.

Additional resources

4.6. Building RPMs

You can build RPM packages by using the rpmbuild command. When using this command, a certain directory and file structure is expected, 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 following are the main use cases:

  • Building source RPMs.
  • Building binary RPMs:

    • Rebuilding a binary RPM from a source RPM.
    • Building a binary RPM from the spec file.

4.6.1. Building source RPMs

Building a Source RPM (SRPM) has the following advantages:

  • You can preserve the exact source of a certain Name-Version-Release of an RPM file that was deployed to an environment. This includes the exact spec file, the source code, and all relevant patches. This is useful for tracking and debugging purposes.
  • You can build a binary RPM on a different hardware platform or architecture.

Prerequisites

Procedure

  1. Navigate to the ~/rpmbuild/SPECS/ directive, which contains the created spec file:

    $ cd ~/rpmbuild/SPECS/
  2. Build the source RPM by entering the rpmbuild command with the specified spec file:

    $ rpmbuild -bs <specfile>

    The -bs option stands for the build source.

    For example, to build source RPMs for the bello, pello, and cello programs, enter:

    $ 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

  • Verify that the rpmbuild/SRPMS directory includes the resulting source RPMs. The directory is a part of the structure expected by rpmbuild.

4.6.2. Rebuilding a binary RPM from a source RPM

To rebuild a binary RPM from a source RPM (SRPM), use the rpmbuild command with the --rebuild option.

The output generated when creating the 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 located 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.

Prerequisites

  • You have installed the rpmbuild utility on your system:

    # dnf install rpm-build

Procedure

  1. Navigate to the ~/rpmbuild/SRPMS/ directive, which contains the source RPM:

    $ cd ~/rpmbuild/SRPMS/
  2. Rebuild the binary RPM from the source RPM:

    $ rpmbuild --rebuild <srpm>

    Replace srpm with the name of the source RPM file.

    For example, to rebuild bello, pello, and cello from their SRPMs, enter:

    $ rpmbuild --rebuild bello-0.1-1.el8.src.rpm
    [output truncated]
    
    $ rpmbuild --rebuild pello-0.1.2-1.el8.src.rpm
    [output truncated]
    
    $ rpmbuild --rebuild cello-1.0-1.el8.src.rpm
    [output truncated]
Note

Invoking rpmbuild --rebuild involves the following processes:

  • Installing the contents of the SRPM (the spec file and the source code) into the ~/rpmbuild/ directory.
  • Building an RPM by using the installed contents.
  • Removing the spec file and the source code.

You can retain the spec file and the source code after building either of the following ways:

  • When building the RPM, use the rpmbuild command with the --recompile option instead of the --rebuild option.
  • Install SRPMs for bello, pello, and cello:

    $ 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%]

4.6.3. Building a binary RPM from the spec file

To build a binary RPM from its spec file, use the rpmbuild command with the -bb option.

Prerequisites

  • You have installed the rpmbuild utility on your system:

    # dnf install rpm-build

Procedure

  1. Navigate to the ~/rpmbuild/SPECS/ directive, which contains spec files:

    $ cd ~/rpmbuild/SPECS/
  2. Build the binary RPM from its spec:

    $ rpmbuild -bb <spec_file>

    For example, to build bello, pello, and cello binary RPMs from their spec files, enter:

    $ rpmbuild -bb bello.spec
    
    $ rpmbuild -bb pello.spec
    
    $ rpmbuild -bb cello.spec

4.7. Checking RPMs for common errors

After creating a package, you might want to check the quality of the package. The main tool for checking package quality is rpmlint.

With the rpmlint tool, you can perform the following actions:

  • Improve RPM maintainability.
  • Enable content validation by performing static analysis of the RPM.
  • Enable error checking by performing static analysis of the RPM.

You can use rpmlint to check binary RPMs, source RPMs (SRPMs), and spec files. Therefore, this tool is useful for all stages of packaging.

Note that rpmlint has strict guidelines. Therefore, it is sometimes acceptable to skip some of its errors and warnings as shown in the following sections.

Note

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, run rpmlint -i instead.

4.7.1. Checking a sample Bash program for common errors

In the following sections, investigate possible warnings and errors that can occur when checking an RPM for common errors on the example of the bello spec file and bello binary RPM.

4.7.1.1. Checking the bello spec file for common errors

Inspect the outputs of the following examples to learn how to check a bello spec file for common errors.

Output of running the rpmlint command on the bello spec file

$ 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 invalid-url Source0 warning. This warning means that the URL listed in the Source0 directive is unreachable. This is expected, because the specified example.com URL does not exist. Assuming that this URL will be valid in the future, you can ignore this warning.

Output of running the rpmlint command on the bello SRPM

$ 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 invalid-url URL warning that means that the URL specified in the URL directive is unreachable. Assuming that this URL will be valid in the future, you can ignore this warning.

4.7.1.2. Checking the bello binary RPM for common errors

When checking binary RPMs, the rpmlint command checks the following items:

  • Documentation
  • Manual pages
  • Consistent use of the filesystem hierarchy standard

Inspect the outputs of the following example to learn how to check a bello binary RPM for common errors.

Output of running the rpmlint command on the bello binary RPM

$ 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 mean that the RPM has no documentation or manual pages, because you did not provide any. Apart from the output warnings, the RPM passed rpmlint checks.

4.7.2. Checking a sample Python program for common errors

In the following sections, investigate possible warnings and errors that can occur when validating RPM content on the example of the pello spec file and pello binary RPM.

4.7.2.1. Checking the pello spec file for common errors

Inspect the outputs of the following examples to learn how to check a pello spec file for common errors.

Output of running the rpmlint command on the pello spec file

$ 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 means that the URL listed in the Source0 directive is unreachable. This is expected, because the specified example.com URL does not exist. Assuming that this URL will be valid in the future, you can ignore this warning.
  • The hardcoded-library-path errors suggest using 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, check all errors carefully.

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 invalid-url URL error means that the URL mentioned in the URL directive is unreachable. Assuming that this URL will be valid in the future, you can ignore this warning.

4.7.2.2. Checking the pello binary RPM for common errors

When checking binary RPMs, the rpmlint command checks the following items:

  • Documentation
  • Manual pages
  • Consistent use of the Filesystem Hierarchy Standard

Inspect the outputs of the following example to learn how to check a pello binary RPM for common errors.

Output of running the rpmlint command on the pello binary RPM

$ 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 mean that the RPM has no documentation or manual pages because you did not provide any.
  • The only-non-binary-in-usr-lib warning means that you provided only non-binary artifacts in the /usr/lib/ directory. This directory is typically used for shared object files, which are binary files. Therefore, rpmlint expects at least one or more files in /usr/lib/ to be binary.

    This is an example of an rpmlint check for compliance with Filesystem Hierarchy Standard. To ensure the correct placement of files, use RPM macros. For the sake of this example, you can safely ignore this warning.

  • The non-executable-script error means 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 output warnings and errors, the RPM passed rpmlint checks.

4.7.3. Checking a sample C program for common errors

In the following sections, investigate possible warnings and errors that can occur when validating RPM content on the example of the cello spec file and cello binary RPM.

4.7.3.1. Checking the cello spec file for common errors

Inspect the outputs of the following examples to learn how to check a cello spec file for common errors.

Output of running the rpmlint command on the cello spec file

$ 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 invalid-url Source0 warning. This warning means that the URL listed in the Source0 directive is unreachable. This is expected because the specified example.com URL does not exist. Assuming that this URL will be valid in the future, you can ignore this warning.

Output of running the rpmlint command on the cello SRPM

$ 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 invalid-url URL warning. This warning means that the URL specified in the URL directive is unreachable. Assuming that this URL will be valid in the future, you can ignore this warning.

4.7.3.2. Checking the cello binary RPM for common errors

When checking binary RPMs, the rpmlint command checks the following items:

  • Documentation
  • Manual pages
  • Consistent use of the filesystem hierarchy standard

Inspect the outputs of the following example to learn how to check a cello binary RPM for common errors.

Output of running the rpmlint command on the cello binary RPM

$ 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 mean that the RPM has no documentation or manual pages because you did not provide any.

Apart from the output warnings, the RPM passed rpmlint checks.

4.8. Logging RPM activity to syslog

You can log any RPM activity or transaction by using the System Logging protocol (syslog).

Prerequisites

  • The syslog plug-in is installed on the system:

    # dnf install rpm-plugin-syslog
    Note

    The 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.

Procedure

  1. Open the file that you configured to store the syslog messages.

    Alternatively, if you use the default syslog configuration, open the /var/log/messages file.

  2. Search for new lines including the [RPM] string.

4.9. Extracting RPM content

In some cases, for example, if a package required by RPM is damaged, you might need 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.

Note

If the RPM installation is severely damaged, you can use the rpm2cpio utility to convert the RPM package file to a cpio archive.

Procedure

  • Convert the RPM file to the tar archive:

    $ rpm2archive <filename>.rpm

    The resulting file has the .tgz suffix. For example, to create an archive from the bash package, enter:

    $ rpm2archive bash-4.4.19-6.el8.x86_64.rpm
    $ ls bash-4.4.19-6.el8.x86_64.rpm.tgz
    bash-4.4.19-6.el8.x86_64.rpm.tgz
Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

© 2024 Red Hat, Inc.