Red Hat Training

A Red Hat training course is available for RHEL 8

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

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:

    # yum 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 %buildroot directories are created here. This is useful for investigating a failed build if the logs output do not provide enough information.

RPMS

Binary RPMs are created here, in subdirectories for different architectures, for example in subdirectories x86_64 and noarch.

SOURCES

Here, the packager puts compressed source code archives and patches. The rpmbuild command looks for them here.

SPECS

The packager puts SPEC files here.

SRPMS

When rpmbuild is used to build an SRPM instead of a binary RPM, the resulting SRPM is created here.

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

4.2.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 4.1. Items used in the Preamble section of the RPM SPEC file

SPEC DirectiveDefinition

Name

The base name of the package, which should match the SPEC file name.

Version

The upstream version number of the software.

Release

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 Version of the software is built.

Summary

A brief, one-line summary of the package.

License

The license of the software being packaged.

URL

The full URL for more information about the program. Most often this is the upstream project website for the software being packaged.

Source0

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.

Patch

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.

BuildArch

If the package is not architecture dependent, for example, if written entirely in an interpreted programming language, set this to BuildArch: noarch. If not set, the package 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 for building 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 can not operate on a specific processor architecture, you can exclude that architecture here.

Conflicts

Conflicts are inverse to Requires. If there is a package matching Conflicts, the package cannot be installed independently on whether the Conflict tag is on the package that has already been installed or on a package that is going to be installed.

Obsoletes

This directive alters the way updates work depending on whether the rpm command is used directly on the command line or the update is performed by an updates or dependency solver. When used on a command line, RPM removes all packages matching obsoletes of packages being installed. When using an update or dependency resolver, packages containing matching Obsoletes: are added as updates and replace the matching packages.

Provides

If Provides is added to a package, the package can be referred to by dependencies other than its name.

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

4.2.2. Body items

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

Table 4.2. Items used in the Body section of the RPM SPEC file

SPEC 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

Command or series of commands to prepare the software to be built, for example, unpacking the archive in Source0. This directive can contain a shell script.

%build

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

%install

Command or series of commands for copying the desired build artifacts from the %builddir (where the build happens) to the %buildroot directory (which contains the directory structure with the files to be packaged). This usually means copying files from ~/rpmbuild/BUILD to ~/rpmbuild/BUILDROOT and creating the necessary directories in ~/rpmbuild/BUILDROOT. This is only run when creating a package, not when the end-user installs the package. See Working with SPEC files for details.

%check

Command or series of commands to test the software. This normally includes things such as unit tests.

%files

The list of files that will be insstalled in the end user’s system.

%changelog

A record of changes that have happened to the package between different Version or Release builds.

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

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

Starting from Red Hat Enterprise Linux 6, the rpmbuild program has its own defaults. Overriding these defaults leads to several problems. Therefore, it is not recommended to define your own value of this macro. You can use the %{buildroot} macro with the defaults from the rpmbuild directory.

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

Note

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 8.x machine
$ rpm --eval %{?dist}
.el8

4.5. Working with SPEC files

To package new software, you must create a SPEC file.

You can create a SPEC file 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 in 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.

The following sections use the three example implementations of the Hello World! program:

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 because 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 installing 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 the following:

As a prerequisite, these implementations need to be placed into the ~/rpmbuild/SOURCES directory.

For more information about the Hello World! program implementations, see What is source code.

In the following section, learn how to work with SPEC files:

4.5.1. Creating a new SPEC file with rpmdev-newspec

To create a SPEC file for each of the three implementations of the Hello World! program by using the rpmdev-newspec utility, complete the following steps.

Procedure

  1. Go to the ~/rpmbuild/SPECS directory and use the rpmdev-newspec utility:

    $ cd ~/rpmbuild/SPECS
  2. Create a SPEC file for each of the three implementations of the Hello World! Program by using the rpmdev-newspec utility:

    $ 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 What is a SPEC file. In the following sections, you will populate particular section in the output files of rpmdev-newspec.

Note

The rpmdev-newspec utility does not use guidelines or conventions specific to any particular Linux distribution. However, this document targets Red Hat Enterprise Linux, therefore 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.

4.5.2. Modifying an original SPEC file for creating RPMs

To modify the output SPEC file provided by the rpmdev-newspec utility for creating RPM packages, complete the following steps.

Prerequisites

  • The source code of the particular program has been placed into the ~/rpmbuild/SOURCES/ directory.
  • The unpopulated ~/rpmbuild/SPECS/<name>.spec SPEC file has been created by the rpmdev-newspec utility.

