RPM packaging: A simplified guide to creating your first RPM

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 .

Everything you need to grow your career. With your free Red Hat Developer program membership, unlock our library of cheat sheets and ebooks on next-generation application development. SIGN UP

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.

section, as this software doesn’t have any dependencies. Delete the %configure section, as this software can be built without configure (keep this if you need configure before you run make ).

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.