# RPM packager's cheat sheet

Published on

These are some random notes on creating RPM packages that I wrote some time ago for my own use.

I don’t have the time or motivation to organize them in a proper article, but I thought I’d publish them anyway in case they are useful to someone.

## The RPM build tree

On Fedora, the default rpm build tree is ~/rpmbuild.

ls ~/rpmbuild
BUILD/
BUILDROOT/
RPMS/
SOURCES/
SPECS/
SRPMS/

You can create this directory structure with rpmdev-setuptree from the rpmdevtools package.

The purpose of each directory is:

• SPECS: spec files live here. They contain package metainformation and build instructions. This is what you’ll be writing when creating packages.
• SOURCES: download the source tarballs into this directory.
• SRPMS: .src.rpm bundle together a spec file and the sources for that spec. You can create one with rpmbuild -bs, or download with dnf download --source, and then build a binary package from it with rpmbuild -rb.
• BUILD: sources are unpacked into this directory and get compiled here.
• BUILDROOT: during the install phase, files are copied here.
• RPMS: the final rpms are created here.

To change the location of the build tree, put this into ~/.rpmmacros:

%_topdir %{getenv:HOME}/myrpmbuild

## SRPMs

To customize a package that already exists in Fedora (for instance, to update to a newer upstream version), it is convenient to download and install an srpm (also known as src.rpm).

First, download an srpm from dl.fedoraproject.org (substitute your release number) to ~/rpmbuild/SRPMS. Alternatively, use the program yumdownloader from the dnf-utils package:

yumdownloader --destdir ~/rpmbuild/SRPMS --source packagename

Next, install it into your build tree:

rpm -i ~/rpmbuild/SRPMS/packagename.src.rpm

Now the spec file should appear under ~/rpmbuild/SPECS and sources under ~/rpmbuild/SOURCES.

## RPM macros

Evaluate an RPM macro expression:

rpm -E '%_topdir'

Show all macro definitions:

rpm --showrc

It will also show where the definitions are located: look for something like Macro path: /usr/lib/rpm/macros:/usr/lib/rpm/macros.d/macros.*:/usr/lib/rpm/platform/%{_target}/macros:/usr/lib/rpm/fileattrs/*.attr:/usr/lib/rpm/redhat/macros:/etc/rpm/macros.*:/etc/rpm/macros:/etc/rpm/%{_target}/macros:~/.rpmmacros.

Unfortunately, it doesn’t seem to show where each particular macro comes from.

### Defining your own

It’s often useful to define variables in the SPEC file.

This can be done with either %define or %global, and %global is preferred:

%define commit a0a746442daf8dfca01859f1efcc8663b47b3705
%global commit a0a746442daf8dfca01859f1efcc8663b47b3705

## Minimal RPM spec file

I usually start with the minimal spec file:

Name:       minimal
Version:    1
Release:    1%{?dist}
Summary:    Minimal package

%description
...

%prep
true

%build
true

%install
true

%files
/*

RPM has many defaults and convenient macros suited for traditional ./configure && make && make install tarballs, but nowadays those are actually rare.

## Sources

If you have any source files, they should be declared (usually above %description) like this:

URL:        ftp://ftp.ncbi.nlm.nih.gov/entrez/entrezdirect/edirect.zip
Source0:    edirect.zip

You can then download the sources automatically using spectool:

spectool -C ~/rpmbuild/SOURCES -g package.spec

Sometimes I don’t declare any sources and instead use a tool (such as pypi or gem) to download and install the software. This is not reproducible, and therefore unacceptable when creating public packages, but is usually fine for personal use.

### github sources

Here’s an example of using a specific commit from a github repo.

See also the pages on SourceURL for git and versioning snapshots.

%global   commit a0a746442daf8dfca01859f1efcc8663b47b3705
%global   shortcommit %(c=%{commit}; echo \${c:0:7})
Release:  1.%{shortcommit}
Source0:  https://github.com/lwindolf/%{name}/archive/%{commit}/%{name}-%{commit}.tar.gz

%prep
%setup -n %{name}-%{commit}

## Build stages

### %prep

At this stage, you unpack the source tarballs and apply patches. If you have any sources to unpack, try to find a %setup invocation that does the trick. The flags to %setup are described elsewhere.

## Auto-provides

http://stackoverflow.com/a/39819960/110081

## Disable debuginfo

Put this in the spec file:

%global debug_package %{nil}

## Extract dependencies from a spec file and install them

dnf builddep package.spec