Procedure

  1. Open the output template of the ~/rpmbuild/SPECS/<name>.spec file provided by the rpmdev-newspec utility:

    1. Populate the first section of the SPEC file that includes the following directives that rpmdev-newspec grouped together:

      Name
      The Name was already specified as an argument to rpmdev-newspec.
      Version
      Set the Version to match the upstream release version of the source code.
      Release
      The Release is automatically set to 1%{?dist}, which is initially 1. Increase the initial value whenever updating the package without a change in the upstream release Version, for example, when including a patch. Reset Release to 1 when a new upstream release happens.
      Summary
      The Summary is a short, one-line explanation of what this software is.
    2. Populate the License, URL, and Source0 directives:

      License

      The License field is the Software License associated with the source code from the upstream release. The exact format for how to label the License in your SPEC file varies depending on which specific RPM based Linux distribution guidelines you are following.

      For example, you can use GPLv3+.

      URL
      The URL field provides a URL to the upstream software website. For consistency, utilize the RPM macro variable of %{name}, and use https://example.com/%{name}.
      Source
      The Source0 field provides URL to the upstream software source code. It must 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.
    3. Populate the BuildRequires, Requires and BuildArch directives:

      BuildRequires
      BuildRequires specifies build-time dependencies for the package.
      Requires
      Requires specifies run-time dependencies for the package.
      BuildArch
      This is a software written in an interpreted programming language with no natively compiled extensions. Therefore, add the BuildArch directive with the noarch value. This tells RPM that this package does not need to be bound to the processor architecture on which it is built.
    4. Populate the %description, %prep, %build, %install, %files, and %license directives. You can think of these directives as section headings, because they are directives that can define multi-line, multi-instruction, or scripted tasks to occur.

      %description
      The %description is a longer, fuller description of the software than Summary. This directive contains one or more paragraphs.
      %prep
      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.
      %build
      The %build section specifies how to build the software.
      %install

      The %install section contains instructions for rpmbuild on how to install the software, once it has been built, into the BUILDROOT 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.

      %files

      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 by using the rpm command. For example, to indicate that the LICENSE file is a software license file, use the %license macro.

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

      Start the first line of the %changelog section with an * 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 - character.

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

4.5.3. 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.
Note

For installing bello you only need to 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

Name:           pello
Version:        0.1.1
Release:        1%{?dist}
Summary:        Hello World example implemented in Python

License:        GPLv3+
URL:            https://www.example.com/%{name}
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz

BuildRequires:  python
Requires:       python
Requires:       bash

BuildArch:      noarch

%description
The long-tail description for our Hello World Example implemented in Python.

%prep
%setup -q

%build

python -m compileall %{name}.py

%install

mkdir -p %{buildroot}/%{_bindir}
mkdir -p %{buildroot}/usr/lib/%{name}

cat > %{buildroot}/%{_bindir}/%{name} <<EOF
#!/bin/bash
/usr/bin/python /usr/lib/%{name}/%{name}.pyc
EOF

chmod 0755 %{buildroot}/%{_bindir}/%{name}

install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/

%files
%license LICENSE
%dir /usr/lib/%{name}/
%{_bindir}/%{name}
/usr/lib/%{name}/%{name}.py*

%changelog
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1.1-1
  - First pello package

Important

The pello program is written in a byte-compiled interpreted language. Therefore, the shebang is not applicable because the resulting file does not contain the entry.

Because the shebang is not applicable, you might want to apply one of the following approaches:

  • Create a non-byte-compiled shell script that will call the executable.
  • Provide a small bit of the Python code that is not byte-compiled as the entry point into the program’s execution.

These approaches are useful especially for large software projects with many thousands of lines of code, where the performance increase of pre-byte-compiled code is sizeable.

  • The Requires directive, which specifies run-time dependencies for the package, includes two packages:

    • The python package is needed to execute the byte-compiled code at runtime
    • The bash package is needed to execute the small entry-point script
  • The BuildRequires directive, which specifies build-time dependencies for the package, includes only the python package. The pello program requires the python package to perform the byte-compile build process.
  • The %build section, which specifies how to build the software, corresponds to the fact that the software is byte-compiled.

To install pello, you need to create a wrapper script because the shebang is not applicable in byte-compiled languages. You can create this script either of the following ways:

  • Make a separate script and use it as a separate SourceX directive.
  • Create the file in-line in the SPEC file.

This example shows creating a wrapper script in-line in the SPEC file to demonstrate that the SPEC file itself is scriptable. This wrapper script will execute the Python byte-compiled code by using a here document.

The %install section in this example also corresponds to the fact that you will need to install the byte-compiled file into a library directory on the system such that it can be accessed.

Additional resources

4.5.5. 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, therefore, you can use the GNU make command provided by the rpmdev-newspec utility. However, you need to 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 that is provided by the rpmdev-newspec command. This is possible because the Makefile for the cello program is available.

Additional resources

4.6. Building RPMs

You can build RPM packages by using 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

In the following sections, learn how to build an RPM after you have created a SPEC file for a program:

4.6.1. Building source RPMs

To build a source RPM, complete the following steps.

Prerequisites

  • A SPEC file for the program that you want to package must already exist.

