initCommon(); $template->displayHeader(); ?>

8.2. Building RPMs

In previous chapters, just about everything you want to do with RPMs is accomplished with the rpm command. Building RPMs is one exception. Just about everything you want to do to build an RPM is done by the rpmbuild command, often with a single command.

Warning

Older RPM manuals refer to using the –b option to the rpm command to create RPMs. Don’t use that option. Instead, always use the rpmbuild command. The reason for this change is that starting with version 4.1, RPM no longer maps the rpm -b command to the real command, rpmbuild.

When building RPMs, go through the following steps:

1.Set up the directory structure.

2.Place the sources in the right directory.

3.Create a spec file that tells the rpmbuild command what to do.

4.Build the source and binary RPMs.

The following sections provide details for these steps.

8.2.1. Setting up the directory structure

The RPM system expects five directories, as listed in Table 9-1.

Table 9-1 RPM directories

Directory

Usage

BUILD

The rpmbuild command builds software in this directory.

RPMS

The rpmbuild command stores binary RPMs it creates in this directory.

SOURCES

You should put the sources for the application in this directory.

SPECS

You should place the spec file for each RPM you plan to make in this directory.

SRPMS

The rpmbuild command places source RPMs in this directory.

The RPMS directory usually has a number of architecture-specific subdirectories, such as the following (on an Intel architecture system):

$ ls RPMS

athlon

i386

i486

i586

i686

noarch

By default, Red Hat Linux systems expect RPMs to be built in the /usr/src/redhat directory.

Note

This directory is obviously specific to Red Hat Linux. On other Linux distributions, you'll likely see other directories.

Within the /usr/src/redhat directory, you’ll see the subdirectories listed in Table 9-1, as follows:

$ ls /usr/src/redhat

BUILD

RPMS

SOURCES

SPECS

SRPMS

At first, it seems rather odd to be using a system directory to build RPMs. But remember that the RPM system was originally built to create Linux distributions. You can also change the default directories by modifying your rpmrc settings.

Cross Reference

See Chapter 21 for more on the use of the rpmrc settings.

For now, it is easiest to just change to the /usr/src/redhat directory and work from this location. To start, you will need to change ownership or permissions on these files so you can build RPMs while logged in as a normal user.

Warning

Do not build RPMs while logged in as root. Mistakes in building packages can have serious consequences if you are logged in as root.

To build RPMs, you really need only two things:

*Your sources in the SOURCES directory

*Your spec file in the SPECS directory

8.2.2. Placing your sources into the directory structure

You can place all the source files directly in the /usr/src/redhat/SOURCES directory. In most cases, however, it is easier to create a tarball of the sources you want to build and place the tarball file in the /usr/src/redhat/SOURCES directory. The RPM specifications for commands necessary to extract the sources from such a file are trivial. Furthermore, the tarball, when extracted, should create a subdirectory specific to your package. This keeps your source code separate from other packages that also have source code in the SOURCES directory.

The best strategy is to start in a directory of your own making, create the tarball file from the sources, and then copy the tarball file to the /usr/src/redhat/SOURCES directory.

The convention for these tarball files is package-version.tar.gz. For example:

jikes-1.17.tar.gz

Place a file like this into the /usr/src/redhat/SOURCES directory. This file should include all the sources, all the build scripts, and any documentation you want to install as part of the package.

8.2.3. Creating the spec file

The spec file, short for specification file, defines all the actions the rpmbuild command should take to build your application, as well as all the actions necessary for the rpm command to install and remove the application. Each source RPM should have the necessary spec file for building a binary RPM.

The spec file is a text file. The normal naming convention is to name the file with the package name and a .spec filename extension. For example, the jikes package spec file would be named jikes.spec.

Inside the spec file, format the information on the package using a special syntax. This syntax defines how to build the package, version numbers, dependency information, and everything else you can query about a package. This syntax differs slightly depending on the sections in the spec file. The following sections describe these spec file sections and the necessary syntax in each section.

8.2.3.1. The introduction section

The introduction section contains information about the package, the type of information shown with the rpm -qi command. For example:

Summary: java source to bytecode compiler

%define version 1.17

Copyright: IBM Public License, http://ibm.com/developerworks/oss/license10.html

Group: Development/Languages

Name: jikes

Prefix: /usr

Provides: jikes

Release: 1

