The way we direct RPM in the build process is to create a spec file. As we saw in the previous chapter, the spec file contains eight different sections, most of which are required. Let's go through each section and create cdplayer's spec file as we go.
The preamble contains a wealth of information about the package being built, and the people that built it. Here's cdplayer's preamble:
# Example spec file for cdplayer app...
Summary: A CD player app that rocks!
Distribution: WSS Linux
Vendor: White Socks Software, Inc.
Packager: Santa Claus <email@example.com>
It slices! It dices! It's a CD player app that
can't be beat. By using the resonant frequency
of the CD itself, it is able to simulate 20X
oversampling. This leads to sound quality that
cannot be equaled with more mundane software...
In general, the preamble consists of entries, one per line, that start with a tag followed by a colon, and then some information. For example, the line starting with ``Summary:'' gives a short description of the packaged software that can be displayed by RPM. The order of the lines is not important, as long as they appear in the preamble.
Let's take a look at each line and see what function it performs:
In our example, the cdplayer sources are contained in the file cdplayer-1.0.tgz, which is available from ftp.gnomovision.com, in the directory /pub/cdplayer. RPM actually ignores everything prior to the last filename in the source line, so the first part of the source string could be anything you'd like. Traditionally, the source line usually contains a Uniform Resource Locator, or URL.
With the preamble, we provided a wealth of information. The majority of this information is meant for human consumption. Only the name, version, release, and source lines have a direct bearing on the package building process. However, in the %prep section, the focus is entirely on directing RPM through the process of preparing the software for building.
It is in the %prep section that the build environment for the software is created, starting with removing the remnants of any previous builds. Following this, the source archive is expanded. Here is what the %prep section looks like in our example spec file:
%prep rm -rf $RPM_BUILD_DIR/cdplayer-1.0 zcat $RPM_SOURCE_DIR/cdplayer-1.0.tgz | tar -xvf -
If the %prep section looks like a script, that's because it is. Any sh constructs can be used here, including expansion of environment variables (Like the $RPM_BUILD_DIR variable defined by RPM), and piping the output of zcat through tar.2
In this case, we perform a recursive delete in the build directory to remove any old builds. We then uncompress the gzipped tar file, and extract its contents into the build directory.
Quite often, the sources may require patching in order to build properly. The %prep section is the appropriate place to patch the sources, but in this example, no patching is required. Fear not, however, as we'll explore patching in all its glory in chapter on page , when we build a more complex package.
While the %prep section as we've described it isn't that difficult to understand, RPM provides macros to make life even easier. In this simple example, there's precious little that can be made easier, but macros will prevent a wealth of headaches when it's time to build more complex packages. The macro we'll introduce here is the %setup macro.
The average gzipped tar file is %setup's stock in trade. Like the hand-crafted %prep section we described above, it cleans up old build trees and then uncompresses and extracts the files from the original source. While %setup has a number of options that we'll cover in later chapters, for now all we need for a %prep section is:
That is simpler than our %prep section, so let's use the %setup macro instead. The %setup macro has a number of options to handle many different situations. For more information on this and other macros, please see section on page .
In our example here, the %prep section is complete. Next comes the actual build.
Not surprisingly, the part of the spec file that is responsible for performing the build, is the %build section. Like the %prep section, the %build section is an ordinary sh script. Unlike the %prep section, there are no macros. The reason for this is that the process of building software is either going to be very easy, or highly complicated. In either case, macros won't help much. In our example, the build process is simple:
Thanks to the make utility, only one command is necessary to build the cdplayer application. In the case of an application with more esoteric build requirements, the %build section could get a bit more interesting.
The %install section is executed as a sh script, just like %prep and %build. If the application is built with make and has an ``install'' target, the %install section will also be straightforward. The cdplayer application is a good example of this:
%install make install
If the application doesn't have a means of automatically installing itself, it will be necessary to create a script to do so, and place it in the %install section.
The %files section is different from the others, in that it contains a list of the files that are part of the package. Always remember -- if it isn't in the file list, it won't be put in the package!
%files %doc README /usr/local/bin/cdp /usr/local/bin/cdplay /usr/local/man/man1/cdp.1
The line starting with %doc is an example of RPM's handling of different file types. As you might guess, %doc stands for documentation. The %doc directive is used to mark files as being documentation. In the example above, the README file will be placed in a package-specific directory, located in /usr/doc, and called cdplayer-1.0-1. It's also possible to mark files as documentation and have them installed in other directories. This is covered in more detail in section on page .
The rest of the files in the example are shown with complete paths. This is necessary as the files will actually be installed in those directories by the application's makefile. Since RPM needs to be able to find the files prior to packaging them, complete paths are required.
Since RPM automates so many aspects of software installation, it's easy to fall into the trap of assuming that RPM does everything for you. Not so! One task that is still a manual process is creating the file list. While it may seem at first glance, that it could be automated somehow, it's actually a more difficult problem than it seems.
Since the majority of an application's files are installed by its makefile, RPM has no control over that part of the build process, and therefore, cannot automatically determine which files should be part of the package. Some people have attempted to use a modified version of install that logs the name of every file it installs. But not every makefile uses install, or if it does, uses it sporadically.
Another approach tried was to obtain a list of every file on the build system, immediately before and after a build, and use the differences as the file list. While this approach will certainly find every file that the application installed, it can also pick up extraneous files, such as system logs, files in /tmp, and the like. The only way to begin to make this approach workable would be to do nothing else on the build system, which is highly inconvenient. This approach also precludes building more than one package on the system at any given time.
At present, the best way to create the file list is to read the makefile to see what files it installs, verify this against the files installed on the build system, and create the list.
Since our example spec file is somewhat simplistic, it's missing two sections that might be used in more complex situations. We'll go over each one briefly here. More complete information on these sections will be covered at various points in the book.
One missing section to our spec file is the section that would define one or more of four possible scripts. The scripts are executed at various times when a package is installed or erased.
The scripts can be executed:
We'll see how these scripts are used in chapter on page .
The other missing section has the rather descriptive title of %clean. This section can be used to clean up any files that are not part of the application's normal build area. For example, if the application creates a directory structure in /tmp as part of its build, it will not be removed. By adding a sh script to the %clean section, such situations can be handled gracefully, right after the binary package is created.