18.4. Spec File Changes For Subpackages

The creation of subpackages is based strictly on the contents of the spec file. This doesn't mean that you'll have to learn an entirely new set of tags, conditionals, and directives in order to create subpackages. In fact, you'll only need to learn one.

The primary change to a spec file is structural and starts with the definition of a preamble for each subpackage.

18.4.1. The Subpackage's "Preamble"

When we introduced RPM package building in Chapter 10, we said that every spec file contains a preamble. The preamble contains a variety of tags that define all sorts of information about the package. In a single package situation, the preamble must be at the start of the spec file. The spec file we're creating will have one there, too.

When creating a spec file that will build subpackages, each subpackage also needs a preamble of its own. These "sub-preambles" need only define information for the subpackage when that information differs from what is defined in the main preamble. For example, if we wanted to define an installation prefix for a subpackage, we would add the appropriate prefix tag to that subpackage's preamble. That subpackage would then be relocatable.

In a single-package spec file, there is nothing that explicitly identifies the preamble, other than its position at the top of the file. For subpackages, however, we need to be a bit more explicit. So we use the %package directive to identify the preamble for each subpackage.

18.4.1.3. Updating Our Spec File

Let's apply some of our newly found knowledge to the spec file we're writing. Here's the list of subpackages that we need to create:

Since our package name is foo, and since the %package directive creates subpackage names by prepending the package name, the %package directives for the foo-server and foo-client subpackages would be written as:

%package server
%package client
            

Since the baz library's package name is not to start with foo, we need to use the -n option on its %package directive:

%package -n bazlib
            

Our requirements further state that foo-server and foo-client are to have the same version as the main package.

One of the time-saving aspects of using subpackages is that there is no need to duplicate information for each subpackage if it is already defined in the main package. Therefore, since the main package's preamble has a version tag defining the version as 2.7, the two subpackages that lack a version tag in their preambles will simply inherit the main package's version definition.

Since the bazlib subpackage's preamble contains a version tag, it must have its own unique version.

In addition, each subpackage must have its own summary tag.

So based on these requirements, our spec file now looks like this:

Name: foo
Version: 2.7
Release: 1
Source: foo-2.7.tgz
CopyRight: probably not
Summary: The foo app, and the baz library needed to build it
Group: bogus/junque
%description
This is the long description of the foo app, and the baz library needed to
build it...

%package server
Summary: The foo server

%package client
Summary: The foo client

%package -n bazlib
Version: 5.6
Summary: The baz library
            

We can see the subpackage structure starting to appear now.

18.4.2. The %files List

In an ordinary single-package spec file, the %files list is used to determine which files are actually going to be packaged. It is no different when building subpackages. What is different, is that there must be a %files list for each subpackage.

Since each %files list must be associated with a particular %package directive, we simply label each %files list with the name of the subpackage, as specified by each %package directive. Going back to our example, our %package lines were:

%package server
%package client
%package -n bazlib
          

Therefore, our %files lists should start with:

%files server
%files client
%files -n bazlib
          

In addition, we need the main package's %files list, which remains unnamed:

%files
          

The contents of each %files list is dictated entirely by the software's requirements. If, for example, a certain file needs to be packaged in more than one package, it's perfectly all right to include the filename in more than one list.

18.4.3. Install- and Erase-time Scripts

The install- and erase-time scripts, %pre, %preun, %post, and %postun, can all be named using exactly the same method as was used for the other subpackage-specific sections of the spec file. The script used during package verification, %verifyscript, can be made package-specific as well. Using the subpackage structure from our example spec file, we would end up with script definitions like:

Other than the change in naming, there's only one thing to be aware of when creating scripts for subpackages. It's important that you consider the possibility of scripts from various subpackages interacting with each other. Of course, this is simply good script-writing practice, even if the packages involved are not related.

18.4.3.1. Back At the Spec File…

Here we've added some scripts to our spec file. So that our example doesn't get too complex, we've just added preinstall scripts for each package:

Name: foo
Version: 2.7
Release: 1
Source: foo-2.7.tgz
CopyRight: probably not
Summary: The foo app, and the baz library needed to build it
Group: bogus/junque
%description
This is the long description of the foo app, and the baz library needed to
build it...

%package server
Summary: The foo server
Group: bogus/junque
%description server
This is the long description for the foo server...

%package client
Summary: The foo client
Group: bogus/junque
%description client
This is the long description for the foo client...

%package -n bazlib
Version: 5.6
Summary: The baz library
Group: bogus/junque
%description -n bazlib
This is the long description for the bazlib...


%pre
echo "This is the foo package preinstall script"

%pre server
echo "This is the foo-server subpackage preinstall script"

%pre client
echo "This is the foo-client subpackage preinstall script"

%pre -n bazlib
echo "This is the bazlib subpackage preinstall script"

%files
/usr/local/foo-file

%files server
/usr/local/server-file

%files client
/usr/local/client-file

%files -n bazlib
/usr/local/bazlib-file
            

As pre-install scripts go, these don't do very much. But they will allow us to see how subpackage-specific scripts can be defined.

Those of you that have built packages before probably realize that our spec file is missing something. Let's add that part now.

Notes

[1]

Hey, we said it was a simple example!