Previous Next Contents

6. Building RPMs

Building RPMs is fairly easy to do, especially if you can get the software you are trying to package to build on its own.

The basic procedure to build an RPM is as follows:

Under normal operation, RPM builds both binary and source packages.

6.1 The rpmrc File

Right now, the only configuration of RPM is available via the /etc/rpmrc file. An example one looks like:

require_vendor: 1
distribution: I roll my own!
require_distribution: 1
topdir: /usr/src/me
vendor: Mickiesoft
packager:  Mickeysoft Packaging Account <packages@mickiesoft.com>

optflags: i386 -O2 -m486 -fno-strength-reduce
optflags: alpha -O2
optflags: sparc -O2

signature: pgp
pgp_name: Mickeysoft Packaging Account
pgp_path: /home/packages/.pgp

tmppath: /usr/tmp

The require_vendor line causes RPM to require that it find a vendor line. This can come from the /etc/rpmrc or from the header of the spec file itself. To turn this off, change the number to 0. The same holds true for the require_distribution and require_group lines.

The next line is the distribution line. You can define that here or later in the header of the spec file. When building for a particular distribution, it's a good idea to make sure this line is correct, even though it is not required. The vendor line works much the same way, but can be anything (ie. Joe's Software and Rock Music Emporium).

RPM also now has support for building packages on multiple architectures. The rpmrc file can hold an ``optflags'' variable for building things that require architecture specific flags when building. See later sections for how to use this variable.

In addition to the above macros, there are several more. You can use:

rpm --showrc
to find out how your tags are set and what all the available flags are.

6.2 The Spec File

We'll begin with discussion of the spec file. Spec files are required to build a package. The spec file is a description of the software along with instructions on how to build it and a file list for all the binaries that get installed.

You'll want to name your spec file according to a standard convention. It should be the package name-dash-version number-dash-release number-dot-spec.

Here is a small spec file (vim-3.0-1.spec):

Summary: ejects ejectable media and controls auto ejection
Name: eject
Version: 1.4
Release: 3
Copyright: GPL
Group: Utilities/System
Source: sunsite.unc.edu:/pub/Linux/utils/disk-management/eject-1.4.tar.gz
Patch: eject-1.4-make.patch
Patch1: eject-1.4-jaz.patch
%description
This program allows the user to eject media that is autoejecting like
CD-ROMs, Jaz and Zip drives, and floppy drives on SPARC machines.

%prep
%setup
%patch -p1
%patch1 -p1

%build
make RPM_OPT_FLAGS="$RPM_OPT_FLAGS"

%install
install -s -m 755 -o 0 -g 0 eject /usr/bin/eject
install -m 644 -o 0 -g 0 eject.1 /usr/man/man1

%files
%doc README COPYING ChangeLog

/usr/bin/eject
/usr/man/man1/eject.1

6.3 The Header

The header has some standard fields in it that you need to fill in. There are a few caveats as well. The fields must be filled in as follows:

6.4 Prep

This is the second section in the spec file. It is used to get the sources ready to build. Here you need to do anything necessary to get the sources patched and setup like they need to be setup to do a make.

One thing to note: Each of these sections is really just a place to execute shell scripts. You could simply make an sh script and put it after the %prep tag to unpack and patch your sources. We have made macros to aid in this, however.

The first of these macros is the %setup macro. In its simplest form (no command line options), it simply unpacks the sources and cd's into the source directory. It also takes the following options:

The next of the available macros is the %patch macro. This macro helps automate the process of applying patches to the sources. It takes several options, listed below:

That should be all the macros you need. After you have those right, you can also do any other setup you need to do via sh type scripting. Anything you include up until the %build macro (discussed in the next section) is executed via sh. Look at the example above for the types of things you might want to do here.

6.5 Build

There aren't really any macros for this section. You should just put any commands here that you would need to use to build the software once you had untarred the source, patched it, and cd'ed into the directory. This is just another set of commands passed to sh, so any legal sh commands can go here (including comments). Your current working directory is reset in each of these sections to the toplevel of the source directory, so keep that in mind. You can cd into subdirectories if necessary.

