There is a dearth of definitive information about packing with RPM. This talk will fill in those gaps, covering details of constructing a solid spec file, writing install scripts and triggers, aspects of packaging that need to be considered, and differences between versions of RPM corresponding to currently supported versions of Red Hat and SUSE enterprise distros, as well as Fedora and openSUSE.
2. About this talk
● Covers package building –
not package management
● Material was collected for a book:
“The RPM Handbook”
● Warning: this talk is not exhaustive!
3. Outline of talk
● What is RPM?
● Building RPMs
– Dependencies and capabilities
– Macros
– Running rpmbuild
– Anatomy of a specfile
– Build scripts
– Management scripts and triggers
– Evolution of RPM
● Sources of further information
4. What is the
significance of packaging?
● Ian Murdoch, founder of Debian,
suggested in 2007 that:
[Package management is] the biggest
advancement Linux has brought to the
industry
● Debian and RPM packages evolved at roughly
the same time and are comparable in
functionality
5. Why is RPM relevant?
● Provides a straightforward, consistent way to manage
software and resources –
directly or through higher-level tools
● The fundamental building block of distros
● Widespread use:
– RPM-based distros (RHEL, Fedora, SLE, openSUSE)
– Independent Software Vendors (ISVs)
– Packages for internal use
● Well-constructed packages give a professional impression
6. RPM design goals
● Upgradability
(easy to install, upgrade and remove packages)
● Powerful querying
● System verification
● Pristine sources
(start with original, “upstream” source code)
● Reproducible builds
7. Issues with RPM
● Poorly documented
● Shows signs of age – but it is evolving
● Enterprise distributions lag behind latest developments
(newer features often not available for several years)
● Many packaging details are distribution-specific
(see Fedora, openSUSE and Mandriva packaging
guidelines)
● Information and misinformation on the internet
8. Versions of RPM in use
Version Date Used by (EOL)
4.4.2 2005-07-21 SUSE 10
4.4.2.3 2008-04-01 RHEL 5 (2017/2020), SUSE 11
4.8.0 2010-01-08 RHEL 6 (2020/2023)
4.9.1.2 2011-09-29 OpenSUSE 12.2 (2014)
4.9.1.3 2012-04-03 Fedora 17 (2013)
4.10.1 2012-10-03 Fedora 18 (2014)
4.11.1 2013-02-01
● These are just the versions still in use by major distributions.
● Prior to 2005 RPM development languished.
● Version 4.4.2 is the first version of the relaunched rpm.org
● In 2006 RPM was forked by the previous developer – rpm5 is only
used by Mandriva
9. What does RPM consist of?
● Package file format (.rpm and .srpm)
contains metadata and payload
● Package database (/var/lib/rpm/*)
information on installed packages
● Configuration files
(/etc/rpm/* and /usr/lib/rpm/*)
● Run-time admin tools (rpm command)
● Build tools (rpmbuild command)
● Libraries used by tools such as yum
and the rpm tools themselves
10. What does RPM do?
● Installs, erases and updates packages
● Reports on what packages are installed
● Verifies installed packages
● Checks dependencies within sets of packages being
installed, upgraded or removed
● Underpins higher-level packaging tools –
e.g. YUM, PackageKit, Zypper
(these resolve dependencies, as well as checking)
● Provides a package build tool (rpmbuild)
11. Building RPM packages
● Dependencies
● Macros
● The build environment
● The build process
● Scriptlets, Scripts, and Triggers
12. Dependencies
● Dependency tracking is fundamental to
packaging systems
● Ensures that software being installed has all its
prerequisites
● Ensures that packages aren't inadvertently
removed while other packages depend on them
● Differentiate between dependency checking and
dependency solving
13. Dependencies (2)
● Packages provide “capabilities” (text strings)
● One automatic capability is the name of the package
● Special capabilities:
– rpmlib(feature)
– interp(Module) – e.g. perl(Class::Accessor)
● Requirements can specify versions of capability:
op [epoch:]version[-release]
14. Version comparison rules
● Epoch - integer comparison
● Version and release:
– Split into numeric and alpha substrings and
compared substring by substring (separators ignored)
– Leading zeroes ignored
– Longer substring or sequence is newer
– e.g.:
● 1.0010 > 1.9
● 1a > 1B
● 3:1.0 > 2:99.999
● 1.2.3abc = 1_2_3_abc
15. RPM macros
● Macro values control all rpm tools
(rpmbuild, rpm, etc) e.g.:
– %_topdir defines build directory (~/rpmbuild)
– %_binary_payload defines payload format and
compression
● Defaults defined in /usr/lib/rpm/macros
● About 250 macros – another 80 commented out
16. RPM macros (2)
Can be defined:
● In macro files
(/usr/lib/rpm/macros, /etc/rpm/*, ~/.rpmmacros)
● On the command line – for all commands
(-D 'name definition')
● In spec files
– %global name[(args)] expansion
– %define name[(args)] expansion
● By rpmbuild internally – e.g. Name tag causes %name macro to
be defined with the tag's value
Note: parameterized macros definitions are evaluated twice (on
definition and use), simple macros are evaluated once (on definition)
17. RPM macros (3)
● Usage %name or %{name} – note: if the macro is
not defined you get literal string in output
● Conditionals:
– %{?name[:expansion]}
– %{!name:expansion}
– %if expr ... %else ... %endif
– %ifarch / %ifnarch / %ifos / %ifnos
● Shell escape: %(command arg ...)
● Messages: %{echo: msg}
(also warn and error)
● Dump all definitions: %dump
18. Building RPMs
● Packages are normally built from sources and patches
● Aimed at software that follows GNU Coding Standard
(autoconf/automake, etc) – works best if you don't fight it
● RPM packages built with rpmbuild command
(-ba option to build everything)
● Controlled by “spec file”
(which may be located within tar file – use -ta)
● Spec file can define multiple packages
● Spec file specifies build requirements
(can be installed with yum-builddep – from yum-utils)
19. Build process
● rpmbuild initializes itself from macro files
(/etc/rpm/*, /usr/lib/rpm/macros, ~/.rpmmacros)
● Reads spec file, expanding macros as it goes
● Steps through build stages specified by spec file
● Determines dependencies and capabilities provided
● Constructs binary RPM and/or source SRPM
● Note:
– never build as root!
– always test RPMs on a clean system or with mock to identify
unspecified dependencies (which may be satisified by s/w
installed on the build system)
20. Build environment
● Build area is a directory hierarchy –
location specified by %_topdir (~/rpmbuild)
– SPECS/ (%__specdir)
– SOURCES/ (%__sourcedir)
– BUILD/ (%__builddir)
– BUILDROOT/ (%__buildroot)
– RPMS/ (%__rpmdir)
– SRPMS/ (%__srcrpmdir)
● Setup directories under $HOME with
rpmdev-setuptree (from rpmdevtools package)
21. Spec files
● Complete specification of package
● Defines meta data for package
(name, version, release, license, etc)
● Specifies dependency information
● Describes software build process
● Provides a manifest of the files to be installed
● Provides scripts for package install/erase
● Note: clumsy syntax – %thing may be a macro, a spec
file section or an file attribute depending on context
● Comments are marked with “#”, but macros within
comments are expanded – which can cause problems
22. Spec file sections
● Preamble (subpackage preambles introduced by %package)
● Package description (%description)
● Build script sections (%prep, %build, %install, %check,
%clean)
● Run-time scripts (%pre, %post, %preun, %postun, %pretrans,
%posttrans, %verify)
● Trigger scripts (%triggerprein, %triggerin, %triggerun,
%triggerpostun)
● Files manifest (%files)
● Change log (%changelog)
Subpackages have separate description, run-time scripts, triggers and
manifests (sections qualified with subpackage suffix or full name)
24. Example spec file
Name: hello
Version: 2.7
Release: 1%{?dist}
Summary: GNU 'hello world' program
Group: Miscellany
Vendor: Free Software Foundation
License: GPLv3
URL: http://www.gnu.org/software/hello/
BuildRoot: %{_tmppath}/%{name}-root-%(%{__id_u} -n)
Requires: info
Source0: %{name}-%version.tar.gz
%description
GNU Hello produces a familiar, friendly greeting. The practical purpose
Of GNU Hello is to serve as a minimal example of a GNU package.
%prep
%setup -q
%build
%configure
make
%install
make install DESTDIR=$RPM_BUILD_ROOT
26. Spec file preamble
● Consists of key-value records before first section
– Name: name of the software package
– Version: version number of the upstream source code
– Release: number of this release of the software package
– Summary: short, one-line description of the package
– URL: web site URL for software
– License: licence for the software
– Group: category the software falls in
– Source0: file containing the N'th source file
● Preamble for subpackages specified with %package section
● Info corresponds to output from rpm --query –info
● %description section provides more detailed description
27. Specifying dependencies
● Automatic and manual dependencies
(scripts %__find_requires and %__find_provides)
● Packages provide “capabilities”
(including one with the name of the package)
● Specify capabilities provided with Provides tag
● Required packages/capabilities with Requires tag
● PreReqs tag is deprecated – use Requires(pre)
● Conflicts specified with Conflicts tag
● SUSE has “soft” dependencies (Suggests and
Recommends) – these may come to later versions of rpm
28. Specifying dependencies (2)
● Dependencies and capabilities provided can be
– Automatically determined by rpmbuild
(and helpers)
– Manually specified (%requires, %provides, etc)
● Automatic dependency generators run by
rpmbuild after %install section
● Also need to specify build dependencies
29. Build process in detail – %prep
● Unpacks source files and applies patches, e.g.:
● Process often acheived with two “pseudo”-macros:
– %setup – unpacks (compressed) tar files into build dir
– %patchN – applies patch N
%prep
%setup -q
%patch0
30. Build drocess in detail – %build
● Configures and builds software e.g.:
● %configure runs GNU configure
● make is standard Linux make command
%build
%configure
make
31. Build process in detail – %install
● Installs to the “build root” - a staging area
(proxy for the real root directory)
● Installs into build root (proxy for the filesystem
root)
● Configure-generated makefiles support
$DESTDIR
%install
make install DESTDIR=$RPM_BUILD_ROOT
32. Debugging RPM build scripts
● rpmbuild creates temporary script files
● Build can be executed up to a certain stage
– -bp – stop after %prep
– -bc – stop after %build (compile stage
– -bi – stop after %install
– -bl – do “list check”
(expand %files and check everything exists)
● --short-circuit option to skip to stage specified with -bc, -bi or -bb
(but makes generated RPM essentially unusable)
● shortrpm program can be used to create installable RPMs skipping prep
and build stages – but should only be used in development
● Alternatively “exit 1” to build or install script,
and examine and debug the script left in /var/tmp
33. Management scripts
● Scripts run before/after package installation, upgrade and erasure
– %pretrans – run at start of transaction
– %pre – before package installed
– %post – after package installs
– %preun – before package uninstalled
– %postun – after package uninstalled
– %posttrans – at end of transaction
– %verifyscript – run by rpm -V
● On upgrade install scripts are run from new version of package,
then uninstall scripts from old version
●
Install scripts are not interactive – we're not on Debian here!
34. Management scripts (2)
● Uses:
– Set up users and groups
– Install services and cron jobs, set up alternatives
– Refresh dynamic linker bindings (ldconfig)
● Scripts receive argument $1 – says how many
instances left at end of operation:
– 1 after first install
– 2 for install of new version on upgrade
– 1 for uninstall of previous version on upgrade
– 0 for final uninstall
35. Management scripts (3)
● Scripts can be provided for subpackages (specify
name after script tag)
● Interpreter specified with -p program
– Default interpreter is /bin/sh
– <lua> for built-in lua interpreter
(all that is available on %pretrans of first-stage install)
– Can specify /sbin/ldconfig if that is all that needs to
run
– Creates an automatic dependency on interpreter
36. Triggers
● Scripts that run when a target package is installed or
uninstalled:
– %triggerin – run when target or source package
installed/upgraded
– %triggerun – run when target or source package is uninstalled
– %triggerpostun – run after target package is uninstalled
● e.g.: %triggerin -p /bin/sh – postfix
● Trigger scripts invoked with two arguments:
– $1 gives number of instances of source package remaining when
trigger completes
– $2 gives number of instances of target package remaining
37. File lists
● List of files in package(s) specified by %files
● List can be read from file with -f file
● Attributes specified with %defattr, %attr
● Configuration files marked with %config
● Documentation flagged with %doc
(collected and placed in /var/share/doc)
● 4.11 introduces %license to mark license files
● Error if there are unpackaged files in build root
38. Repeatable builds
● BuildRequires specifies packages needed
for building
● Building under mock can ensure unspecified
dependencies are identified – basic usage:
mock –-init chroot-name
mock –-root chroot-name
–-rebuild package.src.rpm
● Should also test installation of built packages
39. RPM evolves
Just a couple of examples (remember RHEL5 uses 4.4.2.3):
● 4.6.0
– BuildRoot tag now silently ignored
– Group tag no longer mandatory
– %_topdir now $HOME/rpmbuild (was /usr/src/redhat)
– New macros %patches and %sources
● 4.7.0
– Support for XZ compression
– Group tag in subpackage inherits from main package
– New macros %getenv and %getconfdir
40. More changes
● 4.8.0 (used by RHEL6)
– Deprecated Copyright tag no longer recognized
– PreReq and BuildPreReq are deprecated
– New BugUrl tag and %_bugurl macro
– New %make_install macro
– Macros %PACKAGE_VERSION and %PACKAGE_RELEASE removed
(use %version and %release)
● 4.9.0
– New Requires(pretrans) and Requires(posttrans) tags
– New OrderWithRequires tag
– --sign option to rpmbuild no longer supported
(now is a separate command – rpmsign)
Release notes on rpm.org have the details
41. And there's more...
● Multilib
● SE Linux policies
● POSIX capabilities
● Software collections
●
●
●
42. Sources of further information
● Man pages for rpm, rpmbuild, etc
● rpm.org
● fedoraproject.org/wiki/
Category:Package_Maintainers
● opensuse.org/Portal:Packaging
● wiki.linuxfoundation.org/en/LSB
(Linux Standards Base)
● Classic Shell Scripting, Robbins & Beebe (O'Reilly)
● AUTOTOOLS, John Calcote (No Starch Press)
● GNU Coding Standards (Free Software Foundation)
● rpmhandbook.com (coming soon)