Developer

Sections

Documentations for different RPM sections, steps and preambles.

This section of the document lists out steps in their actual execution order.

Preamble

The preamble section is the "default" section of an RPM spec file. All spec files begin with a preamble section that stretches from the top until a new section (e.g. %description) is reached.

In Fedora, a preamble is also referred to as a "tag" or a "field".1

Here is a non-exclusive (but nearly exclusive) list of preambles available:

## these fields MUST be present in a spec file

Name:           pkgname
Version:        1.2.3
Release:        1%?dist
Summary:        Package summary (do not add period at the end)
# As opposed to the guidelines given by RPM, we (and also Fedora!) strongly
# recommend using SPDX identifiers.
License:        MIT
URL:            https://terra.fyralabs.com/
Source0:        Link to download the source code. If more then one link is needed,
specify with Source1:, Source2:, etc.

## terra also enforces the following preamble:

Packager:       username <email@example.com>

## these fields are optional and have default values

Epoch:          0
# automatic `Requires:` and `Provides:` generation
AutoReqProv:    1
# automatic `Requires:` generation
AutoReq:        1
# automatic `Provides:` generation
AutoProv:       1

## these fields are optional

Patch:
SourceLicense:
BugURL:
ModularityLabel:
DistTag:
VCS:
Distribution:
Copyright:
Vendor:
ExcludeArch:
ExclusiveArch:
ExcludeOS:
ExclusiveOS:
BuildArch:
BuildArchitectures:
BuildRequires:
NoSource:
NoPatch:

Group:
Provides:
Obsoletes:
Conflicts:
Suggests:
Recommends:
Enhances:
Supplements:

OrderWithRequires:
BuildConflicts:
Prefix:
Prefixes:
Docdir:
RemovePathPostFixes:

BuildSystem:
BuildOption:

Icon: (Obsolete)
Buildroot: (Obsolete)
BuildPrereq: (Obsolete)
Prereq: (Obsolete)

If you want to add comments, use %{dnl:…} or start a new line. Adding # … at the end of a line does not work.

BuildSystem: is a relatively new RPM feature.2

If you are a usual package maintainer, you would instantly notice one very important preamble is missing: Requires:. Requires: is quite special because it can be further divided into:

Requires:
Requires(pre):
Requires(post):
Requires(preun):
Requires(postun):
Requires(pretrans):
Requires(posttrans):
Requires(verify):
Requires(interp):
Requires(meta):

the latter ones refer to packages required during %pre, %post, …

The spec file (include sections and preambles) is parsed only after all macros are expanded. This means you may expand preambles from macros too.

Specifying (Build) Dependencies

Requires: or BuildRequires: must be followed by a space-separated (comma-separated is accepted but not recommended) list of "query". A "query" (term used here specifically!) is in the format of x = y (other comparators including >= are accepted) or simply x. RPM will resolve a "query" by finding a best package that provides the requirement of the query. For example, given the package gtk4-devel with the following provides:

Provides: gtk4-devel                  = 0:4.18.2-1.fc42
Provides: pkgconfig(gtk4)             = 0:4.18.2
Provides: pkgconfig(gtk4-atspi)       = 0:4.18.2
Provides: pkgconfig(gtk4-broadway)    = 0:4.18.2
Provides: pkgconfig(gtk4-unix-print)  = 0:4.18.2
Provides: pkgconfig(gtk4-wayland)     = 0:4.18.2
Provides: pkgconfig(gtk4-x11)         = 0:4.18.2

Then each of the following may be used to pull in gtk4-devel as a build dependency.

BuildRequires: gtk4-devel
BuildRequires: pkgconfig(gtk4)
BuildRequires: pkgconfig(gtk4) >= 4.18.0
BuildRequires: (pkgconfig(gtk4) with pkgconfig(gtk4-wayland))

For more information about the last query, read the official RPM documentation for boolean dependencies.

%description

Not a step. %description [[-n] subpkg]

Specify the description of a package.

If -n subpkg, specify the description of the subpackage with the name subpkg instead.

If subpkg is given without -n, specify the description of the subpackage %{name}-subpkg instead.

%description (without args) must be specified exactly once in a spec file.

