The concept of RPM packaging can be overwhelming for first-timers because of the impression a steep learning curve is involved. In this article, I will demonstrate that building an RPM with minimal knowledge and experience is possible. Note that this article is meant as a starting point, not a complete guide to RPM packaging.
ASCII-based Tetris game
For my demonstration, I chose a simple ASCII-based Tetris game, written in C, and I made slight adjustments to ensure a relatively straightforward RPM build. I will use a game called Vitetris as my example, which you can download.
To ensure there are no errors when creating the RPM package, I remove references in the Makefile that change file permissions to root, in order to allow a non-root user to build the RPM. This modification is as follows:
$ cat Makefile |grep 'INSTALL ' INSTALL = install #INSTALL = install -oroot -groot # non-root users building the rpm won't be able to set this and the RPM build will fail.
Once you have made this change, create a new gzipped tarball with the same name: vitetris-0.57.tar.gz
.
Preparing the environment
To install your development environment on a subscribed Red Hat Enterprise Linux (RHEL) 7 system, you need the following repositories to build your RPMs: rhel-7-server-rpms
, rhel-7-server-extras-rpms
, and rhel-7-server-optional-rpms
.
You must have following packages installed:
# yum install -y rpm* gcc gpg* rng-tools
I use rpm*
and gpg*
because it makes the number of things to remember to install much more manageable.
Compiling the software manually
A large part of success with RPM packaging understanding the software you are working with. First, compiling software manually preferably is done as a non-root user. In this case, I am using the rpmbuilder
user.
Start with extracting the gzipped tarball (vitetris-0.57.tar.gz
), and then inspecting the README file. In this case, the README file doesn't contain information about compiling your game from source code. As a general rule, open source software written in C is compiled with three steps: configure
, make
, and make install
. However, it is worth just running make
on its own to see whether the software will build.
As a non-root user, test to see whether running make
is sufficient:
[rpmbuilder@rpm vitetris-0.57]$ make generating src/src-conf.mk ./src-conf.sh 'cc' '' '' ... Done. Now run ./tetris (or make install)
To test the game, simply run ./tetris
to see whether the game loads and can be played:
Creating GPG keys
Signing your RPM package adds an extra layer of trust to your packages. Therefore, to create GPG keys as the rpmbuilder
user, you will need a session with root access to run rngd
(to speed up the generation process) and a session with X11 forwarding as the rpmbuilder
user.
As root, run:
# rngd -r /dev/urandom
If you get the following error:
Failed to init entropy source 2: Intel RDRAND Instruction RNG
Try:
# rngd -r /dev/urandom -o /dev/random -f
You must log into the host as rpmbuilder
user with X11 forwarding (otherwise, the key generation will fail):
$ gpg --gen-key ... Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 1 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: RPM Build User Email address: rpmbuilder@rpm Comment: RPM Builder GPG Signing Key You selected this USER-ID: "RPM Build User (RPM Builder GPG Signing Key) <rpmbuilder@rpm>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O You need a Passphrase to protect your secret key.
... gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u pub 2048R/EEF6D9AD 2019-03-02 Key fingerprint = 6ED1 2456 B7ED EEC6 D0DF B870 444A 40A7 EEF6 D9AD uid RPM Build User (RPM Builder GPG Signing Key) <rpmbuilder@rpm> sub 2048R/D498F883 2019-03-02
If you need to export the key to be used within satellite for custom software or in your yum repo configuration, use the command:
$ gpg --armor --export -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2.0.22 (GNU/Linux)
...
Creating the RPM package for Vitetris
To build the RPM, first create the build tree and the spec file and place the source code in the right place:
$ rpmdev-setuptree $ rpmdev-newspec rpmbuild/SPECS/vitetris.spec rpmbuild/SPECS/vitetris.spec created; type minimal, rpm version >= 4.11. $ cp vitetris-0.57.tar.gz rpmbuild/SOURCES/
Add initial details to the spec file
Provide the initial details:
Name: vitetris Version: 0.57 Release: 1%{?dist} Summary: ASCII based tetris game License: BSD URL: https://www.victornils.net/tetris/ Source0: vitetris-0.57.tar.gz BuildRequires: gcc
Remove unnecessary sections
- Delete the
Requires
section, as this software doesn't have any dependencies. - Delete the
%configure
section, as this software can be built withoutconfigure
(keep this if you needconfigure
before you runmake
).
Add a description
You can add anything you like, but here is a suggestion:
%description vitetris is a multiplayer ASCII-based Tetris game
Test the initial build
Test the build with the information just provided to see what errors appear:
$ rpmbuild -ba rpmbuild/SPECS/vitetris.spec ... RPM build errors: Installed (but unpackaged) file(s) found: /usr/local/bin/tetris /usr/local/share/applications/vitetris.desktop /usr/local/share/doc/vitetris/README /usr/local/share/doc/vitetris/licence.txt /usr/local/share/pixmaps/vitetris.xpm
Add a list of files from the previous step to the spec file
You must add the list of files from the previous step to the %files
section, as follows:
%files /usr/local/bin/tetris /usr/local/share/applications/vitetris.desktop %doc /usr/local/share/doc/vitetris/README /usr/local/share/doc/vitetris/licence.txt /usr/local/share/pixmaps/vitetris.xpm
Notice that %doc
was put in front of the README to identify it as an informational document. The RPM will still build without this.
Rerun the build
$ rpmbuild -ba rpmbuild/SPECS/vitetris.spec Wrote: /home/rpmbuilder/rpmbuild/SRPMS/vitetris-0.57-1.el7.src.rpm Wrote: /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm Wrote: /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-debuginfo-0.57-1.el7.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.AqR4Aq + umask 022 + cd /home/rpmbuilder/rpmbuild/BUILD + cd vitetris-0.57 + /usr/bin/rm -rf /home/rpmbuilder/rpmbuild/BUILDROOT/vitetris-0.57-1.el7.x86_64 + exit 0
Sign the RPM package
Signing your RPM is as simple as running:
$ rpmsign --addsign /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm Enter pass phrase: Pass phrase is good. /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm:
If you get this error:
You must set "%_gpg_name" in your macro file
Set %_gpg_name
with the public key value:
$ gpg --list-keys /home/rpmbuilder/.gnupg/pubring.gpg ----------------------------------- pub 2048R/EEF6D9AD 2019-03-02 uid RPM Build User (RPM Builder GPG Signing Key) <rpmbuilder@rpm> sub 2048R/D498F883 2019-03-02 $ echo "%_gpg_name EEF6D9AD" >> .rpmmacros
Try again:
$ rpmsign --addsign /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm Enter pass phrase: Pass phrase is good. /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm:
Test an install/uninstall of the RPM as root user
# rpm -i /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm warning: /home/rpmbuilder/rpmbuild/RPMS/x86_64/vitetris-0.57-1.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID eef6d9ad: NOKEY # /usr/local/bin/tetris
Uninstall the RPM:
# rpm -qa |grep tetris vitetris-0.57-1.el7.x86_64 =# rpm -e vitetris-0.57-1.el7.x86_64 # /usr/local/bin/tetris -bash: /usr/local/bin/tetris: No such file or directory
Conclusion
Depending on the software you intend to package, custom RPM packaging can be challenging. In this article, I aimed to do as little as possible to demonstrate that default settings are often enough to build an RPM.
To learn more, see Red Hat's RPM packaging guide.
Last updated: March 15, 2019