Packaging and distributing software
Packaging software by using the RPM package management system
Abstract
Providing feedback on Red Hat documentation Copy linkLink copied to clipboard!
We appreciate your feedback on our documentation. Let us know how we can improve it.
Submitting feedback through Jira (account required)
- Log in to the Jira website.
- Click Create in the top navigation bar
- Enter a descriptive title in the Summary field.
- Enter your suggestion for improvement in the Description field. Include links to the relevant parts of the documentation.
- Click Create at the bottom of the dialogue.
Chapter 1. Introduction to RPM Copy linkLink copied to clipboard!
The RPM Package Manager (RPM) is a package management system that runs on Red Hat Enterprise Linux (RHEL), CentOS, and Fedora. You can use RPM to distribute, manage, and update software that you create for any of these operating systems.
The RPM package management system has the following advantages over distributing software in conventional archive files:
- RPM manages software in the form of packages that you can install, update, or remove independently of each other, which makes the maintenance of an operating system easier.
- RPM simplifies the distribution of software because RPM packages are standalone binary files, similar to compressed archives. These packages are built for a specific operating system and hardware architecture. RPMs contain files such as compiled executables and libraries that are placed into the appropriate paths on the filesystem when the package is installed.
With RPM, you can perform the following tasks:
- Install, upgrade, and remove packaged software.
- Query detailed information about packaged software.
- Verify the integrity of packaged software.
- Build your own packages from software sources and complete build instructions.
- Digitally sign your packages by using the GNU Privacy Guard (GPG) utility.
- Publish your packages in a DNF repository.
In Red Hat Enterprise Linux, RPM is fully integrated into the higher-level package management software, such as DNF or PackageKit. Although RPM provides its own command-line interface, most users need to interact with RPM only through this software. However, when building RPM packages, you must use the RPM utilities such as rpmbuild(8).
1.1. RPM packages Copy linkLink copied to clipboard!
An RPM package consists of an archive of files and metadata used to install and erase these files. Specifically, the RPM package contains the following parts:
GPG signature
The GPG signature is used to verify the integrity of the package.
Header (package metadata)
The RPM package manager uses this metadata to determine package dependencies, where to install files, and other information.
Payload
The payload is a
cpioarchive that contains files to install to the system.
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
specfile, which describes how to build the source code into a binary RPM. Optionally, the SRPM can contain patches to source code.Binary RPM
A binary RPM contains the binaries built from the sources and patches.
1.2. Listing RPM packaging utilities Copy linkLink copied to clipboard!
In addition to the rpmbuild(8) program for building packages, RPM provides other utilities to make the process of creating packages easier. You can find these programs in the rpmdevtools package.
Prerequisites
The
rpmdevtoolspackage has been installed:dnf install rpmdevtools
# dnf install rpmdevtoolsCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Use one of the following methods to list RPM packaging utilities:
To list certain utilities provided by the
rpmdevtoolspackage and their short descriptions, enter:rpm -qi rpmdevtools
$ rpm -qi rpmdevtoolsCopy to Clipboard Copied! Toggle word wrap Toggle overflow To list all utilities, enter:
rpm -ql rpmdevtools | grep ^/usr/bin
$ rpm -ql rpmdevtools | grep ^/usr/binCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Chapter 2. Setting up RPM packaging workspace Copy linkLink copied to clipboard!
To build RPM packages, you must first create a special workspace that consists of directories used for different packaging purposes.
2.1. Configuring RPM packaging workspace Copy linkLink copied to clipboard!
To configure the RPM packaging workspace, you can set up a directory layout by using the rpmdev-setuptree utility.
Prerequisites
You installed the
rpmdevtoolspackage, which provides utilities for packaging RPMs:dnf install rpmdevtools
# dnf install rpmdevtoolsCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Run the
rpmdev-setuptreeutility:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
2.2. RPM packaging workspace directories Copy linkLink copied to clipboard!
The following are the RPM packaging workspace directories created by using the rpmdev-setuptree utility:
| Directory | Purpose |
|---|---|
|
|
Contains build artifacts compiled from the source files from the |
|
|
Binary RPMs are created under the |
|
|
Contains compressed source code archives and patches. The |
|
|
Contains |
|
|
When you use the |
Chapter 3. RPM macros Copy linkLink copied to clipboard!
An RPM macro is a straight text substitution that, in addition to simple literal substitution, can perform various string operations, evaluate expressions, interact with the OS, and other actions.
3.1. Displaying the built-in RPM macros Copy linkLink copied to clipboard!
RPM provides multiple built-in macros that you can use to simplify package maintenance and make it consistent across packages.
Procedure
Display the built-in RPM macros:
rpm --showrc|grep "<builtin>”
$ rpm --showrc|grep "<builtin>”Copy to Clipboard Copied! Toggle word wrap Toggle overflow
3.2. Displaying RPM distribution macros Copy linkLink copied to clipboard!
Different distributions provide distinct sets of recommended RPM macros based on the language implementation of the software being packaged or the specific guidelines of the distribution. The sets of recommended RPM macros are often provided as RPM packages, ready to be installed by using the DNF package manager. You can find the installed macro files in the /usr/lib/rpm/macros.d/ directory.
Procedure
Display the raw RPM macro definitions:
rpm --showrc
$ rpm --showrcCopy to Clipboard Copied! Toggle word wrap Toggle overflow Determine what a macro does and how it can be helpful when packaging RPMs:
rpm --showrc | grep <macro_name>
$ rpm --showrc | grep <macro_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Optional: Display information about the RPMs macros for your system version of RPM:
rpm -ql rpm | grep macros
$ rpm -ql rpm | grep macrosCopy to Clipboard Copied! Toggle word wrap Toggle overflow
3.3. Customizing RPM behavior by using macros Copy linkLink copied to clipboard!
You can customize RPM behavior by editing the RPM macros. You can override any macros, except the built-in macros, in the ~/.rpmmacros file with your custom macros. Any changes that you make affect every build on every system sharing the same home directory.
To override macros on a per-machine basis, put these macros in a /etc/rpm/macros.* file.
It is not recommended to use new macros that you defined in the ~/.rpmmacros file in packaging. Such macros would not be present on other machines, where users might want to try to rebuild your package.
Procedure
Customize a macro:
%_topdir /opt/<directory>/rpmbuild
%_topdir /opt/<directory>/rpmbuildCopy to Clipboard Copied! Toggle word wrap Toggle overflow You can create the
<directory>, including all subdirectories, by using therpmdev-setuptreeutility.Note that the value of this macro is by default
~/rpmbuild.
3.4. Defining custom RPM macros in a spec file Copy linkLink copied to clipboard!
In addition to using the built-in and distribution RPM macros, you can define custom RPM macros to simplify package maintenance and make it consistent across packages. RPM spec files can use either the %define and %global macros.
The differences between the %define and %global macros are the following:
-
%definehas global scope, except when used in a parametric macro, where its scope is local to this macro. The body of the%definemacro is expanded when used. -
%globalhas global scope. The body of the%globalmacro is expanded at definition time.
Use %global macros for the following actions:
- To avoid multiple redundant evaluations
- To define global macros inside parametric macros
Otherwise, use %define macros.
The %define and %global macro use the %global <name> <body> or %define <name>[(opts)] <body> pattern:
-
All whitespace, the preceding and succeeding, that surrounds
<body>is removed during the macro expansion. -
The macro name might be composed of alphanumeric characters and the underscore (
_) character. Inclusion of the
(opts)field is optional:-
Simple macros do not contain the
(opts)field. In this case, only recursive macro expansion is performed. -
Parametric options are function-like macros that accept arguments and possible options. For more details, see the
/usr/share/doc/rpm/macros.mdfile.
-
Simple macros do not contain the
Macros are evaluated and expanded everywhere in the spec file, even on lines commented by using the hash (#) and in spec file sections, such as %changelog.
To escape macro expansion, you can use the %dnl macro which comments out everything up to the next new line.
You can also escape macro expansion by placing a second percent sign (%) in front of the macro, for example %%{name}.
For more information about macros, see the /usr/share/doc/rpm/macros.md file.
Procedure
Define the macro. For example, you can include the following line in the RPM
specfile.%define date 20241114 %define upstream_version 2.5.4-pre1
%define date 20241114 %define upstream_version 2.5.4-pre1Copy to Clipboard Copied! Toggle word wrap Toggle overflow
3.5. Common RPM directives in the %files section of spec Copy linkLink copied to clipboard!
The following are the RPM directives that you can use in the %files section of a spec file.
| Macro | Definition |
|---|---|
|
|
The |
|
|
The Important
Documentation can be excluded during package installation, for example, to conserve disk space on images. License files might look like documentation files, but they must always be installed with the software. Therefore, you must use the
The |
|
|
The Example usage: %dir %{_libdir}/%{name}
|
|
|
The Example usage: %config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf
|
3.6. The %autosetup and %setup macros Copy linkLink copied to clipboard!
You can use the %autosetup macro to unpack the source archives and apply patches automatically without manually specifying each patch by using the %patch directive.
%autosetup applies patches in the order they appear in the spec file. Always consider keeping sources and patches sorted by their number in spec to avoid unexpected actions. Alternatively, avoid the numbering entirely by using %patchlist or non-numbered Patch entries.
You can also use the %setup macro to unpack the source archives for building RPM packages.
Use the %autosetup macro whenever possible, instead of the %setup macro.
3.6.1. The %autosetup macro options Copy linkLink copied to clipboard!
You can use the following %autosetup macro options to control its behavior. %autosetup also accepts all %setup macro options.
You can combine the %autosetup macro options.
| Macro option | Description |
|---|---|
|
|
Use the |
|
|
Use the |
|
|
Use the |
|
|
Use the |
3.6.2. The %autopatch macro options Copy linkLink copied to clipboard!
The %autopatch macro applies all patches in the order stated in a spec file. You can use the following %autopatch macro options to control its behavior.
You can combine the %autopatch macro options.
| Macro option | Description |
|---|---|
|
|
Use the |
|
|
Use the |
|
|
Use the |
|
|
Use the |
|
|
Use the |
3.6.3. The %setup macro options Copy linkLink copied to clipboard!
You can use the following %setup macro options for controlling the unpacking of source archives.
You can combine the %setup macro options.
| Macro option | Description |
|---|---|
|
|
Use the |
|
|
Use the
For example, you can use this option when the directory from the expanded source code archive has a different name from what is expected ( Name: cello
Source0: https://example.com/%{name}/release/hello-%{version}.tar.gz
...
%prep
%setup -n hello
|
|
|
Use the /usr/bin/mkdir -p cello-1.0 cd 'cello-1.0'
The directory is not changed after archive expansion. |
|
|
Use the rm -rf 'cello-1.0'
|
|
|
Use the /usr/bin/gzip -dc '/builddir/build/SOURCES/cello-1.0.tar.gz' | /usr/bin/tar -xvvof -
|
|
|
Use the
For example, examples are provided in a separate Source0: https://example.com/%{name}/release/%{name}-%{version}.tar.gz
Source1: %{name}-%{version}-examples.tar.gz
...
%prep
%setup -b 1
|
|
|
Use the
For example, the Source0: https://example.com/%{name}/release/%{name}-%{version}.tar.gz
Source1: examples.tar.gz
...
%prep
%setup -a 1
|
Chapter 4. Creating software for RPM packaging Copy linkLink copied to clipboard!
To prepare software for RPM packaging, you must understand what source code is and how to create software.
4.1. What is source code Copy linkLink copied to clipboard!
Source code is human-readable instructions to the computer that describe how to perform a computation. Source code is expressed by using a programming language.
The following versions of the Hello World program written in three different programming languages cover major RPM Package Manager use cases:
Hello Worldwritten in BashThe bello project implements
Hello Worldin Bash. The implementation contains only thebelloshell script. The purpose of this program is to outputHello Worldon the command line.The
bellofile has the following contents:#!/bin/bash printf "Hello World\n"
#!/bin/bash printf "Hello World\n"Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Hello Worldwritten in PythonThe pello project implements
Hello Worldin Python. The implementation contains only thepello.pyprogram. The purpose of the program is to outputHello Worldon the command line.The
pello.pyfile has the following contents:#!/usr/bin/python3 print("Hello World")#!/usr/bin/python3 print("Hello World")Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Hello Worldwritten in CThe cello project implements
Hello Worldin C. The implementation contains only thecello.candMakefilefiles. The resultingtar.gzarchive therefore has two files in addition to theLICENSEfile. The purpose of the program is to outputHello Worldon the command line.The
cello.cfile has the following contents:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
The packaging process is different for each version of the Hello World program.
4.2. Methods of creating software Copy linkLink copied to clipboard!
You can convert the human-readable source code into machine code by using one the following methods:
- Natively compile software.
- Interpret software by using a language interpreter or language virtual machine. You can either raw-interpret or byte-compile software.
4.2.1. Natively compiled software Copy linkLink copied to clipboard!
Natively compiled software is software written in a programming language that compiles to machine code with a resulting binary executable file. Natively compiled software is standalone software.
Natively compiled RPM packages are architecture-specific.
If you compile such software on a computer that uses a 64-bit (x86_64) AMD or Intel processor, it does not run on a 32-bit (x86) AMD or Intel processor. The resulting package has the architecture specified in its name.
4.2.2. Interpreted software Copy linkLink copied to clipboard!
Some programming languages, such as Bash or Python, do not compile to machine code. Instead, a language interpreter or a language virtual machine executes the programs' source code step-by-step without prior transformations.
Software written entirely in interpreted programming languages is not architecture-specific. Therefore, the resulting RPM package has the noarch string in its name.
You can either raw-interpret or byte-compile software written in interpreted languages:
Raw-interpreted software
You do not need to compile this type of software. Raw-interpreted software is directly executed by the interpreter.
Byte-compiled software
You must first compile this type of software into bytecode, which is then executed by the language virtual machine.
NoteSome byte-compiled languages can be either raw-interpreted or byte-compiled.
Note that the way you build and package software by using RPM is different for these two software types.
4.3. Building software from source Copy linkLink copied to clipboard!
During the software building process, the source code is turned into software artifacts that you can package by using RPM.
4.3.1. Building software from natively compiled code Copy linkLink copied to clipboard!
You can build software written in a compiled language into an executable by using one of the following methods:
- Manual building
- Automated building
4.3.1.1. Manually building a sample C program Copy linkLink copied to clipboard!
You can use manual building to build software written in a compiled language.
A sample Hello World program written in C (cello.c) has the following contents:
Procedure
Invoke the C compiler from the GNU Compiler Collection to compile the source code into binary:
gcc -g -o cello cello.c
$ gcc -g -o cello cello.cCopy to Clipboard Copied! Toggle word wrap Toggle overflow Run the resulting binary
cello:./cello Hello World
$ ./cello Hello WorldCopy to Clipboard Copied! Toggle word wrap Toggle overflow
4.3.1.2. Setting automated building for a sample C program Copy linkLink copied to clipboard!
Large-scale software commonly uses automated building. You can set up automated building by creating the Makefile file and then running the GNU make utility.
Procedure
Create the
Makefilefile with the following content in the same directory ascello.c:cello: gcc -g -o cello cello.c clean: rm cello
cello: gcc -g -o cello cello.c clean: rm celloCopy to Clipboard Copied! Toggle word wrap Toggle overflow Note that the lines under
cello:andclean:must begin with a tabulation character (tab).Build the software:
make make: 'cello' is up to date.
$ make make: 'cello' is up to date.Copy to Clipboard Copied! Toggle word wrap Toggle overflow Because a build is already available in the current directory, enter the
make cleancommand, and then enter themakecommand again:make clean rm cello make gcc -g -o cello cello.c
$ make clean rm cello $ make gcc -g -o cello cello.cCopy to Clipboard Copied! Toggle word wrap Toggle overflow Note that trying to build the program again at this point has no effect because the GNU
makesystem detects the existing binary:make make: 'cello' is up to date.
$ make make: 'cello' is up to date.Copy to Clipboard Copied! Toggle word wrap Toggle overflow Run the program:
./cello Hello World
$ ./cello Hello WorldCopy to Clipboard Copied! Toggle word wrap Toggle overflow
4.3.2. Interpreting source code Copy linkLink copied to clipboard!
You can convert the source code written in an interpreted programming language into machine code by using one of the following methods:
Byte-compiling
The procedure for byte-compiling software varies depending on the following factors:
- Programming language
- Language’s virtual machine
Tools and processes used with that language
NoteYou can byte-compile software written, for example, in Python. Python software intended for distribution is often byte-compiled, but not in the way described in this document. The described procedure aims not to conform to the community standards, but to be simple. For real-world Python guidelines, see Software Packaging and Distribution.
You can also raw-interpret Python source code. However, the byte-compiled version is faster. Therefore, RPM packagers prefer to package the byte-compiled version for distribution to end users.
Raw-interpreting
Software written in shell scripting languages, such as Bash, is always executed by raw-interpreting.
4.3.2.1. Byte-compiling a sample Python program Copy linkLink copied to clipboard!
By choosing byte-compiling over raw-interpreting of Python source code, you can create faster software.
A sample Hello World program written in the Python programming language (pello.py) has the following contents:
print("Hello World")
print("Hello World")
Procedure
Byte-compile the
pello.pyfile:python -m compileall pello.py
$ python -m compileall pello.pyCopy to Clipboard Copied! Toggle word wrap Toggle overflow Verify that a byte-compiled version of the file is created:
ls __pycache__ pello.cpython-311.pyc
$ ls __pycache__ pello.cpython-311.pycCopy to Clipboard Copied! Toggle word wrap Toggle overflow Note that the package version in the output might differ depending on which Python version is installed.
Run the program in
pello.py:python pello.py Hello World
$ python pello.py Hello WorldCopy to Clipboard Copied! Toggle word wrap Toggle overflow
4.3.2.2. Raw-interpreting a sample Bash program Copy linkLink copied to clipboard!
A sample Hello World program written in Bash shell built-in language (bello) has the following contents:
#!/bin/bash printf "Hello World\n"
#!/bin/bash
printf "Hello World\n"
The shebang (#!) sign at the top of the bello file is not part of the programming language source code.
Use the shebang to turn a text file into an executable. The system program loader parses the line containing the shebang to get a path to the binary executable, which is then used as the programming language interpreter.
Procedure
Make the file with source code executable:
chmod +x bello
$ chmod +x belloCopy to Clipboard Copied! Toggle word wrap Toggle overflow Run the created file:
./bello Hello World
$ ./bello Hello WorldCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Chapter 5. Preparing software for RPM packaging Copy linkLink copied to clipboard!
To prepare a piece of software for packaging with RPM, you can first patch the software, create a LICENSE file for it, and archive it as a tarball.
5.1. Patching software Copy linkLink copied to clipboard!
When packaging software, you might need to make certain changes to the original source code, such as fixing a bug or changing a configuration file. In RPM packaging, you can instead leave the original source code intact and apply patches on it.
A patch is a piece of text that updates a source code file. The patch has a diff format, because it represents the difference between two versions of the text. You can create a patch by using the diff utility, and then apply the patch to the source code by using the patch utility.
Software developers often use version control systems such as Git to manage their code base. Such tools offer their own methods of creating diffs or patching software.
5.1.1. Creating a patch file for a sample C program Copy linkLink copied to clipboard!
You can create a patch from the original source code by using the diff utility. For example, to patch a Hello world program written in C (cello.c), complete the following steps.
Prerequisites
You installed the
diffutility on your system:dnf install diffutils
# dnf install diffutilsCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Back up the original source code:
cp -p cello.c cello.c.orig
$ cp -p cello.c cello.c.origCopy to Clipboard Copied! Toggle word wrap Toggle overflow The
-poption preserves mode, ownership, and timestamps.Modify
cello.cas needed:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Generate a patch:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Lines that start with
+replace the lines that start with-.NoteUsing the
Nauroptions with thediffcommand is recommended because it fits the majority of use cases:-N(--new-file)The
-Noption handles absent files as empty files.-a(--text)The
-aoption treats all files as text. As a result, thediffutility does not ignore the files it classified as binaries.-u(-U NUMor--unified[=NUM])The
-uoption returns output in the form of output NUM (default 3) lines of unified context. This is a compact and an easily readable format commonly used in patch files.-r(--recursive)The
-roption recursively compares any subdirectories that thediffutility found.
However, note that in this particular case, only the
-uoption is necessary.Save the patch to a file:
diff -Naur cello.c.orig cello.c > cello.patch
$ diff -Naur cello.c.orig cello.c > cello.patchCopy to Clipboard Copied! Toggle word wrap Toggle overflow Restore the original
cello.c:mv cello.c.orig cello.c
$ mv cello.c.orig cello.cCopy to Clipboard Copied! Toggle word wrap Toggle overflow ImportantYou must retain the original
cello.cbecause the RPM package manager uses the original file, not the modified one, when building an RPM package. For more information, see Working with spec files.
5.1.2. Patching a sample C program Copy linkLink copied to clipboard!
To apply code patches on your software, you can use the patch utility.
Prerequisites
You installed the
patchutility on your system:dnf install patch
# dnf install patchCopy to Clipboard Copied! Toggle word wrap Toggle overflow - You created a patch from the original source code. For instructions, see Creating a patch file for a sample C program.
Procedure
The following steps apply a previously created cello.patch file on the cello.c file.
Redirect the patch file to the
patchcommand:patch < cello.patch patching file cello.c
$ patch < cello.patch patching file cello.cCopy to Clipboard Copied! Toggle word wrap Toggle overflow Check that the contents of
cello.cnow reflect the desired change:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Verification
Build the patched
cello.cprogram:make gcc -g -o cello cello.c
$ make gcc -g -o cello cello.cCopy to Clipboard Copied! Toggle word wrap Toggle overflow Run the built
cello.cprogram:./cello Hello World from my very first patch!
$ ./cello Hello World from my very first patch!Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.2. Creating a LICENSE file Copy linkLink copied to clipboard!
It is recommended that you distribute your software with a software license.
A software license file informs users of what they can and cannot do with a source code. Having no license for your source code means that you retain all rights to this code and no one can reproduce, distribute, or create derivative works from your source code.
Procedure
Create the
LICENSEfile with the required license statement:vim LICENSE
$ vim LICENSECopy to Clipboard Copied! Toggle word wrap Toggle overflow Example 5.1. Example GPLv3
LICENSEfile textCopy to Clipboard Copied! Toggle word wrap Toggle overflow
5.3. Creating a source code archive for distribution Copy linkLink copied to clipboard!
An archive file is a file with the .tar.gz or .tgz suffix. Putting source code into the archive is a common way to release the software to be later packaged for distribution.
5.3.1. Creating a source code archive for a sample Bash program Copy linkLink copied to clipboard!
The bello project is a Hello World file in Bash.
The following example contains only the bello shell script. Therefore, the resulting tar.gz archive has only one file in addition to the LICENSE file.
The patch file is not distributed in the archive with the program. The RPM package manager applies the patch when the RPM is built. The patch will be placed into the ~/rpmbuild/SOURCES/ directory together with the tar.gz archive.
Prerequisites
-
Assume that the
0.1version of thebelloprogram is used. -
You created a
LICENSEfile. For instructions, see Creating a LICENSE file.
Procedure
Move all required files into a single directory:
mkdir bello-0.1 mv ~/bello bello-0.1/ mv LICENSE bello-0.1/
$ mkdir bello-0.1 $ mv ~/bello bello-0.1/ $ mv LICENSE bello-0.1/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create the archive for distribution:
tar -cvzf bello-0.1.tar.gz bello-0.1 bello-0.1/ bello-0.1/LICENSE bello-0.1/bello
$ tar -cvzf bello-0.1.tar.gz bello-0.1 bello-0.1/ bello-0.1/LICENSE bello-0.1/belloCopy to Clipboard Copied! Toggle word wrap Toggle overflow Move the created archive to the
~/rpmbuild/SOURCES/directory, which is the default directory where therpmbuildcommand stores the files for building packages:mv bello-0.1.tar.gz ~/rpmbuild/SOURCES/
$ mv bello-0.1.tar.gz ~/rpmbuild/SOURCES/Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.3.2. Creating a source code archive for a sample Python program Copy linkLink copied to clipboard!
The pello project is a Hello World file in Python.
The following example contains only the pello.py program. Therefore, the resulting tar.gz archive has only one file in addition to the LICENSE file.
The patch file is not distributed in the archive with the program. The RPM package manager applies the patch when the RPM is built. The patch will be placed into the ~/rpmbuild/SOURCES/ directory together with the tar.gz archive.
Prerequisites
-
Assume that the
0.1.1version of thepelloprogram is used. -
You created a
LICENSEfile. For instructions, see Creating a LICENSE file.
Procedure
Move all required files into a single directory:
mkdir pello-0.1.1 mv pello.py pello-0.1.1/ mv LICENSE pello-0.1.1/
$ mkdir pello-0.1.1 $ mv pello.py pello-0.1.1/ $ mv LICENSE pello-0.1.1/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create the archive for distribution:
tar -cvzf pello-0.1.1.tar.gz pello-0.1.1 pello-0.1.1/ pello-0.1.1/LICENSE pello-0.1.1/pello.py
$ tar -cvzf pello-0.1.1.tar.gz pello-0.1.1 pello-0.1.1/ pello-0.1.1/LICENSE pello-0.1.1/pello.pyCopy to Clipboard Copied! Toggle word wrap Toggle overflow Move the created archive to the
~/rpmbuild/SOURCES/directory, which is the default directory where therpmbuildcommand stores the files for building packages:mv pello-0.1.1.tar.gz ~/rpmbuild/SOURCES/
$ mv pello-0.1.1.tar.gz ~/rpmbuild/SOURCES/Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.3.3. Creating a source code archive for a sample C program Copy linkLink copied to clipboard!
The cello project is a Hello World file in C.
The following example contains only the cello.c and the Makefile files. Therefore, the resulting tar.gz archive has two files in addition to the LICENSE file.
The patch file is not distributed in the archive with the program. The RPM package manager applies the patch when the RPM is built. The patch will be placed into the ~/rpmbuild/SOURCES/ directory together with the tar.gz archive.
Prerequisites
-
Assume that the
1.0version of thecelloprogram is used. -
You created a
LICENSEfile. For instructions, see Creating a LICENSE file.
Procedure
Move all required files into a single directory:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create the archive for distribution:
tar -cvzf cello-1.0.tar.gz cello-1.0 cello-1.0/ cello-1.0/Makefile cello-1.0/cello.c cello-1.0/LICENSE
$ tar -cvzf cello-1.0.tar.gz cello-1.0 cello-1.0/ cello-1.0/Makefile cello-1.0/cello.c cello-1.0/LICENSECopy to Clipboard Copied! Toggle word wrap Toggle overflow Move the created archive to the
~/rpmbuild/SOURCES/directory, which is the default directory where therpmbuildcommand stores the files for building packages:mv cello-1.0.tar.gz ~/rpmbuild/SOURCES/
$ mv cello-1.0.tar.gz ~/rpmbuild/SOURCES/Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Chapter 6. Packaging software Copy linkLink copied to clipboard!
In the following sections, learn the basics of the packaging process with the RPM package manager.
6.1. About spec files Copy linkLink copied to clipboard!
A spec file is a file with instructions that the rpmbuild utility uses to build an RPM package. This file provides necessary information to the build system by defining instructions in a series of sections. These sections are defined in the Preamble and the Body part of the spec file:
- The Preamble section contains a series of metadata items that are used in the Body section.
- The Body section represents the main part of the instructions.
6.1.1. Preamble items of a spec file Copy linkLink copied to clipboard!
The following are some of the directives that you can use in the Preamble section of the RPM spec file.
| Directive | Definition |
|---|---|
|
|
A base name of the package that must match the |
|
| An upstream version number of the software. |
|
| The number of times the version of the package was released.
Set the initial value to |
|
| A brief one-line summary of the package. |
|
| A license of the software being packaged.
The exact format for how to label the |
|
| A full URL for more information about the software, for example, an upstream project website for the software being packaged. |
|
| A path or URL to the compressed archive of the unpatched upstream source code. This link must point to an accessible and reliable storage of the archive, for example, the upstream page, not the packager’s local storage.
You can apply the |
|
| A name of the first patch to apply to the source code, if necessary.
You can apply the
You can apply the patches individually by using the |
|
| An architecture that the software will be built for.
If the software is not architecture-dependent, for example, if you wrote the software entirely in an interpreted programming language, set the value to |
|
|
A comma- or whitespace-separated list of packages required to build the program written in a compiled language. There can be multiple entries of |
|
|
A comma- or whitespace-separated list of packages required by the software to run once installed. There can be multiple entries of |
|
|
If a piece of software cannot operate on a specific processor architecture, you can exclude this architecture in the |
|
|
A comma- or whitespace-separated list of packages that must not be installed on the system in order for your software to function properly when installed. There can be multiple entries of |
|
|
The
|
|
|
If you add the |
6.1.2. Body items of a spec file Copy linkLink copied to clipboard!
The following are the items used in the Body section of the RPM spec file.
| Directive | Definition |
|---|---|
|
| A full description of the software packaged in the RPM. This description can span multiple lines and can be broken into paragraphs. |
|
|
A command or series of commands to prepare the software for building, for example, for unpacking the archive in the |
|
| A command or series of commands to configure the software for building. |
|
| A command or series of commands for building the software into machine code (for compiled languages) or bytecode (for some interpreted languages). |
|
|
A command or series of commands that the
The
Note that |
|
| A command or series of commands for testing the software, for example, unit tests. |
|
| A list of files, provided by the RPM package, to be installed in the user’s system and their full path location on the system.
During the build, if there are files in the
Within the |
|
|
A record of changes that happened to the package between different |
6.1.3. Advanced spec file items Copy linkLink copied to clipboard!
A spec file can contain advanced items, such as Scriptlets, File triggers and Triggers. These directives influence not only the spec file, but also the target operating system on which the resulting RPM is installed by updating the system with information from the RPM. Scriptlets, File Triggers and Triggers take effect at different points during the installation process on the target system, not the build process:
- Scriptlets are unconditionally executed before or after the package is installed or deleted.
- Triggers are conditionally executed when their specified trigger condition matches other packages on the installed system or in a transaction.
- File triggers are conditionally executed when their specified path prefix matches other files on the installed system or in a transaction.
6.1.3.1. Scriptlets directives Copy linkLink copied to clipboard!
Scriptlets are arbitrary programs that execute at pre-determined slots related to a package’s lifetime, for example, before or after the package is installed or deleted. By default, scriptlets are short shell scripts declared by the various %pre or %post directives in a spec file. Use scriptlets only for tasks that cannot be done at build time or in a startup script.
Common scriptlet directives are similar to the spec file section headers, such as %build or %install. They are defined by multi-line segments of code, which are often written as a standard POSIX shell script. However, they can also be written in other programming languages that RPM accepts for the target machine’s distribution.
6.1.3.2. Scriptlets directives execution order Copy linkLink copied to clipboard!
Scriptlets directives have different order of execution:
-
%preand%postare executed before and after you installed a package. -
%preunand%postunare executed before and after you uninstalled the package. -
%pretransand %posttrans are executed at start and end of the transaction that installs the package, respectively.
During the package upgrade, the scriptlets are executed in the following order:
| Directive | Description |
|---|---|
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
6.1.3.3. Turning off scriptlets execution Copy linkLink copied to clipboard!
You can turn off the execution of any scriptlet by using the --no option with the scriptlet name.
You can also use the --noscripts option, which is equivalent to turning off the execution of all the following scriptlets:
-
--nopre -
--nopost -
--nopreun -
--nopostun -
--nopretrans -
--noposttrans -
--nopreuntrans -
--nopostuntrans
For more information, see the rpm man page on your system.
Procedure
Turn off the scriptlet execution:
rpm --no<scriptlet_name>
# rpm --no<scriptlet_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow For example, to turn off the execution of the
%pretransscriptlet, enter:rpm --nopretrans
# rpm --nopretransCopy to Clipboard Copied! Toggle word wrap Toggle overflow
6.1.3.4. Example macros for scriptlets Copy linkLink copied to clipboard!
The following are example macros that you can use for scriptlets in a spec file. These macros are real-world macros provided by the systemd-rpm-macros package. You can use these macros for packaging systemd-related things. You can also apply similar principles to other packages.
Packages that contain systemd unit files must use scriptlets to properly handle systemd services. systemd packages provide a set of macros to handle systemd scriptlet operations. For example:
%post %systemd_post httpd.service %preun %systemd_preun httpd.service
%post
%systemd_post httpd.service
%preun
%systemd_preun httpd.service
These macros expand to the following in a package:
The way macros behave is subject to change. For example, macros' behavior can change with a package’s development.
6.1.4. The Epoch directive Copy linkLink copied to clipboard!
If setting the Version spec file directive is not enough for comparing package versions, you can use an Epoch directive. For example, you can use Epoch to resolve upgrade path issues that, for example, occurred because of the upstream change in a version numbering scheme in an incompatible manner.
Epoch is a numeric field. If you assign a value to Epoch, it adds a qualifier that RPM uses when comparing package versions. Not having the Epoch directive listed in a spec file means Epoch is not set. This is contrary to the common belief that not setting Epoch results in an Epoch of 0. However, for processing purposes, if you do not set Epoch, RPM treats it the same as if the Epoch was set to 0, and vice versa.
Using Epoch in a spec file is usually omitted because, in the majority of cases, introducing an Epoch value distorts the expected RPM behavior when comparing versions of packages. Therefore, consider using Epoch as a last resort.
For example, you installed the foobar package with Epoch: 1 and Version: 1.0. Another packager packages foobar with Version: 2.0, but without the Epoch directive. As a result, the new version is never considered an update because the Epoch version is preferred over the traditional Name-Version-Release marker that signifies versioning for RPM packages.
6.1.5. Package versioning essentials Copy linkLink copied to clipboard!
The essential part of the package description is the information defined in the Name, Version, and Release (NVR) spec file directives. RPM uses this information to compare package versions and track package dependencies.
When working with RPMs, you can also see mentions of EVR (epoch-version-release), NEVR (name-epoch-version-release), and NEVRA (name-epoch-version-release-architecture). EVR is the full version information of the package that RPM always uses for comparison. RPM compares one component at a time, starting from the first component. RPM stops the comparison when it finds a difference in components. For example, if Epoch differs, RPM does not compare the rest of the EVR components.
You can display the NVR information for a specific package by querying the RPM database, for example:
rpm -q bash bash-4.4.19-7.el8.x86_64
# rpm -q bash
bash-4.4.19-7.el8.x86_64
Here, bash is the package name, 4.4.19 is the version, and 7.el8 is the release. The x86_64 marker is the package architecture. Unlike NVR, the architecture marker is not under direct control of the RPM packager, but is defined by the rpmbuild build environment. The exception to this is the architecture-independent noarch package.
The rpm -q command displays the package information in the NEVRA format by default.
6.2. spec file conditionals Copy linkLink copied to clipboard!
By using spec file conditionals, you can enable conditional inclusion of various sections of the spec file.
Conditionals usually deal with the following aspects:
- Architecture-specific sections.
- Operating system-specific sections.
- Compatibility issues between various versions of operating systems.
You can use spec conditionals for different purposes, for example:
Conditional expression (
%if). You can use%iffor multiple purposes. It can have, for example, the following syntax:“If expression is true, then do some action”:
%if expression ... %endif
%if expression ... %endifCopy to Clipboard Copied! Toggle word wrap Toggle overflow “If expression is true, then do some action, otherwise, another action”:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow %ifcan also be followed by an arbitrary number of%elifconditionals (nested%elsif), for example:%if expression %elif expression ... %else %endif
%if expression %elif expression ... %else %endifCopy to Clipboard Copied! Toggle word wrap Toggle overflow
System architecture (
%ifarch,%ifnarch).%ifarchtests whether the current target system architecture matches. You can use%ifarchto build RPM packages for multiple platforms, for example:%ifarch s390 s390x BuildRequires: s390utils-devel %endif
%ifarch s390 s390x BuildRequires: s390utils-devel %endifCopy to Clipboard Copied! Toggle word wrap Toggle overflow -
Operating system (
%ifos,%ifnos).%ifoscontrolsspecfile processing according to the build target operating system.
6.2.1. Example usage of the %if conditionals Copy linkLink copied to clipboard!
The following are examples of the usage of %if RPM conditionals.
Example 6.1. Using the %if conditional to handle compatibility between Red Hat Enterprise Linux 10 and other operating systems
%if 0%{?rhel} == 10
sed -i '/AS_FUNCTION_DESCRIBE/ s/^/#/' configure.in
sed -i '/AS_FUNCTION_DESCRIBE/ s/^/#/' acinclude.m4
%endif
%if 0%{?rhel} == 10
sed -i '/AS_FUNCTION_DESCRIBE/ s/^/#/' configure.in
sed -i '/AS_FUNCTION_DESCRIBE/ s/^/#/' acinclude.m4
%endif
When building a package on RHEL 10, this conditional comments out AS_FUNCTION_DESCRIBE lines from autoconf scripts being considered when the %rhel macro’s value is set to 10.
Example 6.2. Using the %if conditional to handle definition of macros
%define ruby_archive %{name}-%{ruby_version}
%if 0%{?milestone:1}%{?revision:1} != 0
%define ruby_archive %{ruby_archive}-%{?milestone}%{?!milestone:%{?revision:r%{revision}}}
%endif
%define ruby_archive %{name}-%{ruby_version}
%if 0%{?milestone:1}%{?revision:1} != 0
%define ruby_archive %{ruby_archive}-%{?milestone}%{?!milestone:%{?revision:r%{revision}}}
%endif
This conditional handles the definition of macros. If the %milestone or the %revision macros are set, the %ruby_archive macro, which defines the name of the upstream archive, is redefined.
6.2.2. Specialized variants of %if conditionals Copy linkLink copied to clipboard!
The specialized variants of the %if conditionals include the %ifarch, %ifnarch, and %ifos conditionals. These conditionals are commonly used and, therefore, have their own macros.
| Conditional | Description |
|---|---|
|
|
Use the %ifarch i386 sparc ... %endif
All the contents of the |
|
|
The %ifnarch aarch64 ... %endif
All the contents of the |
|
|
Use the %ifos linux ... %endif
All the contents of the spec file between |
6.3. BuildRoots Copy linkLink copied to clipboard!
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.
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.
6.4. Working with spec files Copy linkLink copied to clipboard!
To package new software, you must create a spec file. You can create the spec file either of the following ways:
-
Write the new
specfile manually from scratch. -
Use the
rpmdev-newspecutility. This utility creates an unpopulatedspecfile, where you fill 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.
6.4.1. Creating a new spec file for sample Bash, Python, and C programs Copy linkLink copied to clipboard!
You can create a spec file for each of the three implementations of the Hello World! program by using the rpmdev-newspec utility.
Prerequisites
The following
Hello World!program implementations were placed into the~/rpmbuild/SOURCESdirectory:
Procedure
Navigate to the
~/rpmbuild/SPECSdirectory:cd ~/rpmbuild/SPECS
$ cd ~/rpmbuild/SPECSCopy to Clipboard Copied! Toggle word wrap Toggle overflow Create a
specfile for each of the three implementations of theHello World!program:Copy to Clipboard Copied! Toggle word wrap Toggle overflow The
~/rpmbuild/SPECS/directory now contains threespecfiles namedbello.spec,cello.spec, andpello.spec.Examine the created files.
The directives in the files represent those described in About spec files. In the following sections, you will populate a particular section in the output files of
rpmdev-newspec.
6.4.2. Modifying an original spec file Copy linkLink copied to clipboard!
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
-
The unpopulated
~/rpmbuild/SPECS/<name>.specspecfile was created by using therpmdev-newspecutility. For more information, see Creating a new spec file for sample Bash, Python, and C programs.
Procedure
-
Open the
~/rpmbuild/SPECS/<name>.specfile provided by therpmdev-newspecutility. Populate the following directives of the
specfile Preamble section:Name-
Namewas already specified as an argument torpmdev-newspec. Version-
Set
Versionto match the upstream release version of the source code. Release-
Releaseis automatically set to1%{?dist}, which is initially1. 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 thehttps://example.com/%{name}format. SourceEnter the URL to the upstream software source code. Link directly to the software version being packaged.
NoteThe 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 thespecfile.BuildRequires- Specify build-time dependencies for the package.
Requires- Specify run-time dependencies for the package.
BuildArch- Specify the software architecture.
Populate the following directives of the
specfile 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.
%conf- Enter a command or series of commands to configure 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
rpmbuildcommand on how to install the software into theBUILDROOTdirectory. %files- Specify the list of files, provided by the RPM package, to be installed on your system.
%changelogEnter the list of datestamped entries for each
Version-Releaseof the package.Start the first line of the
%changelogsection with an asterisk (*) character followed byDay-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.
6.4.3. An example spec file for a sample Bash program Copy linkLink copied to clipboard!
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
-
The
BuildRequiresdirective, which specifies build-time dependencies for the package, was deleted because there is no building step forbello. Bash is a raw interpreted programming language, and the files are just installed to their location on the system. -
The
Requiresdirective, which specifies run-time dependencies for the package, includes onlybash, because thebelloscript requires only thebashshell environment to execute. -
The
%buildsection, which specifies how to build the software, is blank, because thebashscript does not need to be built.
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.
6.4.4. An example spec file for a sample Python program Copy linkLink copied to clipboard!
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
The
Requiresdirective, which specifies run-time dependencies for the package, includes two packages:-
The
pythonpackage required to execute the byte-compiled code at runtime. -
The
bashpackage required to execute the small entry-point script.
-
The
-
The
BuildRequiresdirective, which specifies build-time dependencies for the package, includes only thepythonpackage. Thepelloprogram requirespythonto perform the byte-compile build process. -
The
%buildsection, which specifies how to build the software, creates a byte-compiled version of the script. Note that in real-world packaging, it is usually done automatically, depending on the distribution used. -
The
%installsection corresponds to the fact that you must install the byte-compiled file into a library directory on the system so that it can be accessed.
This example of creating a wrapper script in-line in the spec file shows that the spec file itself is scriptable. This wrapper script executes the Python byte-compiled code by using the here document.
6.4.5. An example spec file for a sample C program Copy linkLink copied to clipboard!
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
The
BuildRequiresdirective, which specifies build-time dependencies for the package, includes the following packages required to perform the compilation build process:-
gcc -
make
-
-
The
Requiresdirective, which specifies run-time dependencies for the package, is omitted in this example. All runtime requirements are handled byrpmbuild, and thecelloprogram does not require anything outside of the core C standard libraries. -
The
%buildsection reflects the fact that in this example theMakefilefile for the cello program was written. Therefore, you can use the GNU make command. However, you must remove the call to%configurebecause 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.
6.5. Building RPMs Copy linkLink copied to clipboard!
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
specfile.
6.5.1. Building a source RPM Copy linkLink copied to clipboard!
Building a Source RPM (SRPM) has the following advantages:
-
You can preserve the exact source of a certain
Name-Version-Releaseof an RPM file that was deployed to an environment. This includes the exactspecfile, 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
You have installed the
rpmbuildutility on your system:dnf install rpm-build
# dnf install rpm-buildCopy to Clipboard Copied! Toggle word wrap Toggle overflow The following
Hello World!implementations were placed into the~/rpmbuild/SOURCES/directory:-
A
specfile for the program that you want to package exists.
Procedure
Navigate to the
~/rpmbuild/SPECS/directive, which contains the createdspecfile:cd ~/rpmbuild/SPECS/
$ cd ~/rpmbuild/SPECS/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Build the source RPM by entering the
rpmbuildcommand with the specifiedspecfile:rpmbuild -bs <specfile>
$ rpmbuild -bs <specfile>Copy to Clipboard Copied! Toggle word wrap Toggle overflow The
-bsoption stands for the build source.For example, to build source RPMs for the
bello,pello, andcelloprograms, enter:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Verification
-
Verify that the
rpmbuild/SRPMSdirectory includes the resulting source RPMs. The directory is a part of the structure expected byrpmbuild.
6.5.2. Rebuilding a binary RPM from a source RPM Copy linkLink copied to clipboard!
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 either of the following directories:
-
~/rpmbuild/RPMS/YOURARCH, whereYOURARCHis your architecture. -
~/rpmbuild/RPMS/noarch/, if the package is not architecture-specific.
Prerequisites
You have installed the
rpmbuildutility on your system:dnf install rpm-build
# dnf install rpm-buildCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Navigate to the
~/rpmbuild/SRPMS/directive, which contains the SRPM:cd ~/rpmbuild/SRPMS/
$ cd ~/rpmbuild/SRPMS/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Rebuild the binary RPM from the SRPM:
rpmbuild --rebuild <srpm>
$ rpmbuild --rebuild <srpm>Copy to Clipboard Copied! Toggle word wrap Toggle overflow For example, to rebuild
bello,pello, andcellofrom their SRPMs, enter:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Invoking rpmbuild --rebuild involves the following processes:
-
Installing the contents of the SRPM (the
specfile and the source code) into the~/rpmbuild/directory. - Building an RPM by using the installed contents.
-
Removing the
specfile 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
rpmbuildcommand with the--recompileoption instead of the--rebuildoption. Install SRPMs for
bello,pello, andcello:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
6.5.3. Building a binary RPM from a spec file Copy linkLink copied to clipboard!
To build a binary RPM from its spec file, use the rpmbuild command with the -bb option.
Prerequisites
You have installed the
rpmbuildutility on your system:dnf install rpm-build
# dnf install rpm-buildCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Navigate to the
~/rpmbuild/SPECS/directive, which containsspecfiles:cd ~/rpmbuild/SPECS/
$ cd ~/rpmbuild/SPECS/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Build the binary RPM from its
spec:rpmbuild -bb <spec_file>
$ rpmbuild -bb <spec_file>Copy to Clipboard Copied! Toggle word wrap Toggle overflow For example, to build
bello,pello, andcellobinary RPMs from theirspecfiles, enter:rpmbuild -bb bello.spec rpmbuild -bb pello.spec rpmbuild -bb cello.spec
$ rpmbuild -bb bello.spec $ rpmbuild -bb pello.spec $ rpmbuild -bb cello.specCopy to Clipboard Copied! Toggle word wrap Toggle overflow
6.6. Logging RPM activity to syslog Copy linkLink copied to clipboard!
You can log any RPM activity or transaction by using the System Logging protocol (syslog).
Prerequisites
The
syslogplug-in is installed on the system:dnf install rpm-plugin-syslog
# dnf install rpm-plugin-syslogCopy to Clipboard Copied! Toggle word wrap Toggle overflow NoteThe default location for the
syslogmessages is the/var/log/messagesfile. However, you can configuresyslogto use another location to store the messages.
Procedure
Open the file that you configured to store the
syslogmessages.Alternatively, if you use the default
syslogconfiguration, open the/var/log/messagesfile.-
Search for new lines including the
[RPM]string.
6.7. Extracting RPM content Copy linkLink copied to clipboard!
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.
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
$ rpm2archive <filename>.rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow The resulting file has the
.tgzsuffix. For example, to create an archive from thebashpackage, 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
$ 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.tgzCopy to Clipboard Copied! Toggle word wrap Toggle overflow
6.8. Signing RPM packages Copy linkLink copied to clipboard!
You can sign RPM packages to ensure no third party can alter their content by using either of the following software:
- Sequoia PGP supports the OpenPGP standard. RPM also uses Sequoia PGP to verify software signatures.
- GNU Privacy Guard (GnuPG) supports older OpenPGP standard versions, which makes GnuPG more compatible with RHEL 9 and earlier versions.
Starting from version 10.1, RHEL supports OpenPGPv6 and RPMv6 signatures. These signatures are not compatible with earlier versions of RHEL. RPM on these versions ignore such signatures. If a package contains the RPMv4 signature, RPM uses it instead.
However, in RHEL 9.7 and later RHEL 9 versions, you can enable support for OpenPGPv6 and RPMv6 signatures by using the multisig DNF plugin.
6.8.1. Signing RPM packages with GnuPG Copy linkLink copied to clipboard!
You can sign RPM packages by using the GNU Privacy Guard (GnuPG) software.
6.8.1.1. Creating an OpenPGP key for signing packages with GnuPG Copy linkLink copied to clipboard!
To sign an RPM package by using the GNU Privacy Guard (GnuPG) software, you must create an OpenPGP key first.
Prerequisites
-
You have the
rpm-signandpinentrypackages installed on your system.
Procedure
Generate an OpenPGP key pair:
gpg --gen-key
$ gpg --gen-keyCopy to Clipboard Copied! Toggle word wrap Toggle overflow Check the generated key pair:
gpg --list-keys
$ gpg --list-keysCopy to Clipboard Copied! Toggle word wrap Toggle overflow Export the public key:
gpg --export -a '<public_key_name>' > RPM-GPG-KEY-pmanager
$ gpg --export -a '<public_key_name>' > RPM-GPG-KEY-pmanagerCopy to Clipboard Copied! Toggle word wrap Toggle overflow
6.8.1.2. Configuring RPM to sign a package with GnuPG Copy linkLink copied to clipboard!
To sign an RPM package by using the GNU Privacy Guard (GnuPG) software, you must configure RPM by specifying the %_gpg_name RPM macro.
Prerequisites
- You created an OpenPGP key for GnuPG, For more information, see Creating an OpenPGP key for signing packages with GnuPG.
Procedure
Define the
%_gpg_namemacro in your$HOME/.rpmmacrosdirectory:%_gpg_name <key_ID>
%_gpg_name <key_ID>Copy to Clipboard Copied! Toggle word wrap Toggle overflow A valid key ID value for GnuPG can be a key fingerprint, full name, or email address you provided when creating the key.
6.8.1.3. Adding a signature to an RPM package Copy linkLink copied to clipboard!
Packages are commonly built without signatures. You can add your signature before the package is released.
Prerequisites
- You created an OpenPGP key for GnuPG. For more information, see Creating an OpenPGP key for signing packages with GnuPG.
- You configured RPM for signing packages. For more information, see Configuring RPM to sign a package with GnuPG.
-
You have the
rpm-signpackage installed on your system.
Procedure
Add a signature to a package:
rpmsign --addsign <package-name>.rpm
$ rpmsign --addsign <package-name>.rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Verification
Import the exported OpenPGP public key into the RPM keyring:
rpmkeys --import RPM-GPG-KEY-pmanager
# rpmkeys --import RPM-GPG-KEY-pmanagerCopy to Clipboard Copied! Toggle word wrap Toggle overflow Display the key ID with GnuPG:
gpg --list-keys [...] pub rsa3072 2025-05-13 [SC] [expires: 2028-05-12] A8AF1C39AC67A1501450734F6DE8FC866DE0394D [...]$ gpg --list-keys [...] pub rsa3072 2025-05-13 [SC] [expires: 2028-05-12] A8AF1C39AC67A1501450734F6DE8FC866DE0394D [...]Copy to Clipboard Copied! Toggle word wrap Toggle overflow The key ID is the 40-character string in the command output, for example,
A8AF1C39AC67A1501450734F6DE8FC866DE0394D.Verify that the RPM file has the corresponding signature:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow The signature key ID matches the last part of the OpenPGP key ID.
6.8.2. Signing RPM packages with Sequoia PGP Copy linkLink copied to clipboard!
You can use Sequoia PGP to sign RPM packages and ensure no third party can alter their content.
6.8.2.1. Creating an OpenPGP key for signing packages with Sequoia PGP Copy linkLink copied to clipboard!
To sign packages by using the Sequoia PGP software, you must create an OpenPGP key first.
Procedure
Install the Sequoia PGP tools:
dnf install sequoia-sq
# dnf install sequoia-sqCopy to Clipboard Copied! Toggle word wrap Toggle overflow Generate an OpenPGP key pair:
sq key generate --own-key --userid <key_name>
$ sq key generate --own-key --userid <key_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Check the generated key pair:
sq key list
$ sq key listCopy to Clipboard Copied! Toggle word wrap Toggle overflow Export the public key:
sq cert export --cert-userid '<key_name>' > RPM-PGP-KEY-pmanager
$ sq cert export --cert-userid '<key_name>' > RPM-PGP-KEY-pmanagerCopy to Clipboard Copied! Toggle word wrap Toggle overflow
6.8.2.2. Configuring RPM to sign a package with Sequoia PGP Copy linkLink copied to clipboard!
To sign an RPM package with the Sequoia PGP software, you must configure the RPM to use Sequoia PGP and specify the %_gpg_name macro.
Prerequisites
-
You have the
rpm-signpackage installed on your system.
Procedure
Copy the
macros.rpmsign-sequoiafile to the/etc/rpmdirectory:cp /usr/share/doc/rpm/macros.rpmsign-sequoia /etc/rpm/
# cp /usr/share/doc/rpm/macros.rpmsign-sequoia /etc/rpm/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Get a valid OpenPGP key fingerprint value from the output of key listing:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow The key fingerprint is a 40-character string on the first line of the output, for example,
7E4B52101EB3DB08967A1E5EB595D12FDA65BA50.Define the
%_gpg_namemacro in your$HOME/.rpmmacrosfile as follows:%_gpg_name <key_fingerprint>
%_gpg_name <key_fingerprint>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Note that you can also use the full key ID instead of the fingerprint.
NoteUnlike GnuPG, Sequoia PGP accepts only the full key ID or fingerprint.
6.8.2.3. Adding a signature to an RPM package Copy linkLink copied to clipboard!
Packages are commonly built without signatures. You can add your signature before the package is released.
Prerequisites
- You created an OpenPGP key. For more information, see Creating an OpenPGP key for signing packages with Sequoia PGP.
- You configured RPM for signing packages. For more information, see Configuring RPM to sign a package with Sequoia PGP.
-
You have the
rpm-signpackage installed on your system.
Procedure
Add a signature to a package:
rpmsign --addsign <package-name>.rpm
$ rpmsign --addsign <package-name>.rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Verification
Import the exported OpenPGP public key into the RPM keyring:
rpmkeys --import RPM-PGP-KEY-pmanager
# rpmkeys --import RPM-PGP-KEY-pmanagerCopy to Clipboard Copied! Toggle word wrap Toggle overflow Display the key fingerprint of the signing key:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow The key fingerprint is usually a signing subkey in the
sq key list --cert-userid <key_name>command output, for example,E0BD231AB350AD6802D44C0A270E79FFC39C3B25.Verify that the RPM file has the corresponding signature, for example:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow The signature key ID matches the last part of the key fingerprint.
6.8.3. Signing RPM packages with Sequoia PGP by using PQC Copy linkLink copied to clipboard!
Post-quantum cryptography (PQC) is a set of algorithms designed to withstand attacks from quantum computers, thereby enhancing software security. To sign a package with PQC algorithms, you can use Sequoia PGP software.
The RPM package manager uses the OpenPGP standard to sign packages. OpenPGPv6 introduces support for hybrid keys and signatures. They combine the current cryptographic algorithm with the PQC algorithm, preventing a single point of failure and increasing trust in the resulting signature.
Starting from version 10.1, RHEL supports RPMv6 signatures. With this format, you can add multiple OpenPGP signatures to a package, increasing the redundancy on the RPM level.
You can combine both RPMv4 and RPMv6 signatures to sign the package. With this feature, you can use different RPM versions to verify the same signature. Starting from RHEL 10.1, RPM verifies only the RPMv6 signatures, if such exist, and ignores the RPMv4 ones. If no RPMv6 signatures are present in the package, RPM uses the RPMv4 signatures. In earlier RHEL versions, RPM verifies RPMv4 signatures and ignores RPMv6 ones.
6.8.3.1. Creating a PQC key Copy linkLink copied to clipboard!
To sign packages by using post-quantum cryptography (PQC) algorithms, you must create a hybrid key pair with Sequoia PGP first.
Note that you can specify different PQC algorithms. For example, the following procedure uses the ML-DSA-87-Ed448 algorithm.
Procedure
Install the Sequoia PGP tools:
dnf install sequoia-sq
# dnf install sequoia-sqCopy to Clipboard Copied! Toggle word wrap Toggle overflow Generate an OpenPGP key pair:
sq key generate --own-key --expiration=never \ --cannot-authenticate --cannot-encrypt \ --email <vendor_email> --name "<vendor_name>" \ --cipher-suite mldsa87 --profile rfc9580
$ sq key generate --own-key --expiration=never \ --cannot-authenticate --cannot-encrypt \ --email <vendor_email> --name "<vendor_name>" \ --cipher-suite mldsa87 --profile rfc9580Copy to Clipboard Copied! Toggle word wrap Toggle overflow Replace <vendor_email> and <vendor_name> with the email and the name of the software vendor that provides the RPM package.
This command generates a primary key and a signing subkey.
Check the generated key pair:
sq key list --cert-email <vendor_email>
$ sq key list --cert-email <vendor_email>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Copy to Clipboard Copied! Toggle word wrap Toggle overflow Export the PQC OpenPGP certificate:
sq cert export --cert-email '<vendor_email>' > RPM-PGP-KEY-VENDOR
$ sq cert export --cert-email '<vendor_email>' > RPM-PGP-KEY-VENDORCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Next steps
6.8.3.2. Configuring RPM for PQC Copy linkLink copied to clipboard!
After you generate a PQC key you want to use to sign a package, you must configure RPM to use this key.
Configure RPM outside of the build system on a separate signing server. RPM requires macros to support signing packages with Sequoia PGP. These macros are available in a template file.
Prerequisites
- You created a PQC key pair. For more information, see Creating a PQC key.
-
You have the
rpm-signpackage installed on your system.
Procedure
Copy the
macros.rpmsign-sequoiafile to the/etc/rpmdirectory:cp /usr/share/doc/rpm/macros.rpmsign-sequoia /etc/rpm/
# cp /usr/share/doc/rpm/macros.rpmsign-sequoia /etc/rpm/Copy to Clipboard Copied! Toggle word wrap Toggle overflow Check the generated key pair:
sq key list --cert-email <vendor_email>
$ sq key list --cert-email <vendor_email>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Copy to Clipboard Copied! Toggle word wrap Toggle overflow Export the key fingerprint to the
~/.rpmmacrosfile:echo "%_gpg_name <ml_dsa_fingerprint>" > ~/.rpmmacros
$ echo "%_gpg_name <ml_dsa_fingerprint>" > ~/.rpmmacrosCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Next steps
6.8.3.3. Adding multiple signatures to an RPM Copy linkLink copied to clipboard!
Starting from version 10.1, RHEL supports RPMv6 signatures. With this format, you can add multiple signatures to an RPM package. This results in enhanced security if either of the keys gets compromised or either of the cryptographic algorithms is rendered insecure.
You can run the rpmsign --addsign --rpmv6 command multiple times to sign the RPM with multiple different keys. Note that the first RPMv6 signature, usually generated with an OpenPGPv4 RSA key and compatible with the RPMv4, is also stored as an RPMv4 signature. This allows older RPM versions to trust the package signature.
Always consider adding an RPMv4-compatible signature to the package before adding any RPMv6 signatures that use PQC algorithms. This ensures that the package has a signature that RPM on RHEL versions earlier than RHEL 10.1 can verify.
Prerequisites
- You generated a PQC key pair. For more information, see Creating a PQC key.
- You configured RPM to use the PQC key. For more information, see Configuring RPM for PQC.
Procedure
Add a signature to a package:
rpmsign --addsign --rpmv6 <package_name>.rpm
$ rpmsign --addsign --rpmv6 <package_name>.rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow - To sign the package with multiple RPMv6 signatures, repeat the first step.
Verification
Import the exported PQC OpenPGP certificate into the RPM keyring:
rpmkeys --import RPM-PGP-KEY-VENDOR
# rpmkeys --import RPM-PGP-KEY-VENDORCopy to Clipboard Copied! Toggle word wrap Toggle overflow Verify that the RPM file has the corresponding signatures, for example:
rpmkeys -Kv <package_name>.rpm
$ rpmkeys -Kv <package_name>.rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow <package_name>.rpm: Header OpenPGP V6 ML-DSA-87+Ed448/SHA512 signature, key fingerprint: <ml_dsa_fingerprint>: OK Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: <rsa_fingerprint>: OK Header SHA256 digest: OK Payload SHA256 digest: OK<package_name>.rpm: Header OpenPGP V6 ML-DSA-87+Ed448/SHA512 signature, key fingerprint: <ml_dsa_fingerprint>: OK Header OpenPGP V4 RSA/SHA512 signature, key fingerprint: <rsa_fingerprint>: OK Header SHA256 digest: OK Payload SHA256 digest: OKCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Chapter 7. Packaging Python 3 RPMs Copy linkLink copied to clipboard!
You can install Python packages on your system by using the DNF package manager. DNF uses the RPM package format, which offers more downstream control over the software.
Packaging a Python project into an RPM package provides the following advantages compared to native Python packages:
- Dependencies on Python and non-Python packages are possible and strictly enforced by the DNF package manager.
- You can cryptographically sign the packages. With cryptographic signing, you can verify, integrate, and test contents of RPM packages with the rest of the operating system.
- You can execute tests during the build process.
The packaging format of native Python packages is defined by Python Packaging Authority (PyPA) Specifications. Historically, most Python projects used the distutils or setuptools utilities for packaging and defined package information in the setup.py file. However, possibilities of creating native Python packages have evolved over time:
-
To package Python software that uses the
setup.pyfile, follow this document. -
To package more modern packages with
pyproject.tomlfiles, see theREADMEfile in pyproject-rpm-macros. Note thatpyproject-rpm-macrosis included in the CodeReady Linux Builder (CRB) repository, which contains unsupported packages, and it can change over time to support newer Python packaging standards.
7.1. A spec file description for an example Python package Copy linkLink copied to clipboard!
An RPM spec file for Python projects has some specifics compared to non-Python RPM spec files.
Note that it is recommended for any RPM package name of a Python library to include the python3- prefix.
See the notes about Python RPM spec files specifics in the following example of the python3-pello package.
- An example SPEC file for the pello program written in Python
- 1
- By defining the
python3_pkgversionmacro, you set which Python version this package will be built for. To build for the default Python version3.12, remove the line. - 2
- When packaging a Python project into RPM, always add the
python-prefix to the original name of the project. The project name here isPelloand, therefore, the name of the Source RPM (SRPM) ispython-pello. - 3
BuildRequiresspecifies what packages are required to build and test this package. InBuildRequires, always include items providing tools necessary for building Python packages:python3-develand the relevant projects needed by the specific software that you package, for example,python3-setuptoolsor the runtime and testing dependencies needed to run the tests in the%checksection.- 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.12. You can use the%{python3_pkgversion}macro, which evaluates to3for the default Python version3.12unless you set it to an explicit version, for example, when a later version of Python is available (see footnote 1). - 5
- The
%py3_buildand%py3_installmacros run thesetup.py buildandsetup.py installcommands, respectively, with additional arguments to specify installation locations, the interpreter to use, and other details.NoteUsing the
setup.py buildandsetup.py installcommands from thesetuptoolspackage is deprecated and will be removed in the future major RHEL release. You can use pyproject-rpm-macros instead. - 6
- The
%checksection runs the tests of the packaged project. The exact command depends on the project itself, but you can use the%pytestmacro to run thepytestcommand in an RPM-friendly way.
7.2. Common macros for Python 3 RPMs Copy linkLink copied to clipboard!
In a Python RPM spec file, always use the macros for Python 3 RPMs rather than hardcoding their values.
You can redefine which Python 3 version is used in these macros by defining the python3_pkgversion macro on top of your spec file. For more information, see A spec file description for an example Python package. If you define the python3_pkgversion macro, the values of the macros described in the following table will reflect the specified Python 3 version.
| Macro | Normal Definition | Description |
|---|---|---|
| %{python3_pkgversion} | 3 | The Python version that is used by all other macros. Can be redefined to any future Python versions that will be added. |
| %{python3} | /usr/bin/python3 | The Python 3 interpreter. |
| %{python3_version} | 3.12 | The major.minor version of the Python 3 interpreter. |
| %{python3_sitelib} | /usr/lib/python3.12/site-packages | The location where pure-Python modules are installed. |
| %{python3_sitearch} | /usr/lib64/python3.12/site-packages | The location where modules containing architecture-specific extension modules are installed. |
| %py3_build |
Expands to the | |
| %py3_install |
Expands to the | |
| %{py3_shebang_flags} | sP |
The default set of flags for the Python interpreter directives macro, |
| %py3_shebang_fix |
Changes Python interpreter directives to |
7.3. Using automatically generated dependencies for Python RPMs Copy linkLink copied to clipboard!
You can automatically generate dependencies for Python RPMs by using upstream-provided metadata.
Prerequisites
-
A
specfile for the RPM exists. For more information, see A spec file description for an example Python package.
Procedure
Include one of the following directories in the resulting RPM:
-
.dist-info .egg-infoThe RPM build process automatically generates virtual
pythonX.Ydistprovides from these directories, for example:python3.12dist(pello)
python3.12dist(pello)Copy to Clipboard Copied! Toggle word wrap Toggle overflow The Python dependency generator then reads the upstream metadata and generates runtime requirements for each RPM package using the generated
pythonX.Ydistvirtual provides. Example of a generated requirements tag:Requires: python3.12dist(requests)
Requires: python3.12dist(requests)Copy to Clipboard Copied! Toggle word wrap Toggle overflow
-
-
Inspect the generated
Requires. -
To remove some of the generated
Requires, modify the upstream-provided metadata in the%prepsection of thespecfile. -
To disable the automatic requirements generator, include the
%{?python_disable_dependency_generator}macro above the main package’s%descriptiondeclaration.
Chapter 8. Modifying interpreter directives in Python scripts Copy linkLink copied to clipboard!
In Red Hat Enterprise Linux 10, executable Python scripts are expected to use interpreter directives, also known as hashbangs or shebangs, that explicitly specify at a minimum the major Python version. For example:
#!/usr/bin/python3 #!/usr/bin/python3.12
#!/usr/bin/python3
#!/usr/bin/python3.12
The /usr/lib/rpm/redhat/brp-mangle-shebangs buildroot policy (BRP) script is run automatically when building any RPM package, and attempts to correct interpreter directives in all executable files. The BRP script generates errors when encountering a Python script with an ambiguous interpreter directive, for example, #!/usr/bin/python or #!/usr/bin/env python.
You can modify interpreter directives in the Python scripts to prevent build errors at RPM build time.
Prerequisites
- Some of the interpreter directives in your Python scripts cause a build error.
Procedure
Depending on your scenario, modify interpreter directives by performing one of the following steps:
Use the following macro in the
%prepsection of yourspecfile:%py3_shebang_fix <SCRIPTNAME> …
%py3_shebang_fix <SCRIPTNAME> …Copy to Clipboard Copied! Toggle word wrap Toggle overflow SCRIPTNAME can be any file, directory, or a list of files and directories.
As a result, all listed files and all
.pyfiles in listed directories have their interpreter directives modified to point to%{python3}. Existing flags from the original interpreter directive will be preserved and additional flags defined in the%{py3_shebang_flags}macro will be added. You can redefine the%{py3_shebang_flags}macro in yourspecfile to change the flags that will be added.- Modify the packaged Python scripts so that they conform to the expected format.
Chapter 9. Packaging Ruby gems Copy linkLink copied to clipboard!
Ruby is a dynamic, interpreted, reflective, object-oriented, general-purpose programming language.
Programs written in Ruby are typically packaged by using the RubyGems software, which provides a specific Ruby packaging format.
Packages created by RubyGems are called gems and they can be re-packaged into RPM packages.
This documentation refers to terms related to the RubyGems concept with the gem prefix, for example, .gemspec is used for the gem specification, and terms related to RPM are unqualified.
9.1. How RubyGems relate to RPM Copy linkLink copied to clipboard!
RubyGems represent Ruby’s own packaging format. However, RubyGems contain metadata similar to metadata required by RPM. This metadata streamlines packaging gems as RPMs. RPMs re-packaged from gems fit with the rest of the distribution. End users are also able to satisfy dependencies of a gem by installing the appropriate RPM-packaged gem and other system libraries.
RubyGems use terminology similar to RPM packages, such as spec files, package names, dependencies, and other items.
To conform with the rest of RHEL RPM distribution, packages created by RubyGems must comply with the following rules:
-
Follow the
rubygem-%{gem_name}pattern when naming your packages. -
Use the
#!/usr/bin/rubystring as the interpreter directive.
9.2. RubyGems spec file conventions Copy linkLink copied to clipboard!
A RubyGems spec file must meet the following conventions:
-
The file contains a definition of
%{gem_name}, which is the name from the gem’s specification. - The source of the package must be the full URL to the released gem archive.
- The version of the package must be the gem’s version.
The file contains the following
BuildRequires:directive:BuildRequires: rubygems-devel
BuildRequires: rubygems-develCopy to Clipboard Copied! Toggle word wrap Toggle overflow The
rubygems-develpackage contains macros needed for a build.-
The file does not contain any additional
rubygem(foo)RequiresorProvidesdirectives because these directives are autogenerated from the gem metadata.
9.2.1. RubyGems spec file example Copy linkLink copied to clipboard!
The following is the RubyGems-specific part of an example spec file for building gems. The remaining part of the spec file follows the generic guidelines.
A RubyGems-specific part of an example spec file
9.2.2. RubyGems spec file directives Copy linkLink copied to clipboard!
The following are the specifics of particular items in the RubyGems-specific part of the spec file.
| Directive | RubyGems specifics |
|---|---|
|
|
RPM can directly unpack gem archives. The
|
|
|
This section includes commands for building the software into machine code. The |
|
|
The installation is performed into the |
9.3. RubyGems macros Copy linkLink copied to clipboard!
The following are macros useful for packages created by RubyGems. These macros are provided by the rubygems-devel package.
| Macro name | Extended path | Usage |
|---|---|---|
|
|
| Top directory for the gem structure. |
|
|
| Directory with the actual content of the gem. |
|
|
| The library directory of the gem. |
|
|
| The cached gem. |
|
|
| The gem specification file. |
|
|
| The RDoc documentation of the gem. |
|
|
| The directory for gem extension. |
9.4. Using gem2rpm to generate a spec file Copy linkLink copied to clipboard!
You can use the gem2rpm utility to create an RPM spec file.
9.4.1. Creating an RPM spec file for a Ruby gem Copy linkLink copied to clipboard!
You can generate an RPM spec file for a RubyGems package by using the gem2rpm utility.
Prerequisites
You have the
gem2rpmutility installed on your system:gem install gem2rpm
$ gem install gem2rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Download a gem in its latest version and generate the RPM
specfile for this gem:gem2rpm --fetch <gem_name> > <gem_name>.spec
$ gem2rpm --fetch <gem_name> > <gem_name>.specCopy to Clipboard Copied! Toggle word wrap Toggle overflow -
Edit the generated
specfile to add the missing information, for example, a license and a changelog.
9.4.2. Using custom gem2rpm templates to generate a spec file Copy linkLink copied to clipboard!
gem2rpm templates are standard Embedded Ruby (ERB) files that RPM spec files can be generated from. You can edit the template from which the RPM spec file is generated instead of editing the generated spec file.
Prerequisites
You have the
gem2rpmutility installed on your system:gem install gem2rpm
$ gem install gem2rpmCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Procedure
Display all
gem2rpmbuilt-in templates:gem2rpm --templates
$ gem2rpm --templatesCopy to Clipboard Copied! Toggle word wrap Toggle overflow Select one of the built-in templates and save it as a custom template:
gem2rpm -t <template> -T > rubygem-<gem_name>.spec.template
$ gem2rpm -t <template> -T > rubygem-<gem_name>.spec.templateCopy to Clipboard Copied! Toggle word wrap Toggle overflow Note that for RHEL 10 Beta, the
fedora-27-rawhidetemplate is recommended.- Edit the template as needed. For more information, see gem2rpm template variables.
Generate the
specfile by using the edited template:gem2rpm -t rubygem-<gem_name>.spec.template <gem_name>-<latest_version>.gem > <gem_name>-GEM.spec
$ gem2rpm -t rubygem-<gem_name>.spec.template <gem_name>-<latest_version>.gem > <gem_name>-GEM.specCopy to Clipboard Copied! Toggle word wrap Toggle overflow
9.4.3. gem2rpm template variables Copy linkLink copied to clipboard!
The following are the variables included in the gem2rpm template for RPM spec file generation.
| Variable | Explanation |
|---|---|
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |
|
|
The |