6.6 Install

There aren't really any macros here, either. You basically just want to put whatever commands here that are necessary to install. If you have make install available to you in the package you are building, put that here. If not, you can either patch the makefile for a make install and just do a make install here, or you can hand install them here with sh commands. You can consider your current directory to be the toplevel of the source directory.

6.7 Optional pre and post Install/Uninstall Scripts

You can put scripts in that get run before and after the installation and uninstallation of binary packages. A main reason for this is to do things like run ldconfig after installing or removing packages that contain shared libraries. The macros for each of the scripts is as follows:

The contents of these sections should just be any sh style script, though you do not need the #!/bin/sh.

6.8 Files

This is the section where you must list the files for the binary package. RPM has no way to know what binaries get installed as a result of make install. There is NO way to do this. Some have suggested doing a find before and after the package install. With a multiuser system, this is unacceptable as other files may be created during a package building process that have nothing to do with the package itself.

There are some macros available to do some special things as well. They are listed and described here:

The biggest caveat in the file list is listing directories. If you list /usr/bin by accident, your binary package will contain every file in /usr/bin on your system.

6.9 Building It

The Source Directory Tree

The first thing you need is a properly configured build tree. This is configurable using the /etc/rpmrc file. Most people will just use /usr/src.

You may need to create the following directories to make a build tree:

Test Building

The first thing you'll probably want to to is get the source to build cleanly without using RPM. To do this, unpack the sources, and change the directory name to $NAME.orig. Then unpack the source again. Use this source to build from. Go into the source directory and follow the instructions to build it. If you have to edit things, you'll need a patch. Once you get it to build, clean the source directory. Make sure and remove any files that get made from a configure script. Then cd back out of the source directory to its parent. Then you'll do something like:

        diff -uNr dirname.orig dirname > ../SOURCES/dirname-linux.patch
This will create a patch for you that you can use in your spec file. Note that the ``linux'' that you see in the patch name is just an identifier. You might want to use something more descriptive like ``config'' or ``bugs'' to describe why you had to make a patch. It's also a good idea to look at the patch file you are creating before using it to make sure no binaries were included by accident.

Generating the File List

Now that you have source that will build and you know how to do it, build it and install it. Look at the output of the install sequence and build your file list from that to use in the spec file. We usually build the spec file in parallel with all of these steps. You can create the initial one and fill in the easy parts, and then fill in the other steps as you go.

Building the Package with RPM

Once you have a spec file, you are ready to try and build your package. The most useful way to do it is with a command like the following:

        rpm -ba foobar-1.0.spec

There are other options useful with the -b switch as well:

There are several modifiers to the -b switch. They are as follows:

6.10 Testing It

Once you have a source and binary rpm for your package, you need to test it. The easiest and best way is to use a totally different machine from the one you are building on to test. After all, you've just done a lot of make install's on your own machine, so it should be installed fairly well.

You can do an rpm -u packagename on the package to test, but that can be deceiving because in building the package, you did a make install. If you left something out of your file list, it will not get uninstalled. You'll then reinstall the binary package and your system will be complete again, but your rpm still isn't. Make sure and keep in mind that just because you do a rpm -ba package, most people installing your package will just be doing the rpm -i package. Make sure you don't do anything in the build or install sections that will need to be done when the binaries are installed by themselves.

6.11 What to do with your new RPMs

Once you've made your own RPM of something (assuming its something that hasn't already been RPM'ed), you can contribute your work to others (also assuming you RPM'ed something freely distributable). To do so, you'll want to upload it to ftp.redhat.com.

6.12 What Now?

Please see the above sections on Testing and What to do with new RPMs. We want all the RPMs available we can get, and we want them to be good RPMs. Please take the time to test them well, and then take the time to upload them for everyone's benefit. Also, please make sure you are only uploading freely available software. Commercial software and shareware should not be uploaded unless they have a copyright expressly stating that this is allowed. This includes Netscape software, ssh, pgp, etc.


Previous Next Contents