Product SiteDocumentation Site

Chapter 10. Advanced RPM Packaging

10.1. Defining Package Dependencies
10.1.1. Naming dependencies
10.1.2. Setting prerequisites
10.1.3. Naming build dependencies
10.1.4. Generating dependencies automatically
10.2. Setting Triggers
10.3. Writing Verification Scripts
10.4. Creating Subpackages
10.4.1. Providing information for subpackages
10.4.2. Defining scripts for subpackages
10.4.3. Building subpackages
10.5. Creating Relocatable Packages
10.5.1. Setting up the prefixes
10.5.2. Define the files section
10.5.3. Problems creating relocatable packages
10.6. Defining Conditional Builds
10.6.1. Defining conditional macros
10.6.2. Using conditional blocks
10.6.3. Using architecture-based conditionals
10.7. Summary
This chapter covers:
The previous chapter introduced the RPM spec file, which controls how RPM packages are built and installed. This chapter delves into advanced spec file topics such as using conditional commands and making relocatable packages, starting with how to specify package dependencies.

Defining Package Dependencies

Dependencies are one of the most important parts of the RPM system. The RPM database tracks dependencies between packages to better allow you to manage your system. A dependency occurs when one package depends on another. The RPM system ensures that dependencies are honored when upgrading, installing, or removing packages. From that simple concept, RPM supports four types of dependencies:
*Requirements, where one package requires a capability provided by another
*Provides, a listing of the capabilities your package provides
*Conflicts, where one package conflicts with a capability provided by another
*Obsoletes, where one package obsoletes capabilities provided by another, usually used when a package changes name and the new package obsoletes the old name
Cross Reference
Chapter 5, Package Dependencies covers more on dependencies. The Obsoletes dependencies are usually only used when a package is renamed, such as the apache package becoming the httpd package, starting in Red Hat Linux 8.0. The httpd package obsoletes the apache package.
You can list all of these dependencies in your spec file. The most commonly used dependency information, though, is what a package requires.

Naming dependencies

In your spec files, you can name the dependencies for your package. The basic syntax is:
Requires: capability
In most cases, the capability should be the name of another package. This example sets up a requires dependency. This means that the package requires the given capability. Use a similar syntax for the other kinds of dependencies:
Provides: capability
Obsoletes: capability
Conflicts: capability
You can put more than one capability on the dependency line. For example:
Requires: bash perl
You can use spaces or commas to separate the capabilities. For example:
Requires: bash, perl

Specifying the Version of the Dependencies

You can also add version information, for example:
Requires: bash >= 2.0
This states that the package requires the capability bash (a package) at version 2.0 or higher. The same logic applies to the other types of dependencies. For example:
Conflicts: bash >= 2.0
This example states that the package conflicts with all versions of bash 2.0 or higher.
Table 11-1 lists the version comparisons you can use.
Table 11-1 Dependency version comparisons
Comparison
Meaning
package < version
A package with a version number less than version
package > version
A package with a version number greater than version
package >= version
A package with a version number greater than or equal to version
package <= version
A package with a version number less than or equal to version
package = version
A package with a version number equal to version
package
A package at any version number
RPM supports an extended version number syntax for comparisons. The full format follows:
Epoch:Version-Release
For example:
1:5.6.0-17
In this case, the epoch is 1, the version 5.6.0, and the release is 17. In most cases, you will need just the version number. The epoch allows for handling hard-to-compare version numbers. The release number is almost never used. This makes sense, in that it ties a dependency to a particular build of the RPM package, rather than a version of the software itself. This type of dependency would only be useful if you drastically changed the way you build a package.

Creating Virtual CAPABILITIES

Dependencies are based on capabilities, most of which are packages. You can create virtual capabilities, which are just names you define. For example, the sendmail package provides a virtual capability named smtpdaemon. For example:
Provides: smtpdaemon
This capability refers to the general SMTP Internet service for sending e-mail messages. There is no file of this name. Instead, it is just a capability, arbitrary text. Other packages require this capability, such as the fetchmail mail-retrieval and forwarding application, and mutt, an e-mail client program.
By using a virtual capability, other packages can provide the capability, and most importantly, client applications can require the capability without worrying which package provides the ability to send e-mail messages. For example, the exim and postfix packages, mail transport agents like sendmail, can provide the same capability.
Note
Of course, you want to ensure that these packages specify that they conflict with each other.

Naming Dependencies on Script Engines and Modules

Scripting languages such as Perl and Tcl allow for add-on modules. Your package may require some of these add-on modules. RPM uses a special syntax with parenthesis to indicate script module dependencies. For example:
Requires: perl(Carp) >= 3.2
This indicates a requirement for the Carp add-on module for Perl, greater than or equal to version 3.2.

Setting prerequisites

A prerequisite is similar to a require dependency, except that a prerequisite must be installed prior to a given package. Specify a prerequisite as follows:
PreReq: capability
You can include version-number dependencies, such as:
PreReq: capability >= version
In most usage, a PreReq: acts just like Requires:, in fact, the PreReq: directive exists just to allow for a manual order to dependencies. RPM guarantees that the PreReq: package will be installed prior to the package that names the PreReq: dependency.
Cross Reference
Chapter 13, Packaging Guidelines covers a common problem of handling circular dependencies using prerequisites.

Naming build dependencies

Your package, once built, has a set of dependencies. These dependencies are important for anyone installing the package. But there are also dependency issues when trying to build packages. Build dependencies allow you to specify what is necessary to build the package. While you may think this would be the same as what is needed to install a package, this is normally not true. Linux distributions tend to divide up software into runtime and development packages. For example, the python package contains the runtime for executing scripts written in Python. The python-devel package provides the ability to write extensions to the Python language.
RPM allows you to define build-time dependencies in your spec files using the following directives:
BuildRequires:
BuildConflicts:
BuildPreReq:
These directives act like Requires:, Conflicts:, and PreReq:, respectively, except that the dependencies are needed to build the package, not install it. For example, your package may require a C compiler to build, or may need a special build tool or developer library.

Generating dependencies automatically

Because so many dependencies are related to shared libraries, the RPM system will automatically generate provide dependencies for any file in your packages that is a shared object, or .so, file. RPM will also automatically generate require dependencies for all files in the %files list that require shared libraries. To do this, RPM uses the ldd command, which determines the shared libraries used by an application.
In addition, the find-requires and find-provides scripts in /usr/lib/rpm can determine Perl, Python and Tcl script dependencies and other dependencies, such as Java package dependencies, automatically. The find-requires script determines requires dependencies automatically, and the find-provides script determines provides dependencies.
Cross Reference
Chapter 13, Packaging Guidelines covers how to turn off the automatic generation of dependencies.