RPM 4.20 is coming
The RPM Package Manager (RPM) project is nearing the release of RPM 4.20, the last major planned update for the RPM 4.x series. It has few user-facing changes, but several additions and enhancements for developers—as well as some small incompatibilities that will likely require RPM packagers to revise their spec files. 4.20 will be rolling out to many users soon, in Fedora 41, which is scheduled for October. RPM 6.0 is already in the works, with a new package format and opening the door to enabling C++ use in the RPM codebase.
An RPM release consists of the command-line suite of tools for installing, managing, removing, and creating RPM packages. It also includes RPM plugins and librpm, which provides the RPM API to user-facing tools like DNF, Zypper, and others. In addition, the project maintains the RPM package format and spec file format documentation, which is updated with each RPM release. RPM spec files are text files, with the .spec extension, that describe how to build an RPM. They are included with a package's source RPM (.src.rpm), along with the original source code and patches to be applied to the software.
Many Linux users interact directly with RPM rarely, if at all. Desktop users can do all their software management on RPM-based systems, like Fedora and openSUSE, with tools that use RPM behind the scenes, such as DNF, Zypper, or GNOME Software. Packagers, on the other hand, spend quite a bit of time with RPM, and the bulk of the features in 4.20 are designed to make it easier to build and maintain RPMs.
Append and prepend
RPM spec files define package-build steps in scriplet sections such as %prep (get sources ready), %setup (create build directories), %patch (apply patches), and so forth. With 4.20, RPM has added the ability to append (-a) and prepend (-p) the sections with additional commands. This will allow packagers to insert instructions before or after each build step. For example, one might add an %install -a section to remove a file after the package is installed. The append and prepend directives are useful to RPM in any case, but are particularly useful in conjunction with the addition of one of RPM 4.20's more interesting new features: declarative builds.
Declarative builds
This feature is meant to allow upstream projects and distributions to provide build-system macros for common build processes, such as creating Python packages, Ruby gems, or Rust crates. Packagers can use this feature to declare a desired build system for a package with a single stanza, rather than each packager having to describe the build process on their own. The example given in the request for enhancement (RFE) is building projects that use GNU Autotools. When compiling from source, that would usually involve the familiar steps:
$ ./configure $ make # make install
In an RPM spec file, that would usually look something like this:
%prep %autosetup %build %configure %make_build %install %make_install
With this release, that can be condensed to a single line:
BuildSystem: autotools
Declarative builds should reduce the amount of redundant boilerplate that developers have to add to package spec files—but it does not preclude tweaking things if necessary. Declarative builds can be modified using the BuildOption tag or by prepending and appending %install -a, %build -p, etc., sections. See the documentation and example macros for more on declarative builds.
Public plugin API
RPM plugins provide support for features that are not suitable for all platforms. For example, Fedora users may want the SELinux plugin, but it is not suitable for systems with AppArmor, such as openSUSE. RPM has also been ported to non-Linux systems, and many of RPM's plugins are Linux-specific.
Work began
on RPM's plugin system in 2012. RPM shipped a plugin system in the 4.12 release in 2014, but the
API has been considered subject to change and kept internal-only ever since. Not that
it has changed: the RPM
plugin interface is basically unmodified since the 4.12.0
release. In 2023, RPM developer Panu Matilainen said
that the API should have been public to begin with and committed the change
to make it so. "We've
procrastinated on making this API public for about ten years now, and
in the meanwhile there has been exactly one disruptive change to the API.
"
Making the API public will make it possible for others to develop RPM plugins with confidence that subsequent RPM releases won't break the plugins. There is still work to be done for RPM to verify that plugins are compatible with the version of RPM being used, but that does not look likely to ship in 4.20.
Isolation
When RPMs are installed or removed, they can run scriptlets
that make updates to the system. For example, a package may need to
restart a service or make updates to the system's GNOME
settings. Running these scriptlets is necessary, but Johannes Segitz
noted that they can pose a security challenge since packagers may "naively
"
place code in /tmp that could be exploited for privilege
escalation and submitted pull
request with a proof-of-concept to provide a private /tmp
directory for scriptlets.
Matilainen broke that out as a plugin and added Linux-specific functionality to implement optional filesystem and network isolation using namespaces. Specifically, the unshare plugin shipped with RPM 4.20 can mount paths privately during scriptlet execution, such as /tmp and /home, so that scriptlets do not have access to the system /tmp or user home directories. The directories to be isolated are specified in /usr/lib/rpm/macros.d/macros.transaction_unshare as a colon-separated list of directories.
The plugin also allows disabling network access, so that the scriptlet cannot upload or download anything during execution.
Goodbye %patchN
Packagers often add patches to the original upstream source code of
a project. RPM has a macro for this, %patch, which
has accepted several variations for some time: "%patch N",
"%patch -P N", or "%patchN" allow packagers to specify
one or more patches to be applied at build time. However, in RPM 4.19,
the %patchN syntax, was deprecated in favor of %patch N
or %patch -p N. Matilainen said
on the fedora-devel list that the reason for its deprecation was
"it's a mind-bogglingly bad syntax for what it does, and prevents
making %prep like any other section in the spec
". He did not
elaborate on how it prevented this, except to say "don't ask, you
don't want to know
".
The RPM developers may be happy to shed the %patchN syntax, but it is widely used. Dominique Leuenberger posted a message to the opensuse-factory mailing list in February about work needed to enable 4.20, saying that more than 2,066 packages used that syntax. According to the Fedora 41 change proposal for RPM 4.20, more than 1,000 spec files in Fedora's repository were using that syntax as of April. No doubt, many packagers still have work to do to update their package specs.
Miscellaneous
There are, of course, plenty of smaller changes that users and developers may (or may not) notice. For instance, the rpmkeys command, which is used to manage and provide information about RPM signing keys, now has options to list installed keys (--list) and to delete keys (--delete). Previously rpmkeys could only import keys and verify package signatures.
RPM has also added JSON as a query format. It joins the XML
query format, which Matilainen noted
is "an eyesore
". For example, developers who want to access all
of the information about an RPM for a program can use the following to get full output in
JSON format:
$ rpm -q --json <packagename>
Packagers who would like to enable reproducible builds will be interested in the %build_mtime_policy. This allows the packager to set a timestamp policy for the package to help ensure that the timestamps remain the same for all builds. See the documentation for more information.
Beyond 4.20
The RPM project is now in its 29th year, with the first commit (to a CVS repository) made on November 27, 1995, by either Marc Ewing or Erik Troan. The RPM timeline notes that the first commit was added as root, thus the identity of the original author is lost to history. So it goes. The project has pushed out substantial feature releases to the 4.x series about once a year since the project rebooted in 2006. According to the RPM roadmap, RPM 6.0 will be released sometime in the third quarter of 2025, which will coincide with the 30th anniversary of RPM. Those wondering about the jump from RPM 4.20 to 6.0 may not have lived through (or have forgotten) the fork that prompted the RPM.org reboot, relaunch of the fork, the fork's RPM 5.0.0 release, and subsequent drama in 2011.
The fork is showing few signs of life at present. The project site is still up but its news page has no updates after the 2009 release of 5.2, though there appears to have been a 5.4.17 release in 2016. The distributions that had switched to the fork, such as OpenMandriva Lx and OpenEmbedded, have switched back to the RPM.org version.
At any rate, it seems likely the RPM maintainers thought the best course was to avoid any confusion with the fork's 5.x releases and will skip straight to 6.0. The version jump will introduce the RPM v6 package format, which is described as a face-lift for the format rather than a full redesign. The goals are to shed some compatibility baggage, drop obsolete crypto algorithms (MD5, SHA1, and DSA1), and use 64-bit sizes in all headers.
RPM v6 will stop using cpio as the archive format for its file archive (payload) and start using the new format, which supports files larger than 4GB. If 4GB sounds excessive for an RPM, it's worth noting that the Chromium source RPM for Fedora 40 weighs in at a hefty 3.8GB. The Firefox source RPM is a comparatively svelte 826MB. If there are no packages that exceed the 4GB limit today, it seems likely that there will be before long.
To prepare for the new format, RPM 4.20 ships with a new utility, rpm2archive, which replaces the now-outdated rpm2cpio utility. Historically, rpm2cpio has been used to convert RPMs to cpio files, which can be unpacked with cpio. The rpm2archive utility converts RPMs to a gzipped-compressed tar archive that can be manipulated with tar instead.
The move to the v6 format should not be disruptive to distributions still on RPM 4.20 when 6.0 is released. In the first draft Matilainen sent to the rpm-maint mailing list, he said that the last RPM 4.x version would be able to read and install v6 packages and that RPM v6 would be able to read and install v4 packages. This should mean that RPM 4.20 will be able to work with v6 packages, since no further major 4.x releases are on the RPM roadmap.
6.0 and C++
In March, Matilainen started a discussion
on GitHub about RPM in C++. He said that the project had been
"dreaming about richer data structures than C has to offer
"
since the RPM reboot, but his early experiments in 2010 with C++ left him with
a "resounding 'ugh no' conclusion
". Recently, he took another
look at C++ and "woke up to a language that seems almost like a
distant cousin to the C++ I cursed at in 2010 (and before)
".
With RPM 6.0 on the horizon, it was a good opportunity to enable the use of C++ in the RPM codebase. This is not a rewrite, he said, just an implementation detail. After 4.20 branched, Matilainen merged a commit that made it possible to build RPM with a C++ compiler and start switching to C++. Currently RPM's Python bindings, its plugins, and the low-level engine for RPM's ndb database are not planned for conversion.
In the initial discussion, Neal H. Walfield wondered
whether it would make sense to wait a few more years to port RPM to
Rust instead of C++. Matilainen said
that Rust is not an option, but if someone wants to rewrite RPM in
Rust from
scratch "in another 15 years when I'm retired
", they are
welcome to do so.
The final RPM 4.20 release is expected before the end of September. The most recent release as of this writing is 4.19.94 (aka 4.20 RC2), released on September 10. That release is already available in Fedora 41 Beta, which was released on September 17. It will also likely turn up in the openSUSE Tumbleweed rolling-release distribution early in 2025 (RPM 4.19 entered Tumbleweed in February of this year), though it's unclear whether it will make it into openSUSE Leap 16.
There are quite a few other changes arriving in RPM 4.20, see the draft release notes for a comprehensive list of changes and bug fixes.
The LWN site is currently under high scraper load, so comment display has been suppressed for anonymous users. If you are a human, you may read the comments by clicking the button below:
Note: you can avoid this step in the future by logging into your LWN account.
