Traditionally, software for Unix systems has primarily been distributed as source code. To use this software,
an administrator must compile it properly for the system on which it will be used, then install it. If it requires any supporting packages, they must also be installed.
If any local customizations are required, they must be applied to the software.
When the software needs to be upgraded, an administrator must find all the original files for that software on the system and replace them with updated versions, taking care to preserve any configuration changes which have been made locally.
Now, consider a typical Unix workstation application, such as Mozilla. The basic Mozilla application consists of approximately 495 files scattered through approximately 10 different directories. When removing it, an administrator must find all those files and delete them.
When upgrading it, an administrator must manually replace all those files. To operate, Mozilla requires that approximately 50 other system executables and libraries (many of which, in turn, require still other libraries) be installed.
Debian introduced the DPKG packaging system, while Red Hat introduced the RPM packaging system.
Since that time, the RPM packaging system has become a de facto standard in the Linux community.
RPM Features
Non-interactive, Scriptable Installation
Tracking of Installed Files
Verification of Installed Files
Queries of Installed Files
Dependency Tracking
Tracking of All Source and Build Process
• Pristine Source preservation
Digitally Signed Software
RPM provides a set of tools which can be used to carry out noninteractive, scriptable installations of software.
Once that software is installed, RPM provides tools which can track those installed files, making it easily possible to uninstall them later, or to upgrade them.
RPM has excellent dependency tracking capabilities, meaning that when used to install new software, it can first ensure that any software required for that new software to work is already installed; when used to uninstall software, it can first verify that doing so will not break any other applications.
In addition, RPM provides a tool set which manages the entire process of patching, configuring, and compiling new applications.
When compiling an application, RPM makes it possible to start with the pristine source code for that application,
produce any needed patches for that application, then script the process of applying those patches, configuring the source code, and compiling the source code to produce executables. This aspect of RPM greatly simplifies the process of maintaining custom-configured applications in the enterprise.
Furthermore, RPM allows all packaged software to be signed digitally (using public-key technology). This feature allows the authenticity of software packaged for use with RPM to be verified, helping prevent the accidental installation of Trojan Horse software.
RPM Architecture
RPM package files
RPM database
• /var/lib/rpm
RPM utilities
• rpm
• rpmbuild
• rpmsign
• rpm2cpio
RPM configuration files
• macros used during preparation and installation of RPMs
The RPM system consists of several components. Software which is to be installed using RPM must be supplied in a special format, the RPM package file.
This RPM package file is an archive which contains the actual files to be installed, as well as metadata about those files which is used by the RPM system to ensure that those files are installed with the correct permissions and ownerships and in the correct locations.
As software is installed using RPM, the name and several other properties of each file being installed on the system are recorded in the RPM database, typically located in the /var/lib/rpm directory.
This database contains a list of all installed applications, and the files which belong to those applications, allowing easy upgrade or
uninstallation of applications at a later time. It also tracks properties of each file—such as its correct size, timestamp, and cryptographic checksum—ensuring that the file’s correctness can be verified at a later date. This database also contains dependency information for every application, ensuring that administrators installing new applications can be certain that the applications the new software requires to operate are present, and that administrators removing applications can be certain that doing so will not break any other existing applications.
Several utilities are supplied for use with RPM. The basic utility used for most RPM administrative tasks is the /bin/rpm command.
On dated systems, which use an older version of RPM, this command is the only command commonly used when working with RPM. On modern systems, which use newer versions of RPM, many of the functions formerly performed by the /bin/rpm command have been moved to helper utilities.
For example, the /usr/bin/rpmbuild command is used to produce new RPM package files, while the /usr/bin/rpmsign command is used to sign new packages.
The /usr/bin/rpm2cpio command has always been available for conversion of RPM package files into a standard archive file format.
RPM also has several configuration files. In RHEL/FC, these are found in the /etc/rpm and /usr/lib/rpm directories,
while on SUSE distributions, they are found in the /usr/lib/rpm directory only.
These configuration files primarily define macros—short-cut commands which are used when running RPM commands, or when preparing RPM package files.
RPM Packages Files
Naming Conventions
• name-version-release.architecture.rpm
Architectures
• source -- .src.rpm
• noarch -- .noarch.rpm
• binary -- .i386.rpm
Format
• cpio archive plus a binary header
Considering RPM Files:
Software prepared for use with RPM must be packaged in an RPM package file. These package files should be named in the format:
name-version-release.architecture.rpm
In this package file name, the name indicates the software which is packaged in that RPM. Usually, this name is the name of the application.
In the RPM package file name, the version indicates the version of the software which is packaged in that RPM.
This version is usually the version of the application which is being packaged in that RPM package file. Although it is not required by the RPM package file format or RPM utilities, this version field should always be a number; use of words in this field can (and has) caused problems for several front-end applications which use RPM. The release in the RPM package file name is used to indicate revisions of the packaging of that particular version of that application. Sometimes, mistakes are made when preparing RPM package files of a specific version of a specific application. When that occurs, a new package file of that specific version of that specific application can be prepared which fixes those mistakes. The release field allows these revisions of package files to be tracked. This field should be a number, and should be increased every time the package is revised.
The architecture is the platform on which that RPM can be executed, if binary. Typical values seen here include:
• i386 – the package can be used on
any 32-bit Intel-compatible CPU
• i686 – the package can be used on
any 686-class 32-bit Intel-compatible CPU
• ppc64 – the package can be used on the 64-bit
PowerPC CPU
• x86_64 – the package can be used on AMD or
Intel 64-bit CPUs
• ia64 – the package can be used on the 64-bit Itanium CPU
• sparc64 – the package can be used on a 64-bit
UltraSparc CPU
In addition to binary executables, RPM package files can also be used to package platform-neutral executable code
(such as programs written in an interpreted language like Lisp or Perl or Java). RPM package files which contain code which can run on any CPU, or other files - such as documentation- which are platform-neutral are packaged with in RPM package files for which the architecture is noarch.
RPM package files can also be used to package application source code, patches, and scripts specifying how that source code should be configured and compiled.
These package files will have an architecture of src, indicating that they contain source code rather than executables. Regardless of their name, all RPM package files are a cpio archive with a binary header attached.
Working With RPM's
Installing without upgrading RPMs
• rpm -i
Upgrading/Installing & Freshing RPMs
• rpm -U
• rpm -F
Removing RPMs
• rpm -e
Querying RPMs and Files
• rpmquery / rpm -q
Verifying RPMs and Files
• rpmverify / rpm -V
RPM package files are normally installed using the -U option to the rpm command. Typically, this is used in conjunction with the -v option, which causes rpm to be more verbose, and the -h option, which causes rpm to display progress meters:
# rpm -Uvh ytalk-3.1.1-12.i386.rpm
Preparing... ############################### [100%]
1:ytalk ############################### [100%]
#
If you wish to install a package AND keep the older version installed as well (this is only possible if there is no files that overlap), then use the -i option. This only typically done with installing a kernel package and you want to keep the older kernel installed in case the new kernel malfunctions.
Packages can also be upgraded using the -F option to the rpm command (which is typically also used with the -v and -h options). This option causes the package to be upgraded if already installed and of an older version, but not to be installed if it is not currently installed.
When performing upgrades or freshening installed packages, the rpm utility compares the version of the RPM being installed with the version, in the RPM database on the system, of the already installed RPM. If the version number of the package being installed is greater than the installed version number, RPM will upgrade. If the version number of the package being installed is less than the installed version number, RPM will refuse to downgrade. If the versions numbers of the two are the same, then RPM compares the release numbers, and upgrades only if the release number of the new package is greater than the release number of the installed package.
Once installed, applications can be removed using the -e option to the rpm command:
# rpm -e ytalk
#
When erasing installed software, only the name of the software (ytalk) is used. When installing new packages or upgrading existing packages,the complete package file name (ytalk-3.1.1-12.i386.rpm) is used. Package files and installed packages can also be queried.
The rpmquery command or the rpm command with the -q option can perform many powerful queries. Similarly, installed files can be verified using the rpmverify command or the rpm command with the -V option.
Source RPM Files
Contents
• Pristine source code
• Any needed patches and support files
• Script specifying how to build binary packages from
the source code
.spec file
Sometimes similar contents in tarball format instead
Understanding Source RPM Files
The rpm command can also be used to work with source RPM files (SRPMs). SRPMs are package files which can be used to build binary RPMs, such as the .i386.rpm and .noarch.rpm RPM package files that are typically the end product and installed on systems.
SRPMs contain several different files
• Original source code for the application
• Any patches required to modify that source code
• Any needed auxiliary files for that application,
such as System V init scripts
• A script specifying how to configure and compile the
source code; this script is typically named application.spec
One design principal behind RPM is that packages should always be compiled from the original source code for that application.
This criterion is important in the Linux community, where individual applications are developed by a large loosely organized collection of organizations all over the Internet, and then collated into a cohesive operating system by distribution vendors such as Red Hat or SUSE.
Distribution vendors often need to modify the original source code to make it integrate better into their distribution. Similarly, end users often need to recompile, and occasionally need to patch, applications shipped by their distribution vendor to better suit their local environment.
Preparing RPMs from original source code, plus separate patches, helps ensure long-term ease of maintenance.
It also allows end-users to determine easily exactly how a package has been modified. Typically, application developers who support creation of binary RPMs from their source code do so by releasing SRPMs. Some application developers, however, instead release their source code in a standard Unix tarball format, and simply include within the tarball a spec file specifying how to produce a binary RPM from that source code.
Using Source RPM's
Why?
• Typically, need software not included with distribution
• Sometimes need newer version of existing software,
or existing software compiled with different features
• Want maintenance benefits of packaging for this needed software
Two approaches
• Rebuild existing src.rpm
Not modifying it in the process
Customizing the existing package
• Creating new src.rpm
Although administrators can often obtain binary RPMs of the software which they need to install, sometimes administrators will instead need to compile software.
There are several reasons why an administrator might need to compile software from source including:
• A need for software not included in the Linux distribution
• A need for a newer version of an application included
in the Linux distribution
• A need for an application compiled with different options
or features than the build included in the Linux distribution
• A need to fix a bug in an application included in the
Linux distribution
When compiling software from source, an administrator might still want the benefits of using a package management system like RPM,
such as the ability to uninstall the software easily at a later date, or the ability to upgrade the software easily when necessary. Similarly, an administrator might want the benefits gained by building software using the RPM software, such as the inherent tracking of all build commands and the coordination of patches with software.
For reasons such as these, an administrator might choose to compile software from a SRPM to produce binary RPMs. To produce a binary RPM, the administrator will first need to have a source RPM which can be used to produce the binary RPM.
The administrator will typically obtain a SRPM by either of two methods:
• Creating a new SRPM from scratch
• Using an existing SRPM
When working from an existing SRPM, the administrator might use it as-is, or might choose to customize it. All of these actions are possible using RPM.
Preparing to Build RPMs
Install Necessary Software Prerequisites
• gcc, make, and other development tools
• All needed dependencies
• Should be same environment as expected on target host
Do not build RPMs as root, to prevent changing current system, Prepare Non-root Build Environment On Red Hat
• Create needed directory structure
• Create ~/.rpmmacros
When building binary RPMs from SRPMs, some preparatory steps on the system which will be used to build the RPMs are first required.
The software needed to compile the binary RPM needs to be installed on the build host.Typically, this requirement means that common development tools such as the gcc C compiler and the make command need to be installed. Depending upon how the Linux distribution was installed, these tools may or may not be installed already.
In addition to development tools, most software has build dependencies which must be present when the software is being compiled. Many applications require support libraries and header files which must be present when they are compiled, and these also need to be installed if not already present.
The binary, once compiled, will be compiled to execute on a system with the same system libraries and features as the system on which it was compiled. For this reason, it is best to compile software on the same operating system release as the system on which it will be installed.
When compiling binary RPMs from SRPMs, it is important to do so as a non-root user whenever possible.
As part of the RPM build process, the RPM software performs an install of the compiled software into a virtual filesystem environment. Errors in the spec file controlling the RPM build process can cause RPM to install to the real filesystem instead.
Building RPMs as a non-root user, though not possible for all RPMs, prevents the build process from accidentally writing to the real filesystem since non-root users do not typically have write access to the directories in which the RPM build process would attempt to install software.
On Red Hat distributions, the system will need to be configured to support non-root RPM builds.
To enable RPM building on Red Hat distributions as a normal user:
1. Log in as the non-privileged user who will be performing builds.
2. Create the directory structure needed by the RPM build process:
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,S{OURCE,PEC,RPM}S}
or
$ cp -a /usr/src/redhat ~/rpmbuild
3. Configure RPM to use this new directory structure, rather than the default directory structure, when building RPMs:
$ echo "%_topdir $HOME/rpmbuild" > ~/.rpmmacros
Once these commands are completed, RPMs can be built under the rpmbuild directory in the user’s home directory. To build RPMs elsewhere, simply adjust the paths as appropriate.
Rebuilding Existing Packages
Source RPMs
• rpmbuild --rebuild
• rpmbuild --recompile
Tarballs containing .spec files
• rpmbuild -ta
Once a proper build environment has been prepared, any existing packages which need recompilation can be rebuilt. On modern systems, the commands:
$ rpmbuild --rebuild name-ver-rel.src.rpm
can be used to compile the SRPM to produce a binary RPM, while
$ rpmbuild --recompile name-ver-rel.src.rpm
can be used to compile an unpackaged binary from the SRPM.
Or on older systems, the commands:
$ rpm --rebuild name-ver-rel.src.rpm
can be used to compile the SRPM to produce a binary RPM, while
$ rpm --recompile name-ver-rel.src.rpm
can be used to compile an unpackaged binary from the SRPM.
Some developers release source code as tarballs which contain a spec file. RPM can also be used to compile this software. On modern systems, the command:
$ rpmbuild -ta tarball
can be used to compile the tarball to produce a SRPM and a binary RPM.
On older systems, the command
$ rpm -ta tarball
can be used to compile the tarball to produce a SRPM and a binary RPM.
Installing source RPMs
By installing a source RPM, using the command:
$ rpm -Uvh name-ver-rel.src.rpm
The pristine source tarball, patches and supporting files will be placed in your defined SOURCES directory. The spec file will be placed in your SPECS directory. This only needed if you want to change something before you make the binary RPM.
Creating New RPMs
Prepare any needed patches
• Changes to released source code
Prepare any needed support files
• Startup scripts and similar files
Create the .spec file
• “recipe” for compilation of software
Build and Test the RPM
Many times, an existing SRPM is available for the software which needs to be compiled. If one is not available, however, one can be created from scratch by following a few simple steps:
• Preparing any needed patches
• Preparing any needed support files
• Creating the .spec file
• Building and testing the RPM
Sometimes, released software needs a patch to alter the way the code behaves. If the application being compiled needs any patches, they will need to be prepared.
Instructions which tell the RPM software how to compile the software must also be prepared. These instructions are stored in a spec file which the RPM software will use when compiling the RPM.
After these basic components have been created, the RPM can be built and tested. Typically, doing so is an iterative process—during the build process, mistakes in patch files or spec files will be caught and corrected, then the build will be repeated. Eventually, a working build will be obtained.
Patching Software
SRPM Contains Pristine Source and Patches
• Eases long-term maintenance
• Allows authenticity verification
Why Patch?
• Change hard-coded default values
• Back port changes from development tree
• Make changes to better integrate package with the system
• Fix software bugs
Generating Patches
• Create .org file then modify existing file
• Use /usr/bin/diff to create patch file
When preparing software for a package, the software often needs modifications to the source code. These modifications might be needed for any of several different reasons, including:
• A need to change hard-coded values, such as directory
paths or usage limits, within the software
• A need to fix bugs in already released software
• A need to make the software better integrate with other
software on the system
Any changes to the original source code of an application which are made by a packager need to be made in the form of a patch file,
and not by directly modifying the original source of the application. SRPMs always contain the original source code for an application, as well as any patch files which are needed to make changes to that source code.
It also simplifies verification of the authenticity of the source code, an important consideration in today’s Trojan Horse-flooded Internet.
Patch files are easily created. To create a patch file, first make a copy of the file to be modified under its original with a .orig extension. Then, make any modifications to the file which are needed. Next, use the diff command with the -N, -a, -u, and -r options to generate the differences between the original file and the modified file. Finally, save these differences as a patch file.
For example, suppose an application, less, required a couple of customizations to the files edit.c and filename.c in its source code.
To prepare patch files of these changes:
1. Obtain and unpack the original source code.
$ tar -zxvf less-378.tar.gz
2. Back up the files to be modified.
$ cd less-378/
$ cp edit.c edit.c.orig
$ cp filename.c filename.c.orig
3. Modify the source files
$ vi edit.c
$ vi filename.c
4. Save the differences in the edited files to patch files
$ diff -Naur edit.c.orig edit.c > edit.patch
$ diff -Naur filename.c.orig filename.c > filename.patch
At this point, two patch files for the less source code exist which can be used when preparing a SRPM to build the patched less program.
Creating Support Files
Does package need a scheduled job?
• Create file for /etc/cron.*
Does package need log file rotation?
• Create file for /etc/logrotate.d/
Does package need shell or environment changes?
• Create files for /etc/profile.d/
Consider special cases
• Startup scripts for daemons
• Desktop file(s) for menus
• Web configuration files
• Authenticating daemons -- /etc/pam.d/
Creating Menu Entries
freedesktop.org
• Multiple formal and informal specifications for
interoperability
• Desktop Menu Specification
Standardized menu specification
applicationname.desktop files
• Stored in the /usr/share/applications/ directory
desktop-file-utils software
• desktop-file-install
• desktop-file-validate
When packaging application software in RPM format as opposed to system software, it is recommended that a menu entry is created for the software so that users can easily find and launch the application.
the GNOME and KDE desktops used their own separate menus and menu files with different format. This was recognized as a problem and the two groups came together and created the Desktop Entry Standard.
The Desktop Entry Standard defines that the directory /usr/share/applications/ stores XML files for each menu entry in the format applicationname.desktop.
Once a desktop file is created, it is installed using the desktop-file-install command. The files can be validated to ensure that the syntax is correct using the desktop-file-validate command.
For small desktop files that don’t use translated descriptions, they are often defined and created directly within the package spec file.
Full details on the structure and rules for the desktop files can be found at the URL:
http://standards.freedesktop.org/menu-spec/latest/
Example spec file desktop generation and installation
%install
[snip lines unrelated to desktop]
# Desktop menu entry
cat > %{name}.desktop << EOF
[Desktop Entry]
Name=BZFlag
Comment=%{summary}
Exec=%{name}
Icon=bzflag-m.xpm
Terminal=0
Type=ApplicationEOF
mkdir -p %{buildroot}%{_datadir}/applications
desktop-file-install --vendor TimRiker --dir %{buildroot}%{_datadir}/applications --add-category X-Red-Hat-Extra --add-category Application --add-category Game %{name}.desktop
The .spec file
--> Defines meta-info about the package
--> Describes how to compile package
--> Describes what files to install
• Defines permissions with which to install files
--> Contains scripts to execute before and after installation and
uninstallation
Examining .spec Files
After creating any required patch files and support files which are needed for the application, a spec file must be created.
This spec file is written in a syntax which interleaves a macro programming language with shell commands and with descriptive text.
In the spec file, the number sign (#) is used to denote comments, just as in most other Unix configuration files.
The spec file consists of several closely related sections:
• The Header stanza
• The Prep stanza
• The Build stanza
• The Install stanza
• The Files stanza
• The Scripts stanza
• The Changelog stanza
Together, these sections define the source files and patches which make up the application, provide detailed information about the source and use of the application, instruct RPM on how to compile the application, define the files which RPM needs to install when installing the application, as well as how to install those files. The spec file can also contain optional scripts which are executed before and after installation or uninstallation of the application.
The foo.spec file
Summary: The world famous foo
Name: foo
Version: 1.03
Release: 1
License: GPL
Group: Applications/System
Source0: foo-%{version}.tar.bz2
Source1: foo.sysvinit
Patch0: foo-fix1.patch
Patch1: foo-fix2.patch
BuildRoot: /var/tmp/%{name}-root
%description
This foo daemon serves bar clients.
%prep
%setup -q
%build
%configure
make
%install
rm -rf %{buildroot}
%makeinstall
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root)
/etc/init.d/foo
%{_sbindir}/foo
/usr/share/man/man8/foo.8
%files devel
%defattr(-,root,root)
/usr/include/foo.h
/usr/lib/foo.a
%changelog
* Mon sept 3 2013 ctechz
- ver 1.03
Using Macros
Widely used in .spec files
• Simplify creation of .spec files
System-wide macros
• /usr/lib/rpm/macros
• Vendor-specific files
/usr/lib/rpm/suse_macros
/etc/rpm/macros*
User-defined macros
• ~/.rpmmacros
Macros are widely used throughout RPM to perform configuration.
These configuration macros can be set globally, in the /usr/lib/rpm/macros configuration file. They can also be set on a per-user basis; whenever an RPM command is executed, the RPM software looks for the configuration file .rpmmacros in the user’s home directory,
and any configuration directives defined in this file override global configuration options.
Macros are commonly used in spec files as well. Pre-defined macros exist for several commonly used fields within the spec file, and macros also exist for many commonly used directories and paths on the system.
In configuration files and spec files, values are assigned to macro names by listing the macro name followed by its value. The statement
%_topdir /export/home/rpmmaker/rpmbuild
in ~/.rpmmacros, for example, assigns the value
/export/home/rpmmaker/rpmbuild
to the macro
%_topdir
Within configuration files and spec files, the value of a macro is accessed by using the macro name encased in braces.
For example, any time the statement
%{_topdir}
appears within a spec file for this rpmmaker user, it will automatically be replaced by the value
/export/home/rpmmaker/rpmbuild
Because macros are so useful when writing spec files, many distribution vendors supply a variety of pre-defined macros which can be used when writing spec files. On Red Hat distributions, these vendor-specific macros are put in the /etc/rpm subdirectory,
When preparing packages for building on multiple distributions, care should be taken to avoid using vendor-specific macros.
Commonly Used Macros
Directory Macros
%_prefix /usr
%_exec_prefix %{_prefix}
%_bindir %{_exec_prefix}/bin
%_sbindir %{_exec_prefix}/sbin
%_libexecdir %{_exec_prefix}/libexec
%_datadir %{_prefix}/share
%_sysconfdir %{_prefix}/etc
%_sharedstatedir %{_prefix}/com
%_localstatedir %{_prefix}/var
%_lib lib
%_libdir %{_exec_prefix}/%{_lib}
%_includedir %{_prefix}/include
%_oldincludedir /usr/include
%_infodir %{_prefix}/info
%_mandir %{_prefix}/man
The %configure macro
%configure \
CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS; \
CXXFLAGS="${CXXFLAGS:-%optflags}"; export CXXFLAGS; \
FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ; \
./configure --host=%{_host} --build=%{_build} \\\
--target=%{_target_platform} \\\
--program-prefix=%{?_program_prefix} \\\
--prefix=%{_prefix} \\\
--exec-prefix=%{_exec_prefix} \\\
--bindir=%{_bindir} \\\
--sbindir=%{_sbindir} \\\
--sysconfdir=%{_sysconfdir} \\\
--datadir=%{_datadir} \\\
--includedir=%{_includedir} \\\
--libdir=%{_libdir} \\\
--libexecdir=%{_libexecdir} \\\
--localstatedir=%{_localstatedir} \\\
--sharedstatedir=%{_sharedstatedir} \\\
--mandir=%{_mandir} \\\
--infodir=%{_infodir}
The %makeinstall macro
%makeinstall \
make \\\
prefix=%{buildroot}%{_prefix} \\\
exec_prefix=%{buildroot}%{_exec_prefix} \\\
bindir=%{buildroot}%{_bindir} \\\
sbindir=%{buildroot}%{_sbindir} \\\
sysconfdir=%{buildroot}%{_sysconfdir} \\\
datadir=%{buildroot}%{_datadir} \\\
includedir=%{buildroot}%{_includedir} \\\
libdir=%{buildroot}%{_libdir} \\\
libexecdir=%{buildroot}%{_libexecdir} \\\
localstatedir=%{buildroot}%{_localstatedir} \\\
sharedstatedir=%{buildroot}%{_sharedstatedir} \\\
mandir=%{buildroot}%{_mandir} \\\
infodir=%{buildroot}%{_infodir} \\\
install
Common Header Fields
Name - the application
Version - the application’s version
Release - the revision of that version’s packaging
License - the license used for the application
Group - the category to which that application belongs
Source - source files for the application
Patch - patch files to modify the source files
URL - the location of the original application source
Requires -any software required for the application to work
BuildRequires - any software required to compile the app
Creating the Header :- The Header stanza is usually the first section to appear in the spec file. It provides a lot of metadata about the application being packaged. Fields commonly found in the header include:
• Name • Version • Release • License • Group • Source • Patch • URL • Requires • BuildRequires
Valid values for the categories used in the Group header can be found in the /usr/share/doc/rpm-*/GROUPS file on Red Hat systems.
Often, more than one Source file or more than one Patch file is needed for an RPM. In that case, the Source and Patch headers are simply numbered:
Source:
Source1:
Patch0:
Patch1:
The Requires and BuildRequires headers are optional. RPM will automatically calculate dependencies for software as it builds the software; the Requires header just allows developers to list run-time dependencies if they so desire. Similarly, the BuildRequires field is used to specify any applications which have to be present for the software to compile correctly.
Although not always used, it is courteous to define any non-obvious build requirements to aid others trying to compile the software.
Both Requires and BuildRequires can list the name of the software they require, or they can list the name and the version if specific versions are required.
Two other fields are always seen in the Header. The Summary field is used to provide a short, one-line blurb describing the application being packaged, while the %description field provides a longer, potentially multi-paragraph description of the application being packaged.
If any custom macros are being created and defined for use within the spec file, these macros will typically be defined within the Header stanza of the spec file.
Advanced Header Fields
Arch options
• BuildArch
• ExclusiveArch
• ExcludeArch
Epoch
A variety of Architecture options exist which can be used to control the platforms on which the package will be built.
The BuildArch directive is used to force a package to be built for a particular architecture, rather than the default architecture of the machine on which it is being build. Commonly, this is used to indicate that the built package should be a
.noarch.rpm:
BuildArch: noarch
Not all software will compile on all architectures, just as not all applications are even usable on all architectures.
Two directives exist which can be used to enforce these requirements. The ExclusiveArch statement can be used to list platforms on which the package is supported, instructing the RPM software not to build it on other platforms. The ExcludeArch statement can be used to list platforms on which the package is not supported, instructing the RPM software to build it on all other platforms.
The statement
ExcludeArch: s390 s390x
specifies that the package should be built on all machines except 31-bit and 64-bit s/390 hardware, while the statement
ExclusiveArch: i386 s390 s390x x86_64
specifies that the package should be built only on 32-bit Intel-compatible hardware, 31-bit and 64-bit s/390 hardware, and 64-bit AMD (Opteron) hardware, but not on any other systems.
RPM also provides another field in the Header stanza, the Epoch. Normally, the RPM software uses the combination of package version and package release to determine if one package is newer than another. Some software uses non-standard versioning, or has changed versioning,
For example, the Postfix MTA historically used YearMonthDate as its version (such as the postfix-19990906.tar.gz release). More recently, Postfix’s author has adopted a more traditional two-digit versioning system (such as the postfix-2.0.9.tar.gz release).
When RPM compares 19990906 with 2.0.9, 19990906 appears to be the newer software (since the version is higher), even though it is actually 4 years older than the 2.0.9 Postfix release. To correct these sorts of problems, RPM supports an Epoch field. Normally, this field is assumed to be zero if not present, but can be set to a higher number if necessary. Whenever package versions are compared, RPM first compares the Epoch, then the Version, then the Release.
Because of this, a Postfix package with an Epoch of 1 and a Version of 2.0.9 will correctly appear newer than a Postfix package with an Epoch of 0 and a Version of 19990906.
The Prep Section
Used to prepare the software
• Untar the source code
• Apply any needed patches
• Perform any other required setup steps
Preparing the Software
After the Header stanza, the next stanza in the spec file is usually the Prep stanza. This section is always begun by the token,
%prep
and is used to prepare the software to be compiled. Typically, this section unpacks the archived source code files, and applies any needed patches to these files. This can be done using standard shell commands, but is more typically done using predefined macros.
One macro commonly seen here is
%setup
This macro unpacks the source code and then changes directory to the directory where the source code was unpacked. Options are available to %setup as well. For example, after untarring the package, the %setup macro assumes the directory that is created is named:
%{name}-%{version}
If the directory inside the tarball is named differently, you can use the -n option to specify the directory name to cd into. For example:
%setup -n %{name}-April2003Rel
Another commonly used option to %setup is the -q option which turns off the verbose output from the tar command.
Another macro typically used here is
%patch
This macro applies the patches defined in the Header stanza. If multiple patches are being used,it accepts a numeric argument to indicate which patch file should be applied. It also accepts a -b extension argument to instruct the RPM software to back up files with the specified extension before patching them.
The following macro
%patch2 -b .test
instructs the RPM software to apply Patch2, and to save a backup of any files being patched with a .test extension before patching them.
The -p option to the %patch macro controls the -p option passed to the /usr/bin/patch command. Typically, -p1 is used, however, it depends on how the patch file was created in the first place.
The Build Section
Used to compile the software
• Configure the software
• Compile the software
Defining the Build Process
After the Prep stanza, the spec file usually contains a Build stanza. The Build stanza always begins with the token:
%build
In this stanza, commands to configure the software and to compile the configured software are listed. As with the Prep section, these commands can be shell commands, or they can be macros.
If the software being compiled is designed for use with autoconf,the
%configure
macro should be used to configure the software. This macro automatically specifies the correct options to autoconf to
install software correctly, and to compile it optimized for best performance.
If the software is not designed for configuration using autoconf, use shell commands to configure the software appropriately.
Once the software is configured, it must be compiled. Since compilation methods vary so widely from application to application, no macro exists for compilation. Simply list the shell commands which would be used to compile the software.
A shell variable,
$RPM_OPT_FLAGS
is commonly used when compiling software. This shell variable contains the correct optimization flags for the gcc suite of compilers.
Using syntax such as
make CC=”gcc $RPM_OPT_FLAGS”
or
make CFLAGS=”$RPM_OPT_FLAGS”
will ensure that the appropriate optimization flags are always used. Other compiler flags and options can, of course, be specified as necessary.
The default value of $RPM_OPT_FLAGS is:
-O2 -g -march=i386 -mcpu=i686
The Install Section
Used to install the software
• Install the software into a virtual directory structure
• Clean up the temporary build directory
Relies on Buildroot set in Header stanza
Installing the Software:
After the Build stanza, the next section of the spec file is the Install stanza. This stanza always begins with the token:
%install
This stanza is used to install the compiled software into a virtual directory structure so that it can be packaged up into an RPM.
In the Header stanza, the Buildroot can be specified. This Buildroot defines the location of a virtual directory tree into which the software can be installed. Usually, this will be declared as:
Buildroot: %{_tmppath}/%{name}-root
or
Buildroot: %{_tmppath}/%{name}-%{version}-root
using RPM’s built-in macros to specify a private directory under the /var/tmp directory.
The shell variable
$RPM_BUILD_ROOT
can be used to access the value of Buildroot throughout the rest of the spec file.
mkdir -p $RPM_BUILD_ROOT/usr/share/icons/
cp %{SOURCE3} $RPM_BUILD_ROOT/usr/share/icons/
The Install stanza typically lists shell commands to install the compiled software within this Buildroot.
The macro %makeinstall can be used to install software which supports autoconf; this macro automatically installs
software into the correct subdirectories under the $RPM_BUILD_ROOT.
Sometimes, a package needs to be built more than once, due to packaging errors or similar problems. Each time the package is build, the Install stanza will copy files into the Buildroot. To prevent incorrect packaging due to old files within the Buildroot, the Buildroot should always have any existing files deleted before installing new files into it. For this purpose, a clean script can be created within the Install stanza. This script is always denoted by the token
%clean
and usually just consists of the command
rm -rf $RPM_BUILD_ROOT
If present, this %clean section is run after preparing packages from the software installed in the Install stanza, ensuring that the Buildroot is correctly empty for the next time the package is built.
The Files Section
Used to define the files which should be packaged
• Only packages files installed into the Buildroot
• Should specify ownerships and permissions for the
files being packaged
Controlling Installed Files :-
After the Install stanza, the next section of the spec file is the Files stanza, which lists the files and directories
which should be packaged into an RPM. This stanza always begins with the token:
%files
Within this section, simply list, on a one-file-per-line-basis, the files and directories, relative to the Buildroot, which the RPM software should archive into packages. Wildcards can be used within this section, such as the statement
/usr/bin/*
which instructs the RPM software to package all files within the directory $RPM_BUILD_ROOT/usr/bin.
When listing files and directories, care must be taken to list all files which are needed, and not to list any files which should not be packaged. Great caution should be used when listing a directory.
Listing a directory instructs the RPM software to
package that directory and all files within it, so the statement
/usr/bin
instructs the RPM software to package all files within the directory $RPM_BUILD_ROOT/usr/bin, but also incorrectly produces a package which appears to own the /usr/bin directory!
Within the Files stanza, several macros can be used. The %defattr macro should always be used to specify default ownerships and permissions which apply to files listed after it. For example, the statement %defattr(0770,root,root)would specify that all files and directories listed after it and prior to any subsequent %defattr macros would be installed owned by the root user and group, and with permissions 0770. Further, individual files can have different permissions and ownership than the %defattr macro specifies by using the %attr macro.
Within the Files stanza, several macros can be used. The %defattr macro should always be used to specify default ownerships and permissions which apply to files listed after it. For example, the statement %defattr(0770,root,root)would specify that all files and directories listed after it and prior to any subsequent %defattr macros would be installed owned by the root user and group, and with permissions 0770. Further, individual files can have different permissions and ownership than the %defattr macro specifies by using the %attr macro.
%files
%defattr(-,root,root)
%{_libdir}/libamanda*.so
%attr(660,amanda,disk) /var/lib/amanda/.amandahosts
Several macros exist to indicate that installed files have special properties. The macro
%dir
can be used to specify that a directory should be packaged, rather than the files within that directory. The macro
%config(noreplace)
can be used to indicate that the installed file is a configuration file, and shouldn’t be overwritten on a package upgrade.
Optional Script Section( s )
preinstall / postinstall / preuninstall / postuninstall scripts
• Allow execution of commands before and after
installation and deletion
• triggers can make script execution conditional Commonly
used to create necessary user accounts
Executing Commands During Installation or Deletion:-
Sometimes, commands need to be executed on the system before or after software gets installed. For example,
after new shared libraries are installed, the ldconfig command needs to be run so that the system will use the newly installed libraries.
The RPM spec file can contain scripts which get executed before or after package installation or uninstallation. These scripts are usually listed after the Files stanza, and are simply Bourne shell scripts which are listed after a macro indicating when they should execute.
Available scripts are:
%pre – executed before the package is installed
%post – executed after the package is installed
%preun – executed before the package is uninstalled
%postun – executed after the package is uninstalled
Most commonly, these scripts are used for packages which require a user account on the system to operate. The %pre script can be used to add the required account when installing the software, and the %postun script can be used to remove the no-longer-required account when uninstalling the software. When preparing a package for use on Red Hat systems which requires a user account, consult the file /usr/share/doc/setup-*/uidgid, which lists the UIDs and GIDs which are already used by software shipped with Red Hat Linux.
Sometimes, the actions which should be carried out in the %pre,%post, %preun, and %postun scripts are
contingent upon the software which is installed on the system. For example, the Mailman mailing-list management software needs several email aliases to operated, so a package of it needs to add email aliases to the system in its %post script, and remove them from the system in its %postun script. Where those aliases get written is contingent upon the MTA installed on the system—Postfix uses the file /etc/postfix/aliases as its aliases database, while Sendmail uses the file /etc/aliases as its aliases database.
To deal with situations where the action to take is contingent upon the current system state, conditional shell scripting can be used.
Alternately, RPM provides a trigger mechanism which can be used to list actions to carry out when other software is
installed or uninstalled. These scripts are denoted by the tokens
%triggerin -- package
or
%triggerun -- package
The first token indicates a script to run when the software package is installed or upgraded, while the second token indicates a script to run when the software package is removed.
The Changelog Section
Used to record packaging changes
• List changes, and why made
• Provides a record of how the software is packaged
Tracking Packaging Changes:-
The final stanza of the RPM spec file is the Changelog stanza. This stanza always begins with the following token and is used to list any changes made to the package:
%changelog
Although the structure of this log is technically free-form, the following format is typically used by most RPM packages:
* date packager <packager’s email> version-release
- change made
- other change made
The date must be in the following format:
Wed Nov 20 2002
The current day in the required format can be obtained with the command:
date +"%a %b %d %Y"
Every time a new revision of the package is prepared, the packager simply adds a stanza similar to the above example to the beginning of the Changelog stanza.
Example Changelog Section from FC3 firefox RPM
The following example changelog comes from the Fedora Core v3 firefox RPM:
* Wed Mar 02 2005 Christopher Aillon
<caillon@redhat.com> 0:1.0.1-1.3.2
- Remerge firefox-1.0-pango-selection.patch
* Thu Feb 24 2005 Christopher Aillon
<caillon@redhat.com> 0:1.0.1-1.3.1
- Update to 1.0.1 fixing several security flaws.
- Mark some generated files as ghost (#136015)
- Add RPM version to the useragent
- BuildRequires pango-devel
- Enable pango rendering by default.
- Enable smooth scrolling by default
Putting It All Together
Example spec file
• Package for the less application
• All comments added, though production spec files often
contain comments as well
The less Spec
# Header Stanza begins here
#
# Short description
Summary: A text file browser similar to more, but better.
# the application name
Name: less
# the version of the application
Version: 378
# the packaging revision of this particular version
Release: 8
# this software is licensed under the GPL
License: GPL
# this software is an application used with text files
Group: Applications/Text
# this software source file; not the use of variables
Source: http://www.greenwoodsoftware.com/less/%{name}-%{version}.tar.gz
# a shell script needed for use with less
Source1: lesspipe.sh
# script to change the environment when less is used in Bourne-compatible shells
Source2: less.sh
# script to change the environment when less is used in C shells
Source3: less.csh
# Patches
Patch0: less-378-rh1.patch
Patch1: less-378+iso247-20030108.diff
Patch2: less-378-multibyte.patch
# this software can be downloaded from the following location
URL: http://www.greenwoodsoftware.com/less/
# temporary dir where the software should be compiled
Buildroot: %{_tmppath}/%{name}-root
# non-obvious software required to build the software
BuildRequires: ncurses-devel
# long description
%description
The less utility is a text file browser that resembles
more,but has more capabilities. Less allows you to move backwards in the file as well as forwards. Since less doesn't have to read the entire input file before it starts, less starts up more quickly than text editors (for example, vi). You should install less because it is a basic utility for viewing text files, and you'll use it frequently.
# Prep Stanza begins here
#
%prep
# unpack the source and cd into the source directory
%setup -q
# apply the first patch
%patch0 -p1 -b .rh1
# apply the second patch
%patch1 -p1 -b .jp
# apply the third patch
%patch2 -p1 -b .multibyte
# perform other needed setup
chmod -R a+w *
# Build Stanza begins here
# less uses autoconf, so ./configure it w/ appropriate options
%configure
# compile the software
make CC="gcc $RPM_OPT_FLAGS -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOU
RCE -D_FILE_OFFSET_BITS=64" datadir=%{_docdir}
#
%build
# Install Stanza begins here
#
%install
# as sanity protection, make sure the Buildroot is empty
rm -rf $RPM_BUILD_ROOT
# install software into the Buildroot
%makeinstall
strip -R .comment $RPM_BUILD_ROOT/usr/bin/less
mkdir -p $RPM_BUILD_ROOT/etc/profile.d
install -c -m 755 %{SOURCE1} $RPM_BUILD_ROOT/usr/bin/
install -c -m 755 %{SOURCE2} $RPM_BUILD_ROOT/etc/profile.d
install -c -m 755 %{SOURCE3} $RPM_BUILD_ROOT/etc/profile.d
# define a clean-up script to run after the software in Buildroot is pkg'ed
%clean
# the actual script -- just delete all files within the Buildroot
rm -rf $RPM_BUILD_ROOT
# Files Stanza begins here
#
%files
# set perms and ownerships of packaged files
# the - indicates that the current permissions on the files should be used
%defattr(-,root,root)
# package all files within the $RPM_BUILD_ROOT/etc/profile.d directory
/etc/profile.d/*
# package all files within the $RPM_BUILD_ROOT/usr/bin directory
/usr/bin/*
# package all files within the $RPM_BUILD_ROOT/usr/share/man/man1 directory
%{_mandir}/man1/*
# Scripts Stanza begin here
#
# No Scripts in this RPM
# Changelog begins here
#
%changelog
# newest Changelog entry
* Tue Feb 4 2003 Tim Waugh <twaugh@redhat.com> 378-7
- Part of multibyte patch was missing; fixed.
# 2nd-newest Changelog entry
* Mon Feb 3 2003 Tim Waugh <twaugh@redhat.com> 378-6
- Fix underlining multibyte characters (bug #83377).
# oldest Changelog entry
* Thu Jan 30 2003 Karsten Hopp <karsten@redhat.de> 378-5
- removed older, unused patches
- add patch from Yukihiro Nakai to fix display of japanese text
(#79977)
Advanced Packaging
Creating sub-packages
Building RPMs of binary-only software
Building interactive RPMs
Supporting multiple distributions
Supporting multiple languages
Packagers often need to prepare packages for more than one distribution. Several potential complications should be
considered to ensure that a single spec file can be used to compile RPMs suitable for multiple distributions:
• Different distributions predefine different macros. Most macros defined on Red Hat distributions are a “base line” which
can be assumed to be defined on most major distributions, including SUSE distributions, so using just the macros defined on Red Hat systems aids cross-distribution compatibility
• Different distributions use different versions of RPM. Older Linux distributions use an old RPM release, RPM 3, while modern systems use a newer release, RPM 4. There are both behavioral and syntax difference between different RPM releases which must be counteracted.
• Different distributions sometimes install files in different locations. The Linux Standards Base (LSB) effort has largely eliminated this fac-tor, but it can occasionally still occur.
Packagers often want to release packages which support multiple languages, so that users can see the package description and similar information in their native language. RPM provides a specspo mechanism which can be used to store translated messages for package files.
Building Packages
Modern RPM (version 4.x and higher)
• rpmbuild -b
Legacy RPM (version 3.x and lower)
• rpm -b
Common options
• -a
Targeting a Platform
Overriding Macros
Once a spec file has been prepared, the next step is to build software using this spec file.
The basic command to build software on modern systems is rpmbuild -b spec, while with older systems the command is rpm -b spec. These commands accept any of several different arguments, depending on what part of the spec file should be processed:
• -bp – Carry out the Prep stanza of the spec file
• -bc – "" "" Prep and Build stanzas of the spec file
• -bi – "" "" Build, and Install stanzas of the spec file
• -bl – Verify the Files stanza of the spec file
• -bb – Build a binary RPM based on the spec file
• -bs – Build a source RPM based on the spec file
• -ba – Build both source and binary RPMs based on the
spec file
The most common command to build an RPM from a spec file is:
rpmbuild -ba spec
Sometimes, the --target option is used to force the RPM software to compile software for a specific platform.
For example, on 32-bit Intel-compatible systems running RHEL/FC, RPM software will, by default, produce RPMs which run on any 32-bit Intel-compatible computer but which are optimized for use on 80686-class machines. This option can be used to force RPM to produce executables which only run on 80686-class machines, or which are better optimized for the AMD Athlon, or which are optimized for 80386-class machines.
The command:
rpmbuild -ba --target i686-redhat-linux spec
builds RPMs based on the spec which are only compatible with 80686-class machines, and which are marginally more optimized than the default optimizations RPM performs would offer.
When building packages, RPM software provides the capability to override or modify RPM macros from the command-line. This feature is commonly used by packagers to produce spec files which can be used to compile the same software with different options. For example, the Postfix spec file in RHEL/FC contains a series of macro definitions in the Header stanza which enable or disable support, at
compilation time, for various features. The statement:
%define LDAP 0
is used to define the value of the LDAP variable to 0, and later commands in the Build stanza use this to compile Postfix
without LDAP support. Overriding this variable by the command-line
rpmbuild -ba --define ‘LDAP 1’ postfix.spec
changes the value of the variable, and Postfix is compiled with LDAP support.
Digitally Signing Packages
Why?
• Provides authentication
• Confirms integrity
How?
• Create GPG key
• Modify macros
• Sign package
rpmsign --addsign
Verifying Signatures
• rpmsign -k
Signing Built Packages:-
After producing binary and source RPMs from a spec file, the resulting RPMs can be digitally signed using GPG (or PGP).
Signed packages offer two important advantages to end users who download them:
• They authenticate the package, assuring the user that the package comes from the vendor it is supposed to come from
• They guarantee the package’s integrity, assuring the user that the package has not been modified since the packager signed it
(though RPMs also provide this guarantee using other mechanisms) Both of these features are important on today’s Trojan Horse-riddled Internet.
To sign a package, you must first have a GPG key. If you do not already have one, you can generate one easily:
$ gpg --gen-key
Once you have created a key, modify your RPM macros to instruct RPM to use GPG to sign packages:
echo "%_signature gpg" >> ~/.rpmmacros
Also, specify which key RPM should use when signing packages:
echo "%_gpg_name email_address" >> ~/.rpmmacros
Also tell RPM where to locate your GPG keys:
echo "%_gpg_path $HOME/.gnupg" >> ~/.rpmmacros
Once the RPM software is configured to use GPG, the rpmsign command can be used to sign packages you have built:
$ rpmsign --addsign /path/to/the.rpm
You can export your public key:
$ gpg --export --armor > gpg-pub-key
You can then give this public key to users installing your RPMs, and they can use it to verify that your RPMs are signed by you. To do this, they must first import your GPG public key into their RPM GPG keychain as root:
# rpmsign --import /path/to/gpg-pub-key
Once the public key is imported, the signature of packages can be verified:
$ rpmsign -K package-1.0-1.i386.rpm
package-1.0-1.i386.rpm: (sha1) dsa sha1 md5 gpg OK
If the package verifies, then the user knows the signature of it is that of a vendor they trust.
Revising a Package
Install current SRPM
Drop new source tarball in SOURCES
Update spec file to use new source
Try Prep
• If any patch has error applying, visually inspect to see whats up.
Already applied in new package, or reason for patch addressed via another method == drop patch
If patch needed but won’t apply == redo new patch
In addition to producing new RPMs from scratch, another common task for packagers is to update existing packages,
rebuilding the package as newer versions of the application it contains become available. Revising an existing source RPM requires a few simple steps:,
1. Install the latest available SRPM for that application
2. Add the latest version of the source code for that
application in the SOURCES directory
3. Modify the spec file for that application to use the
new source code.
4. Try to complete the Prep section of the spec file:
$ rpmbuild -bp application.spec
When trying to complete the Prep stanza for the software, some patches may not apply to the new application source code.
If a patch does not apply, inspect the patch and the application source code to see why it does not apply.
1. The patch may not apply correctly because it is no longer needed.
In this case, simply remove the patch from the spec file.
2. The patch may still be needed, but might no longer apply
do to other code changes in the application.
In this case, create a new version of the patch which applies to the new source code.
Once the Prep stanza can be completed successfully, update the Changelog and package versioning information in the spec file, then build new packages:
$ rpmbuild -ba application.spec
Other Resources
RPM references
Add-on Tools
Sources of RPMs
Many tools are available which can simplify the creation of RPMs. These include tools like spec file editing modes for popular text editors:
http://www.tihlde.hist.no/~stigb/rpm-spec-mode.el
http://pegasus.rutgers.edu/~elflord/vim/syntax/spec.vim
There are also a variety of spec file generation tools available:
http://rpmrebuild.sourceforge.net/
http://www.cpan.org/modules/by-module/RPM/RPM-Specfile-1.17.tar.gz
http://checkinstall.izto.org/
One difficulty with preparing packages for multiple releases is the need to have a separate build environment for every release.
There are several applications which can be used to simplify the work of creating multiple build environments on the same machine, including:
http://thomas.apestaart.org/projects/mach/
http://www.solucorp.qc.ca/miscprj/s_context.hc
Several sites exist which provide a variety of high-quality pre-created RPMs, or which can help locate existing RPMs:
http://freshrpms.net
http://www.fedoraproject.org
http://www.rpmfind.net
http://www.GuruLabs.com/downloads.html
Lots of tools are available which ease the work in installing RPMs, including:
http://current.tigris.org
http://www.linux.duke.edu/projects/yum/
http://www.autorpm.org/
http://www.mat.univie.ac.at/~gerald/ftp/autoupdate/
http://apt4rpm.sourceforge.net/