|
One of my goals in RPM 3.0 was to permit package builders more
flexibility. RPM was designed to build software packages reliably
and reproducibly. Software development using RPM proceeds in strict
stages from virgin sources with local patches applied, through
configuration, compilation and installation, and finally to preparation
of a manifest that includes not only the files that are in a package
but also the libraries, tools, and procedures needed to successfully
install the package. The final output of a build typically consists of
a source package and one or more binary packages that can be installed.
The entire build process is described in something called a
spec file.
The strict adherance to a rigorous methodology in using RPM to produce
packages is often a pain. Building a package can take much longer than
simply compiling a program. Correcting even simple typographic errors
in a spec file necessitates restarting a build from the beginning, and
much of the art of programming is reduced to an obsession with mind-numbing
packaging details such as correcting broken symbolic links, classifying
files as documentation or configuration, and generally making sure that
each and every file is properly tucked into its swaddling package.
The focus on encapsulating all components necessary to produce a binary
package in RPM prevents reuse of common code. The encapsulation is called
a source rpm and consists of the virgin sources,
local patches, and the spec file describing the build process. The spec
file is augmented with certain configuration information such as the
compiler flags to use and the architecture on which the package is
being built but very little else that is of use in preparing a package.
The information provided by RPM to a package is reminiscent of what
UNIX C compilers supplied to programs around 1986. In the early days
of computing, programmers routinely used constructs like
#if sun
... C code that depends on the most significant byte stored first ...
#else
... C code that depends on the least significant byte stored first ...
#endif
|
to condition sections of code depending on computer architecture.
The section of code that was marked for conditional compilation often
depended on, for example, some property of the "sun" architecture such
as the ordering of bytes in an integer. By testing for the compiler supplied
variable "sun", a program was able determine whether the most or
least significant byte was stored first. Note that the test implictly
assumed the connection between the property of byte ordering and the
architecture. Note also that the code broke the day that Sun Microsystems
shipped an operating system for an Intel computer.
Just as modern programming practices have evolved through more sophisticated
configuration techniques, RPM 3.0 attempts to provide a more flexible
configuration mechanism to package builders using a macro facility.
In order to build binary packages for a variety of architectures and
operating systems from identical source packages, parts of the
build procedure will need to be parameterized to adapt to specfic differences
between platforms. By providing commonly used packaging procedures on each
build platform as macros, RPM 3.0 can accommodate many of the differences
encountered on a variety of platforms.
Although previous versions of RPM have had a macro facility, there are
several important differences in RPM 3.0 macros. The most important
difference is that macros in RPM 3.0 are recursively evaluated when used
rather than being simply evaluated when parsed. Recursive evaluation on
use permits macros to be loaded from multiple sources and to be composed
from yet other macros in order to provide a simple and robust configuration
mechanism.
Package builders will certainly notice that RPM 3.0 configuration is
different. RPM establishes a configuration by reading first a global
/usr/lib/rpm/rpmrc file, then an optional per-site /etc/rpmrc file, and
finally an optional .rpmrc file located in the builder's home directory.
Site-specific configuration information has been reimplemented using macros.
The order and locations from which macros can be read is configurable, and
the default order and locations of macro files is similar to that of rpmrc
files. Changing the configuration paradigm is the first step in unifying
the method by which information is supplied from the spec file, the build
system and eventually the command line used to build a package.
Last but not least, RPM 3.0 supports build prerequisites. A build
prerequisite permits a source package to check whether all the components
necessary to build a package are installed on the build system. The use of
build prerequisites can assist in identifying missing components on a
build system by name without having to examine the output of the
build process itself.
|