Библиотека сайта rus-linux.net
|Maximum RPM: Taking the Red Hat Package Manager to the Limit|
|Prev||Chapter 13. Inside the Spec File||Next|
The scripts that RPM uses to control the build process are among the most varied and interesting parts of the spec file. Many spec files also contain scripts that perform a variety of tasks whenever the package is installed or erased.
The start of each script is denoted by a keyword. For example, the %build keyword marks the start of the script RPM will execute when building the software to be packaged. It should be noted that, in the strictest sense of the word, these parts of the spec file are not scripts. For example, they do not start with the traditional invocation of a shell. However, the contents of each script section are copied into a file and executed by RPM as a full-fledged script. This is part of the power of RPM: Anything that can be done in a script can be done by RPM.
Let's start by looking at the scripts used during the build process.
The scripts that RPM uses during the building of a package follow the steps known to every software developer:
Unpacking the sources.
Building the software.
Installing the software.
cdplayerpackage, issued an rpm -ba --test cdplayer-1.0-1.spec, and viewed the script files left in RPM's temporary directory. This section (with the appropriate package-specific values) is present in every script RPM executes during a build:
As we can see, the script starts with the usual invocation of a shell (in this case, the Bourne shell). There are no arguments passed to the script. Next, a number of environment variables are set. Here's a brief description of each one:
RPM_SOURCE_DIR— This environment variable gets its value from the rpmrc file entry sourcedir, which in turn can get part of its value from the topdir entry. It is the path RPM will prepend to the file, specified in the source tag line.
RPM_BUILD_DIR— This variable is based on the builddir rpmrc file entry, which in turn can get part of its value from the topdir entry. This environment variable translates to the path of RPM's build directory, where most software will be unpacked and built.
RPM_DOC_DIR— The value of this environment variable is based on the defaultdocdir
rpmrcfile entry. Files marked with the %doc directive can be installed in a subdirectory of defaultdocdir. For more information on the %doc directive, refer to the section called The %doc Directive.
RPM_OPT_FLAGS— This environment variable gets its value from the optflags
rpmrcfile entry. It contains options that can be passed on to the build procedures of the software being packaged. Normally this means either a configuration script or the make command itself.
RPM_ARCH— As one might infer from the example above, this environment variable contains a string describing the build system's architecture.
RPM_OS— This one contains the name of the build system's operating system.
RPM_BUILD_ROOT— This environment variable is used to hold the "build root", into which the newly built software will be installed. If no explicit build root has been specified (either by command line option, spec file tag line, or rpmrc file entry), this variable will be null.
RPM_PACKAGE_NAME— This environment variable gets its value from the name tag line in the package's spec file. It contains the name of the software being packaged.
RPM_PACKAGE_VERSION— The version tag line is the source of this variable's translation. Predictably, this environment variable contains the software's version number.
RPM_PACKAGE_RELEASE— This environment variable contains the package's release number. Its value is obtained from the release tag line in the spec file.
All of these environment variables are set for your use, to make it easier to write scripts that will do the right thing even if the build environment changes.
The script also sets an option that causes the shell to print out each command, complete with expanded arguments. Finally, the default permissions are set. Past this point, the scripts differ. Let's look at the scripts in the order they are executed.
The %prep script is the first script RPM executes
during a build. Prior to the %prep script, RPM
has performed preliminary consistency checks, such as whether the
spec file's source tag points to files that
actually exist. Just prior to passing control over to the
%prep script's contents, RPM changes directory
into RPM's build area, which, by default, is
At that point, it is the responsibility of the %prep script to:
Create the top-level build directory.
Unpack the original sources into the build directory.
Apply patches to the sources, if necessary.
Perform any other actions required to get the sources in a ready-to-build state.
The first three items on this list are common to the vast majority of all software being packaged. Because of this, RPM has two macros that greatly simplify these routine functions. More information on RPM's %setup and %patch macros can be found in the section called Macros: Helpful Shorthand for Package Builders.
The last item on the list can include creating directories or anything else required to get the sources in a ready-to-build state. As a result, a %prep script can range from one line invoking a single %setup macro, to many lines of tricky shell programming.
The %build script picks up where the %prep script left off. Once the %prep script has gotten everything ready for the build, the %build script is usually somewhat anti-climactic — normally invoking make, maybe a configuration script, and little else.
Like %prep before it, the
%build script has the same assortment of
environment variables to draw on. Also, like
%prep, %build changes
directory into the software's top-level build directory (located in
RPM_BUILD_DIR, or usually called
Unlike %prep, there are no macros available for use in the %build script. The reason is simple: Either the commands required to build the software are simple (such as a single make command), or they are so unique that a macro wouldn't make it easier to write the script.
The environment in which the %install script executes is identical to the other scripts. Like the other scripts, the %install script's working directory is set to the software's top-level directory.
As the name implies, it is this script's responsibility to do whatever is necessary to actually install the newly built software. In most cases, this means a single make install command, or a few commands to copy files and create directories.
The %clean script, as the name implies, is used to clean up the software's build directory tree. RPM normally does this for you, but in certain cases (most notably in those packages that use a build root) you'll need to include a %clean script.
RPM_BUILD_ROOTenvironment variable is particularly useful. In many cases, a simple
The other type of scripts that are present in the spec file are those that are only used when the package is either installed or erased. There are four scripts, each one meant to be executed at different times during the life of a package:
Unlike the build-time scripts, there is little in the way of
environment variables for these scripts. The only environment
variable available is
RPM_INSTALL_PREFIX, and that is
only set if the package uses an installation prefix.
Unlike the build-time scripts, there is an argument defined. The sole argument to these scripts, is a number representing the number of instances of the package currently installed on the system, after the current package has been installed or erased. Sound tricky? It really isn't. Here's an example:
Assume that a package, called
being installed. No previous versions of
have been installed. Since the software is being installed, only the
%pre and %post scripts are
executed. The argument passed to these scripts will be 1, since the
the number of
blather packages installed is 1.
Continuing our example, a new version of the
blather package, version 1.3, is now available.
Clearly it's time to upgrade. What will the scripts' values be during
the upgrade? As
blather-1.3 is installing, its
%pre and %post scripts will have
an argument equal to 2 (1 for version 1.0 already installed, plus 1
for version 1.3 being installed). As the final part of the upgrade,
it's then time to erase
blather version 1.0. As
the package is being removed, its %preun and
%postun scripts are executed. Since there will be
blather package (version 1.3) installed
after version 1.0 is erased, the argument passed to version 1.0's
scripts is 1.
To finally bring an end to this example, we've decided to erase
blather 1.3. We just don't need it anymore. As
the package is being erased, its %preun and
%postun scripts will be executed. Since there will
blather packages installed once the erase
completes, the argument passed to the scripts is 0.
With all that said, of what possible use would this argument be? Well, it has two very interesting properties:
When the first version of a package is installed, its %pre and %post scripts will be passed an argument equal to 1.
When the last version of a package is erased, its %preun and %postun scripts will be passed an argument equal to 0.
Based on these properties, it's trivial to write an install-time script that can take certain actions in specific circumstances. Usually, the argument is used in the %preun or %postun scripts to perform a special task when the last instance of a package is being erased.
What is normally done during these scripts? The exact tasks may vary, but in general, the tasks are any that need to be performed at these points in the package's existence. One very common task is to run ldconfig when shared libraries are installed or removed. But that's not the only use for these scripts. It's even possible to use the scripts to perform tests to ensure the package install/erasure should proceed.
Since each of these scripts will be executing on whatever system installs the package, it's necessary to choose the script's choice of tools carefully. Unless you're sure a given program is going to be available on all the systems that could possibly install your package, you should not use it in these scripts.
The %pre script executes just before the package is to be installed. It is the rare package that requires anything to be done prior to installation; none of the 350 packages that comprise Red Hat Linux Linux 4.0 make use of it.
The %post script executes after the package has
been installed. One of the most popular reasons a
%post script is needed is to run
ldconfig to update the list of available shared
libraries after a new one has been installed. Of course, other
functions can be performed in a %post script.
For example, packages that install shells use the
%post script to add the shell name to
If a package uses a %post script to perform some function, quite often it will include a %postun script that performs the inverse of the %post script, after the package has been removed.
If there's a time when your package needs to have one last look around before the user erases it, the place to do it is in the %preun script. Anything that a package needs to do immediately prior to RPM taking any action to erase the package, can be done here.
The %postun script executes after the package has
been removed. It is the last chance for a package to clean up after
itself. Quite often, %postun scripts are used to
run ldconfig to remove newly erased shared
In this script, the config file
checked to ensure that it has entries for the shells provided by this
It is worth noting that the script sends informational and error messages to stdout, and error messages only to stderr. Normally RPM will only display error output from a verification script; the output sent to stdout is only displayed when the verification is run in verbose mode.
Keep in mind that this command in a %clean
script can wreak havoc if used with a build root of, say,
Or it will be 1, once the package is completely installed. Remember, the number is based on the number of packages installed after the current package's install or erase has completed.