White Paper: Changes in RPM 3.0


< Prev Contents  

Features for packagers

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.


< Prev Contents