Source: jikes-%{version}.tar.gz

URL: http://ibm.com/developerworks/opensource/jikes

Version: %{version}

Buildroot: /tmp/jikesrpm

%description

The IBM Jikes compiler translates Java source files to bytecode. It

also supports incremental compilation and automatic makefile generation,

and is maintained by the Jikes Project:

http://ibm.com/developerworks/opensource/jikes/

In this example, you can see the Source: definition of a compressed tar archive associated with a particular version number. This also names a Buildroot: setting that defines where the files will get built into a working program. You can see the description of the package that will get printed with the rpm –qi command.

Note

You can further divide this first section into the preamble and other areas. For simplicity, I grouped all introductary parts of a spec file into one introduction section.

This example comes from a real-world RPM spec file. It does not follow all the rules for creating RPMs. This example:

*Should not explicitly provide jikes, the name of the package.

*Should not include a Copyright tag, as this tag is deprecated.

*Uses a %define for the version when the rpmbuild command can create a version macro for you.

8.2.3.2. The prep section

The prep section, short for prepare, defines the commands necessary to prepare for the build. If you are starting with a compressed tar archive (a tarball) of the sources, the prep section needs to extract the sources.

For example:

%prep

%setup -q

The prep section starts with a %prep statement.

This example uses the %setup RPM macro, which knows about tar archives, to extract the files. In most cases, this will be all you need in your spec file prep section.

8.2.3.3. The build section

The spec file build section contains the commands to build the software. Usually, this will include just a few commands, since most of the real instructions appear in the Makefile. For example:

%build

./configure CXXFLAGS=-O3 --prefix=$RPM_BUILD_ROOT/usr

make

The build section starts with a %build statement.

The commands shown for this build section run the configure script, covered in the previous section on Linux build tools, and then run the make command with the default maketarget. If things unfold as they should, this procedure builds the software.

8.2.3.4. The install section

The spec file install section holds the commands necessary to install the newly built application or library. In most cases, your install section should clean out the Buildroot directory and run the make install command. For example:

%install

rm -fr $RPM_BUILD_ROOT

make install

The install section starts with an %install statement.

8.2.3.5. The clean section

The clean section cleans up the files that the commands in the other sections create:

%clean

rm -rf $RPM_BUILD_ROOT

The clean section starts with a %clean statement

8.2.3.6. The files section

Finally, the files section lists the files to go into the binary RPM, along with the defined file attributes. For example:

%files

%defattr(-,root,root)

/usr/bin/jikes

%doc /usr/doc/jikes-%{version}/license.htm

%doc /usr/man/man1/jikes.1*

The files section starts with a %files statement

The %doc macro marks certain files as documentation. This allows the RPM to distinguish the files holding documentation from the other files in the RPM.

Cross Reference

This example skips the install and uninstall script sections, as well as a verification section. There are also no triggers defined in this RPM spec file. All of these topics are covered in Chapters 10 and 11.

Once you have written your spec file, and placed the files in the SOURCES and SPECS directories under /usr/src/redhat, you’ll see files like the following:

$ ls –CF /usr/src/redhat/*

/usr/src/redhat/BUILD:

/usr/src/redhat/RPMS:

athlon/ i386/ i486/ i586/ i686/ noarch/

/usr/src/redhat/SOURCES:

jikes-1.17.tar.gz

/usr/src/redhat/SPECS:

jikes.spec

/usr/src/redhat/SRPMS:

That is, with a clean system and no other RPMs being built, you'll see a spec file in /usr/src/redhat/SPECS and the sources in /usr/src/redhat/SOURCES. In this example, the sources are in a compressed tar archive. (For this, the RPM spec file, jikes.spec needs to have a command in the prep section to extract the files.)

You should now be ready to build an RPM.

8.2.4. Building RPMs with the rpmbuild command

To build RPMs with the rpmbuild command, use the following basic syntax:

rpmbuild -bBuildStage spec_file

The -b option tells rpmbuild to build an RPM. The extra BuildStage option is a special code that tells the rpmbuild command how far to go when building. Table 9-2 lists these options:

Table 9-2 Options for building with rpmbuild

Option

Usage

-ba

Build all, both a binary and source RPM

-bb

Build a binary RPM

-bc

Build (compile) the program but do not make the full RPM, stopping just after the %build section

-bp

Prepare for building a binary RPM, and stop just after the %prep section

-bi

Create a binary RPM and stop just after the %install section

-bl

Check the listing of files for the RPM and generate errors if the buildroot is missing any of the files to be installed

-bs

Build a source RPM only

Note

See chapter 12 for advanced options you can use with rpmbuild.

For example, to set up all the necessary files and prepare for building, run the following command:

rpmbuild –bp specfile

This example runs through the %prep section, and stops immediately after this section. With the jikes package, for example, you’ll see a result like the following:

$ rpmbuild -bp /usr/src/redhat/SPECS/jikes.spec

Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.72435

+ umask 022

+ cd /usr/src/redhat/BUILD

+ LANG=C

+ export LANG

+ cd /usr/src/redhat/BUILD

+ rm -rf jikes-1.17

+ /usr/bin/gzip -dc /usr/src/redhat/SOURCES/jikes-1.17.tar.gz

+ tar -xf -

+ STATUS=0

+ '[' 0 -ne 0 ']'

+ cd jikes-1.17

++ /usr/bin/id -u

+ '[' 500 = 0 ']'

++ /usr/bin/id -u

+ '[' 500 = 0 ']'

+ /bin/chmod -Rf a+rX,g-w,o-w .

+ exit 0

After running this command, the source files are extracted into the /usr/src/redhat/BUILD directory, under the jikes-1.17 subdirectory. Using a subdirectory keeps the sources for this package from intermixing with the sources for other packages.

Running a directory listing on the /usr/src/redhat/BUILD/jikes-1.17 subdirectory shows what the spec file %prep section commands have done. For example:

$ ls -1 /usr/src/redhat/BUILD/jikes-1.17

acinclude.m4

aclocal.m4

AUTHORS

ChangeLog

config.guess

config.sub

configure

configure.in

COPYING

depcomp

doc

INSTALL

install-sh

jikes.spec

Makefile.am

Makefile.in

missing

mkinstalldirs

NEWS

README

src

TODO

Note

From these sources, you see a configure script. The configure script gives a good indication of how the software needs to be built. This example also shows a README file. You know what to do with these files.

The actual source code is in the /usr/src/redhat/BUILD/jikes-1.17/src directory. The user documentation is stored in the /usr/src/redhat/BUILD/jikes-1.17/doc directory.

To build a binary RPM, use the –bb option to the rpmbuild command. For example:

$ rpmbuild -bb /usr/src/redhat/SPECS/jikes.spec

Warning

Don’t build packages when you are logged in as the root user. Log in as a normal user instead. This is to limit the damage caused to your system if the spec file or the Makefile contains errors that delete system files, for example. If you are logged in as the root user, you will have permission to perform these destructive acts. If you are logged in as a normal user, though, these RPM spec file and Makefile errors will fail to run, because you don’t have permission to modify system files.

This command results in a lot of output, most coming from the configure script. (This script examines the C programming environment on your system.) When the rpmbuild command completes, you’ll see the binary RPM in the proper subdirectory of the RPMS directory. You can see the RPM with a directory listing, for example:

$ls /usr/src/redhat/RPMS/i386:

jikes-1.17-1.i386.rpm

To stop execution just after the %install section, use a command like the following:

rpmbuild –bi specfile

For example:

# rpmbuild -bi /usr/src/redhat/SPECS/jikes.spec

To build a source RPM out of the files you have (in this case a tar archive of the sources and the spec file), use a command like the following:

rpmbuild –bs specfile

For example:

$ rpmbuild -bs /usr/src/redhat/SPECS/jikes.spec

When done, you’ll see the source RPM in the /usr/src/redhat/SRPMS directory:

$ ls /usr/src/redhat/SRPMS

jikes-1.17-1.src.rpm

To clean out the files created by building these RPMs, use the --clean option to the rpmbuild command:

rpmbuild --clean specfile

For example:

$ rpmbuild --clean /usr/src/redhat/SPECS/jikes.spec

Executing(--clean): /bin/sh -e /var/tmp/rpm-tmp.21908

+ umask 022

+ cd /usr/src/redhat/BUILD

+ rm -rf jikes-1.17

+ exit 0

Cross Reference

Chapter 12 covers a number of addition options for the rpmbuild command that you can use to customize the build.

displayFooter('$Date: 2005/11/02 19:30:06 $'); ?>