Procedure

  • Run the rpmbuild command with the specified SPEC file:

    $ rpmbuild -bs specfile

    Replace specfile with the name of the SPEC file. The -bs option stands for the build source.

Verification steps

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

Example 4.2. Building source RPMs for bello, pello, and cello.

The following is an example of building source RPMs for the bello, pello, and cello projects.

  1. Go to the ~/rpmbuild/SPECS/ directive, which contains the created SPEC file:

    $ cd ~/rpmbuild/SPECS/
  2. Run the rpmbuild command with the specified SPEC file:

    $ 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

4.6.2. Rebuilding a binary RPM from a source RPM

To rebuild a binary RPM from a source RPM (SRPM), complete the following steps.

Procedure

  • To rebuild bello, pello, and cello 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]
Note

Invoking rpmbuild --rebuild involves:

  • Installing the contents of the SRPM (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.

To retain the SPEC file and the source code after building, complete either of the following steps:

  • When building an RPM, use the rpmbuild command with the --recompile option instead of the --rebuild option.
  • Install the 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%]

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

4.6.3. Building a binary RPM from the SPEC file

To build bello, pello, and cello binary RPMs from their SPEC files, complete the following steps.

Procedure

  • Run the rpmbuild command with the bb option:

    $ rpmbuild -bb ~/rpmbuild/SPECS/bello.spec
    
    $ rpmbuild -bb ~/rpmbuild/SPECS/pello.spec
    
    $ rpmbuild -bb ~/rpmbuild/SPECS/cello.spec

4.6.4. Building binary RPMs from source RPMs

You build any kind of RPM from a source RPM. To do so, complete the following steps.

Procedure

  • Run the rpmbuild command with one of the following options and with the source package specified:

    # rpmbuild {-ra|-rb|-rp|-rc|-ri|-rl|-rs} [rpmbuild-options] source-package

    Replace source-package with the name of the source RPM.

Additional resources

  • rpmbuild(8) man page

4.7. Checking RPMs for sanity

After creating a package, you must 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. 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 examples.

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 bello for sanity

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

4.7.1.1. Checking the bello SPEC File for sanity

Inspect the outputs of the following examples to learn how to check a bello SPEC file for sanity.

Example 4.3. Output of running the rpmlint command on the SPEC file for bello

The following is an example output of the rpmlint command run 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 warning. 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.

Example 4.4. Output of running the rpmlint command on the SRPM for bello

The following is an example output of the rpmlint command run on the bello source RPM (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. 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.1.2. Checking the bello binary RPM for sanity

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

Example 4.5. Output of running the rpmlint command on the binary RPM for bello

The following is an example output of the rpmlint command run 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 pello for sanity

In the following sections, investigate possible warnings and errors that can occur when checking RPM sanity on the example of the pello SPEC file and pello binary RPM.

4.7.2.1. Checking the pello SPEC File for sanity

Inspect the outputs of the following examples to learn how to check a pello SPEC file for sanity.

Example 4.6. Output of running the rpmlint command on the SPEC file for pello

The following is an example output of the rpmlint command run 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.

Example 4.7. Output of running the rpmlint command on the SRPM for pello

The following is an example output of the rpmlint command run on the pello source RPM (SRPM).

$ 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 is about the URL directive, which 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 sanity

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

Example 4.8. Output of running the rpmlint command on the binary RPM for pello

The following is an example output of the rpmlint command run 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 normally reserved 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. 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 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 executing permissions and ignore this error.

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

4.7.3. Checking cello for sanity

In the following sections, investigate possible warnings and errors that can occur when checking RPM sanity on the example of the cello SPEC file and cello binary RPM.

4.7.3.1. Checking the cello SPEC File for sanity

Inspect the outputs of the following examples to learn how to check a cello SPEC file for sanity.

Example 4.9. Output of running the rpmlint command on the SPEC file for cello

The following is an example output of the rpmlint command run 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 warning. 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.

Example 4.10. Output of running the rpmlint command on the SRPM for cello

The following is an example output of the rpmlint command run on the cello source RPM (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 sanity

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

Example 4.11. Output of running the rpmlint command on the binary RPM for cello

The following is an example output of the rpmlint command run 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

Any RPM activity or transaction can be logged by the System Logging protocol (syslog).

Prerequisites

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

    # yum 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.

To see the updates on RPM activity, complete the following steps.

Procedure

  1. 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.
  2. Search for new lines including the [RPM] string.

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

Note

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

To convert an RPM payload to a tar archive by using the rpm2archive utility, complete the following steps.

Procedure

  • Run the rpm2archive command on the RPM file:

    $ rpm2archive filename.rpm

    Replace filename with the name of the .rpm file.

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

    $ rpm2archive bash-4.4.19-6.el8.x86_64.rpm
    bash-4.4.19-6.el8.x86_64.rpm.tgz