Chapter 22. Software management

The following chapter contains the most notable changes to software management between RHEL 8 and RHEL 9.

22.1. Notable changes to software management

Package management with DNF/YUM

In Red Hat Enterprise Linux 9, software installation is ensured by DNF. Red Hat continues to support the usage of the yum term for consistency with previous major versions of RHEL. If you type dnf instead of yum, the command works as expected because both are aliases for compatibility.

Although RHEL 8 and RHEL 9 are based on DNF, they are compatible with YUM used in RHEL 7.

For more information, see Managing software with the DNF tool.

Notable RPM features and changes

Red Hat Enterprise Linux 9 is distributed with RPM version 4.16. This version introduces many enhancements over its previous versions.

Notable features include:

  • New SPEC features, most notably:

    • Fast macro-based dependency generators

      It is now possible to define dependency generators as regular RPM macros. This is especially useful in combination with the embedded Lua interpreter (%{lua:…​}) because it enables writing sophisticated yet fast generators and avoiding redundant forking and executing a shell script.


      %__foo_provides()    %{basename:%{1}}
    • The %generate_buildrequires section that enables generating dynamic build dependencies

      Additional build dependencies can now be generated programmatically at RPM build time, using the newly available %generate_buildrequires section. This is useful when packaging software written in a language in which a specialized utility is commonly used to determine run-time or build-time dependencies, such as Rust, Golang, Node.js, Ruby, Python or Haskell.

    • Meta (unordered) dependencies

      A new dependency qualifier called meta enables expressing dependencies that are not specifically install-time or run-time dependencies. This is useful for avoiding unnecessary dependency loops that could otherwise arise from the normal dependency ordering, such as when specifying the dependencies of a meta package.


      Requires(meta): <pkgname>
    • Native version comparison in expressions

      It is now possible to compare arbitrary version strings in expressions by using the newly supported v"…​" format.


      %if v"%{python_version}" < v"3.9"
    • Caret version operator, opposite of tilde

      The new caret (^) operator can be used to express a version that is higher than the base version. It is a complement to the existing tilde (~) operator which has the opposite semantics.

    • %elif, %elifos and %elifarch statements
    • Optional automatic patch and source numbering

      Patch: and Source: tags without a number are now automatically numbered based on the order in which they are listed.

    • %autopatch now accepts patch ranges

      The %autopatch macro now accepts the -m and -M parameters to limit the minimum and maximum patch number to apply, respectively.

    • %patchlist and %sourcelist sections

      It is now possible to list patch and source files without preceding each item with the respective Patch: and Source: tags by using the newly added %patchlist and %sourcelist sections.

    • A more intuitive way to declare build conditionals

      Starting from RHEL 9.2, you can use the new %bcond macro to build conditionals. The %bcond macro takes a build conditional name and the default value as arguments. Compared to the old %bcond_with and %bcond_without macros, %bcond is easier to understand and allows you to calculate the default value at build time. The default value can be any numeric expression.


      • To create a gnutls build conditional, enabled by default:

        %bcond gnutls 1
      • To create a bootstrap build conditional, disabled by default:

        %bcond bootstrap 0
      • To create an openssl build conditional, defaulting to opposite of gnutls:

        %bcond openssl %{without gnutls}
  • The RPM database is now based on the sqlite library. Read-only support for BerkeleyDB databases has been retained for migration and query purposes.
  • A new rpm-plugin-audit plug-in for issuing audit log events on transactions, previously built into RPM itself
  • Increased parallelism in package builds

    There have been numerous improvements to the way the package build process is parallelized. These improvements involve various buildroot policy scripts and sanity checks, file classification, and subpackage creation and ordering. As a result, package builds on multiprocessor systems, particularly for large packages, should now be faster and more efficient.

  • Enforced UTF-8 validation of header data at build-time
  • RPM now supports the Zstandard (zstd) compression algorithm

    In RHEL 9, the default RPM compression algorithm has switched to Zstandard (zstd). As a result, packages now install faster, which can be especially noticeable during large transactions.