Each subpackage requires its own %description too.

%mkbuilddir

Step Executing(%mkbuilddir). Optional.

As the name suggests, this step creates the build directory.

This is automatically generated and you should never need to specify this.

%prep

Step Executing(%prep). Required.

This prepares sources by extracting them to the build directory.

Unlike Fedora which does not provide Internet access during rpmbuild -bb, Terra also allows downloads during this stage.

The most common body of %prep is simply:

%prep
%autosetup

%generate_buildrequires

Step Executing(%generate_buildrequires). Optional. Since rpm >= 4.15.

The stdout is intercepted during this step. The output should be a newline (\n)-separated list of RPM build dependencies that should be installed.

Once this stage finishes, rpmbuild will attempt to install the list of dependencies. This implies that you may generate a dynamic dependency list that will be available by the time %build executes, usually by calling the package manager (e.g. dnf) with Internet access.

This optional script can be used to determine BuildRequires dynamically. If present it is executed after %prep and can though access the unpacked and patched sources. The script must print the found build dependencies to stdout in the same syntax as used after BuildRequires: one dependency per line.

rpmbuild will then check if the dependencies are met before continuing the build. If some dependencies are missing a package with the .buildreqs.nosrc.rpm postfix is created, that - as the name suggests - contains the found build requires but no sources. It can be used to install the build requires and restart the build.

On success the found build dependencies are also added to the source package. As always they depend on the exact circumstance of the build and may be different when bulding based on other packages or even another architecture.

%conf

Step Executing(%conf). Optional. Since rpm >= 4.18.

In %conf, the unpacked sources are configured for building.

Different build- and language ecosystems come with their own helper macros, but rpm has helpers for autotools based builds such as itself which typically look like this:

%conf
%configure

Macros such as %cmake and %meson should also be placed in this section.

%build

Step Executing(%build). If there is nothing to build, you should still declare this step in your spec.

In %build, the unpacked (and configured) sources are compiled to binaries.

Different build- and language ecosystems come with their own helper macros, but rpm has helpers for autotools based builds such as itself which typically look like this:

%build
%make_build

%install

Step Executing(%install). Required.

In %install, the software installation layout is prepared by creating the necessary directory structure into an initially empty “build root” directory and copying the just-built software in there to appropriate places. For many simple packages this is just:

%install
%make_install

%install [is] required for creating packages that contain any files.

In this step, files should be installed to the %{buildroot} folder, e.g.:

%install
install -Dpm755 my_binary -t %{buildroot}/usr/bin/
install -Dpm644 rand_file -t %{buildroot}/usr/share/my_software/

%check

Step Executing(%check). Optional.

If the packaged software has accomppanying tests, this is where they should be executed.

If you would like to make sure the software actually works properly, you may optionally choose to execute unit tests here.

%clean

Step Executing(%clean). Optional. Obsolete.

Packages should place all their temporaries inside their designated %builddir, which rpm will automatically clean up. Needing a package specific %clean section generally suggests flaws in the spec.

%rmbuild

Step Executing(%rmbuild). Optional.

As the name suggests, this basically removes the %builddir with rm -rf.

This is automatically generated and you should never need to specify this.

%files

Not a step. Required (practically). %files [-f file] [[-n] subpkg].

This specify all files that the package (or the subpackage) contains.

-f can be used in combination with %find_lang. Or rather, it just needs to be a file with a list of line-separated paths that should be included into the final RPM package.

RPM generates debug packages (%{name}-debuginfo and %{name}-debugsource) automatically. When you did not compile your software with debug symbols, you might see the following error:

error: Empty %files file %_builddir/%buildsubdir/debugsourcefiles.list

In this case, you should make sure you've applied the correct compiler flags.

Alternatively, disable debuginfo and debugsource packages by:

%define debug_package %nil

Files can be specified with globs (* and ?).

File derivatives

Files can be specified with optionally an attribute3 (aka. a file directive4). The following is an exhaustive list of file attributes available:

%artifact …
# ╰─ denote files that are more like side-effects of packaging than actual content
# the user would be interested in. Such files can be easily filtered out on queries.
%caps
# ╰─ sets the given POSIX.1e draft 15 capabilities on the file
%config(…) … (can be used on it's own or with parameters)
# ╰─ exhaustive list:
# - config(missingok)
# - config(noreplace)
%dir …
# ╰─ explicitly own the directory itself but not it’s contents
%doc
# ╰─ store the file into %{_docdir}
%docdir
# ╰─ mado: personally never seen this used
%ghost …
# ╰─ mark a file as owned by the package, but don't actually install the file
%license
# ╰─ store the file into %{_defaultlicensedir}
%verify(…)
# ╰─ exhaustive list:
# - verify(user owner) ← user and owner are same
# - verify(group)
# - verify(mode)
# - verify(filedigest md5) ← same
# - verify(size)
# - verify(maj)
# - verify(min)
# - verify(link symlink) ← same
# - verify(rdev)
# - verify(mtime)
# - verify(not ...) (don't verify this attribute)
%missingok
# ╰─ mark file presence optional
%readme
# ╰─ Obsolete - use %doc

# special:
%attr(…)
%defattr(…)

For more information about %attr and %defattr, see: https://rpm-software-management.github.io/rpm/manual/spec.html

%changelog

Metadata section. Optional, but required in Fedora and Terra

Specify a change to the spec.

Must either use %autochangelog, or follow this structure:

* Day Mon DD YYYY Name <email> - version-release
- Change you made
- Another change, if there's enough to justify two lines

Package scripts

Package scripts execute before and after the main operation (install/remove etc.) of the package inside a transaction.

Package scripts should only be used for actions that are fundamentally package specific. Domain specific registries, databases, caches and such are much better handled centrally by file triggers. Similarly, user and group creation should be handled by rpm-sysusers, rather than scripting them.

%pre

Executed just before unpacking the contents of the package. Non-zero exit prevents the installation of the containing package.

%post

Executed just after unpacking the contents of the package.

%preun

Executed just before removing the contents of the package. Non-zero exit prevents the uninstallation of the containing package.

%postun

Executed just after removing the contents of the package.

%verify

Executed when a package is verified using rpm --verify.

Unlike all the other scriptlet types, %verify never executes as a part of install/erase etc. operations.

Transaction scripts

Transaction scripts run before and after all the other package level operations (install/remove etc.) in a transaction.

When multiple transaction scripts for a given slot are present in a transaction, they are executed in the order of their install/removal order within the transaction.

%pretrans

Executed just before an install/update/reinstall transaction on the containing package starts.

No files from the transaction have been installed or removed yet. That is, in a fresh installation to an empty system root, there are no files around and no interpreter to run, so the only interpreter that can be reliably used in this slot is the embedded rpm-lua(7) interpreter.

Non-zero exit prevents the installation of the containing package.

This is a very special and a dangerous slot, and is best avoided.

%posttrans

Executed just after an install/update/reinstall transaction on the containing package finishes.

All files from the transaction have been installed or removed at this point.

%preuntrans

Executed just before an uninstall/updated-from transaction on the containing package starts.

%postuntrans

Executed just after an uninstall/updated-from transaction on the containing package finishes.

Sub-sections

These are optional macros that are not their own build steps, but are also not standalone macros.

%sourcelist

List of sources, one per line. Handled like unnumbered Source tags. For clarity, mixing Source tags and %sourcelist in one specfile is not recommended.

%patchlist

Like %sourcelist, but for patches.

%package [-n]<name>

Not a step. Optional. %package [-n] subpkg

Specify the preambles for a subpackage. The name of the subpackage is

  • subpkg if -n is given; and
  • %{name}-subpkg otherwise.

%description [-n]<name>

Used to define a description for a subpackage. Requires if %package is used.

The -n and <name> options work the same, however if not defined this will refer to the main package.

File Triggers

For information on file triggers, check out the RPM documentation.

Footnotes

  1. https://docs.fedoraproject.org/en-US/legal/license-field/

  2. https://rpm-software-management.github.io/rpm/manual/buildsystem.html

  3. https://rpm-software-management.github.io/rpm/manual/spec.html#virtual-file-attributes

  4. http://ftp.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html

On this page