Chapter 6. New features in RHEL 8
This section documents the most notable changes in RPM packaging between Red Hat Enterprise Linux 7 and 8.
6.1. Support for Weak dependencies
Weak dependencies
are variants of the Requires
directive. These variants are matched against virtual Provides:
and package names using Epoch-Version-Release
range comparisons.
Weak dependencies
have two strengths (weak
and hint
) and two directions (forward
and backward
), as summarized in the following table.
The forward
direction is analogous to Requires:
. The backward
has no analog in the previous dependency system.
Strength/Direction | Forward | Backward |
---|---|---|
Weak | Recommends: | Supplements: |
Hint | Suggests: | Enhances: |
The main advantages of the Weak dependencies
policy are:
- It allows smaller minimal installations while keeping the default installation feature rich.
- Packages can specify preferences for specific providers while maintaining the flexibility of virtual provides.
6.1.1. Introduction to Weak dependencies
By default, Weak dependencies
are treated similarly to regular Requires:
. Matching packages are included in the YUM transaction. If adding the package leads to an error, YUM by default ignores the dependency. Hence, users can exclude packages that would be added by Weak dependencies
or remove them later.
Conditions of use
You can use Weak dependencies
only if the package still functions without the dependency.
It is acceptable to create packages with very limited functionality without adding any of its weak requirements.
Use cases
Use Weak dependencies
especially where it is possible to minimize the installation for reasonable use cases, such as building virtual machines or containers that have a single purpose and do not require the full feature set of the package.
Typical use cases for Weak dependencies
are:
Documentation
- Documentation viewers if missing them is handled gracefully
- Examples
Plug-ins or add-ons
- Support for file formats
- Support for protocols
6.1.2. The Hints strength
Hints
are by default ignored by YUM. They can be used by GUI tools to offer add-on packages that are not installed by default but can be useful in combination with the installed packages.
Do not use Hints
for the requirements of the main use cases of a package. Include such requirements in the strong or Weak dependencies
instead.
Package Preference
YUM uses Weak dependencies
and Hints
to decide which package to use if there is a choice between multiple equally valid packages. Packages that are pointed at by dependencies from installed or to be installed packages are preferred.
Note, the normal rules of dependency resolution are not influenced by this feature. For example, Weak dependencies
cannot enforce an older version of a package to be chosen.
If there are multiple providers for a dependency, the requiring package can add a Suggests:
to provide a hint to the dependency resolver about which option is preferred.
Enhances:
is only used when the main package and other providers agree that adding the hint to the required package is for some reason the cleaner solution.
Example 6.1. Using Hints to prefer one package over another
Package A: Requires: mysql Package mariadb: Provides: mysql Package community-mysql: Provides: mysql
If you want to prefer the mariadb
package over the community-mysql
package
Suggests: mariadb to Package A.
6.1.3. Forward and Backward dependencies
Forward dependencies
are, similarly to Requires
, evaluated for packages that are being installed. The best of the matching packages are also installed.
In general, prefer Forward dependencies
. Add the dependency to the package when getting the other package added to the system.
For Backward dependencies
, the packages containing the dependency are installed if a matching package is installed as well.
Backward dependencies
are mainly designed for third party vendors who can attach their plug-ins, add-ons, or extensions to distribution or other third party packages.
6.2. Support for Boolean dependencies
Starting with version 4.13, RPM is able to process boolean expressions in the following dependencies:
-
Requires
-
Recommends
-
Suggests
-
Supplements
-
Enhances
-
Conflicts
The following sections describe boolean dependencies syntax, provides a list of boolean operators, and explains boolean dependencies nesting as well as boolean dependencies semantics.
6.2.1. Boolean dependencies syntax
Boolean expressions are always enclosed with parenthesis.
They are build out of normal dependencies:
- Name only or name
- Comparison
- Version description
6.2.2. Boolean operators
RPM 4.13 introduced the following boolean operators:
Boolean operator | Description | Example use |
---|---|---|
| Requires all operands to be fulfilled for the term to be true. | Conflicts: (pkgA and pkgB) |
| Requires one of the operands to be fulfilled for the term to be true. | Requires: (pkgA >= 3.2 or pkgB) |
| Requires the first operand to be fulfilled if the second is. (reverse implication) | Recommends: (myPkg-langCZ if langsupportCZ) |
|
Same as the | Requires: myPkg-backend-mariaDB if mariaDB else sqlite |
RPM 4.14 introduced the following additional boolean operators:
Boolean operator | Description | Example use |
---|---|---|
| Requires all operands to be fulfilled by the same package for the term to be true. | Requires: (pkgA-foo with pkgA-bar) |
| Requires a single package that satisfies the first operand but not the second. (set subtraction) | Requires: (pkgA-foo without pkgA-bar) |
| Requires the first operand to be fulfilled if the second is not. (reverse negative implication) | Conflicts: (myPkg-driverA unless driverB) |
|
Same as the | Conflicts: (myPkg-backend-SDL1 unless myPkg-backend-SDL2 else SDL2) |
The if
operator cannot be used in the same context with the or
operator, and the unless
operator cannot be used in the same context with and
.
6.2.3. Nesting
Operands themselves can be used as boolean expressions, as shown in the below examples.
Note that in such case, operands also need to be surrounded by parenthesis. You can chain the and
and or
operators together repeating the same operator with only one set of surrounding parenthesis.
Example 6.2. Example use of operands applied as boolean expressions
Requires: (pkgA or pkgB or pkgC)
Requires: (pkgA or (pkgB and pkgC))
Supplements: (foo and (lang-support-cz or lang-support-all))
Requires: (pkgA with capB) or (pkgB without capA)
Supplements: ((driverA and driverA-tools) unless driverB)
Recommends: myPkg-langCZ and (font1-langCZ or font2-langCZ) if langsupportCZ
6.2.4. Semantics
Using Boolean dependencies
does not change the semantic of regular dependencies.
If Boolean dependencies
are used, checking for one match all names are checked and the boolean value of there being a match is then aggregated over the Boolean operators.
For all dependencies with the exception of Conflicts:
, the result has to be True
to not prevent an install. For Conflicts:
, the result has to be False
to not prevent an install.
Provides
are not dependencies and cannot contain boolean expressions.
6.2.5. Understanding the output of the if operator
The if
operator is also returning a boolean value, which is usually close to what the intuitive understanding is. However, the below examples show that in some cases intuitive understanding of if
can be misleading.
Example 6.3. Misleading outputs of the if operator
This statement is true if pkgB is not installed. However, if this statement is used where the default result is false, things become complicated:
Requires: (pkgA if pkgB)
This statement is a conflict unless pkgB is installed and pkgA is not:
Conflicts: (pkgA if pkgB)
So you might rather want to use:
Conflicts: (pkgA and pkgB)
The same is true if the if
operator is nested in or
terms:
Requires: ((pkgA if pkgB) or pkgC or pkg)
This also makes the whole term true, because the if
term is true if pkgB is not installed. If pkgA only helps if pkgB is installed, use and
instead:
Requires: ((pkgA and pkgB) or pkgC or pkg)
6.3. Support for File triggers
File triggers
are a kind of RPM scriptlets,
which are defined in a spec
file of a package.
Similar to Triggers, they are declared in one package but executed when another package that contains the matching files is installed or removed.
A common use of File triggers
is to update registries or caches. In such use case, the package containing or managing the registry or cache should contain also one or more File triggers
. Including File triggers
saves time compared to the situation when the package controls updating itself.
6.3.1. File triggers syntax
File triggers
have the following syntax:
%file_trigger_tag [FILE_TRIGGER_OPTIONS] — PATHPREFIX… body_of_script
Where:
file_trigger_tag
defines a type of file trigger. Allowed types are:
-
filetriggerin
-
filetriggerun
-
filetriggerpostun
-
transfiletriggerin
-
transfiletriggerun
-
transfiletriggerpostun
FILE_TRIGGER_OPTIONS
have the same purpose as RPM scriptlets options, except for the -P
option.
The priority of a trigger is defined by a number. The bigger number, the sooner the file trigger script is executed. Triggers with priority greater than 100000 are executed before standard scriptlets, and the other triggers are executed after standard scriptlets. The default priority is set to 1000000.
Every file trigger of each type must contain one or more path prefixes and scripts.
6.3.2. Examples of File triggers syntax
The following example shows the File triggers
syntax:
%filetriggerin — /lib, /lib64, /usr/lib, /usr/lib64 /usr/sbin/ldconfig
This file trigger executes /usr/bin/ldconfig
directly after the installation of a package that contains a file having a path starting with /usr/lib
or /lib
. The file trigger is executed just once even if the package includes multiple files with the path starting with /usr/lib
or /lib
. However, all file names starting with /usr/lib
or /lib
are passed to standard input of trigger script so that you can filter inside of your script as shown below:
%filetriggerin — /lib, /lib64, /usr/lib, /usr/lib64 grep "foo" && /usr/sbin/ldconfig
This file trigger executes /usr/bin/ldconfig
for each package containing files starting with /usr/lib
and containing foo
at the same time. Note that the prefix-matched files include all types of files including regular files, directories, symlinks and others.
6.3.3. File triggers types
File triggers
have two main types:
File triggers
are further divided based on the time of execution as follows:
- Before or after installation or erasure of a package
- Before or after a transaction
6.3.3.1. Executed once per package File triggers
File triggers
executed once per package are:
- %filetriggerin
- %filetriggerun
- %filetriggerpostun
%filetriggerin
This file trigger is executed after installation of a package if this package contains one or more files that match the prefix of this trigger. It is also executed after installation of a package that contains this file trigger and there is one or more files matching the prefix of this file trigger in the rpmdb
database.
%filetriggerun
This file trigger is executed before uninstallation of a package if this package contains one or more files that match the prefix of this trigger. It is also executed before uninstallation of a package that contains this file trigger and there is one or more files matching the prefix of this file trigger in rpmdb
.
%filetriggerpostun
This file trigger is executed after uninstallation of a package if this package contains one or more files that match the prefix of this trigger.
6.3.3.2. Executed once per transaction File triggers
File triggers
executed once per transaction are:
- %transfiletriggerin
- %transfiletriggerun
- %transfiletriggerpostun
%transfiletriggerin
This file trigger is executed once after a transaction for all installed packages that contain one or more files that match the prefix of this trigger. It is also executed after a transaction if there was a package containing this file trigger in that transaction and there is one or more files matching the prefix of this trigger in rpmdb
.
%transfiletriggerun
This file trigger is executed once before a transaction for all packages that meet the following conditions:
- The package will be uninstalled in this transaction
- The package contains one or more files that match the prefix of this trigger
It is also executed before a transaction if there is a package containing this file trigger in that transaction and there is one or more files matching the prefix of this trigger in rpmdb
.
%transfiletriggerpostun
This file trigger is executed once after a transaction for all uninstalled packages that contain one or more file that matches the prefix of this trigger.
The list of triggering files is not available in this trigger type.
Therefore, if you install or uninstall multiple packages that contain libraries, the ldconfig cache is updated at the end of the whole transaction. This significantly improves the performance compared to RHEL 7 where the cache was updated for each package separately. Also the scriptlets which called ldconfig in %post and %postun in spec
file of every package are no longer needed.
6.3.4. Example use of File triggers in glibc
The following example shows a real-world usage of File triggers
within the glibc
package.
In RHEL 8, File triggers
are implemented in glibc
to call the ldconfig
command at the end of an installation or uninstallation transaction.
This is ensured by including the following scriptlets in the glibc’s
SPEC file:
%transfiletriggerin common -P 2000000 – /lib /usr/lib /lib64 /usr/lib64 /sbin/ldconfig %end %transfiletriggerpostun common -P 2000000 – /lib /usr/lib /lib64 /usr/lib64 /sbin/ldconfig %end
Therefore, if you install or uninstall multiple packages, the ldconfig
cache is updated for all installed libraries after the whole transaction is finished. Consequently, it is no longer necessary to include the scriptlets calling ldconfig
in RPM spec
files of individual packages. This improves the performance compared to RHEL 7, where the cache was updated for each package separately.
6.4. Stricter SPEC parser
The SPEC parser has now some changes incorporated. Hence, it can identify new issues that were previously ignored.
6.5. Support for files above 4 GB
On Red Hat Enterprise Linux 8, RPM can use 64-bit variables and tags, which enables operating on files and packages bigger than 4 GB.
6.5.1. 64-bit RPM tags
Several RPM tags exist in both 64-bit versions and previous 32-bit versions. Note that the 64-bit versions have the LONG
string in front of their name.
32-bit variant tag name | 62-bit variant tag name | Tag description |
---|---|---|
RPMTAG_SIGSIZE | RPMTAG_LONGSIGSIZE | Header and compressed payload size. |
RPMTAG_ARCHIVESIZE | RPMTAG_LONGARCHIVESIZE | Uncompressed payload size. |
RPMTAG_FILESIZES | RPMTAG_LONGFILESIZES | Array of file sizes. |
RPMTAG_SIZE | RPMTAG_LONGSIZE | Sum of all file sizes. |
6.5.2. Using 64-bit tags on command line
The LONG
extensions are always enabled on the command line. If you previously used scripts containing the rpm -q --qf
command, you can add long
to the name of such tags:
rpm -qp --qf="[%{filenames} %{longfilesizes}\n]"
6.6. Other features
Other new features related to RPM packaging in Red Hat Enterprise Linux 8 are:
- Simplified signature checking output in non-verbose mode
- Support for the enforced payload verification
- Support for the enforcing signature checking mode
- Additions and deprecations in macros
Additional resources
See the following references to various topics related to RPMs, RPM packaging, and RPM building. Some of these are advanced and extend the introductory material included in this documentation.
Red Hat Software Collections Overview - The Red Hat Software Collections offering provides continuously updated development tools in latest stable versions.
Red Hat Software Collections - The Packaging Guide provides an explanation of Software Collections and details how to build and package them. Developers and system administrators with basic understanding of software packaging with RPM can use this Guide to get started with Software Collections.
Mock - Mock provides a community-supported package building solution for various architectures and different Fedora or RHEL versions than has the build host.
RPM Documentation - The official RPM documentation.
Fedora Packaging Guidelines - The official packaging guidelines for Fedora, useful for all RPM-based distributions.