4. Building a RPM

This graph represents the different steps one has to follow to build a rpm package. Circled numbers are references to sections of this howto.

4.1. From an existing source RPM

This is generally the case for the packages which are already included in the distribution.

The latest rpm files from cooker are available on many mirrors which list is available at http://www.linux-mandrake.com/en/cookerdevel.php3 . Under the ftp hierarchy, you will find:

When you find the source rpm you want to modify for Mandrake Linux, just issue rpm -ivh mypackage.src.rpm; it'll install all source files into your RPM directory.

For example:

[camille@kenobi ~/rpm]$ rpm -i /cooker/SRPMS/ktron-1.0.1-2mdk.src.rpm 
[camille@kenobi ~/rpm]$ ls -R * 
SRPMS: 
SPECS: 
ktron.spec 
SOURCES: 
ktron-1.0.1.tar.bz2 
RPMS: 
noarch/ i686/ i586/ i386/ 
BUILD: 

We see that rpm installed in our RPM tree the source file ktron-1.0.1.tar.bz2 and the spec file. It is all we need, in that case, to modify the spec file and then rebuild the package.

It is important to note that each package maintained at MandrakeSoft is stored on a cvs system. This allows every state of a package to being recorded by the system, so that the developer may consult the archive to check previous modifications and eventually come back to an older release version.

Each spec file is stored on a module called SPECS/<package> or contrib-SPECS/<package>.

For details on how to access cvs system, consult Mandrake Linux CVS pages

4.2. From raw sources

You found an interesting program at freshmeat or AppWatch or sourceforgewhich warns you when the tea is ready. And you want it available to all our Mandrake Linux's english tea drinkers.

Download it and place it in the SOURCES directory.

4.3. Preliminary checks

4.4. Inside the spec file

Here we are. This is the important section of this document. The spec file contains all the information needed by rpm to:

  1. compile the program and build source and binary rpms,

  2. install and uninstall the program on the final user's machine.

The fact that these two types of information are messed up into one single file may be quite confusing for the beginner. Actually, this is due to the source tar tree, which contains already this information. As installation procedure is extracted from the installation process generally run by make install into the source tree, both parts are tightly linked.

Important

In a nutshell, the spec file describes a "simulated" compilation and installation, tells rpm which files resulting from this installation are to be packed, and how to finally install these files onto the user's system. Commands there are executed using the /bin/sh shell, so such things like [ -f configure.in ] && autoconf is valid.

This part is not intended to explain you in details all the features of a spec file. The book Maximum RPM (see Section 7) explains it deeply. All we are going to do here is quickly check all of the features used into one standard example Mandrake spec file.

This is an example from the cooker repository. You may also consider our template spec file to begin your from scratch.

As you build more and more RPMs,you will find that there are some options that we have not told you about. RPM is extremely extensible, so, finding out all of those is left as an exercise to the reader. It is always good practice to open up some spec files to take a look at them and see how they work.

you can get a list of specs and patches here.

%define name gif2png 
%define version 2.0.1 
%define release 1mdk 

Name: %{name} 
Summary: tools for converting websites from using GIFs to using PNGs 
Version: %{version} 
Release: %{release} 
Source: http://www.tuxedo.org/~esr/gif2png/%{name}-%{version}.tar.bz2 
Source1: %{name}-%{version}-mdk-addon.tar.bz2 
Patch: gif2png-2.0.1-bugfix.patch.bz2 
URL: http://www.tuxedo.org/~esr/gif2png/ 
Group: Applications/Multimedia 
BuildRoot: %{_tmppath}/%{name}-buildroot 
License: MIT-like 
Requires: python 

%description
Tools for converting GIFs to PNGs. The program gif2png converts GIF files
to PNG files. The Python script web2png converts an entire web tree, also
patching HTML pages to keep IMG SRC references correct.

%prep 
rm -rf $RPM_BUILD_ROOT 
%setup -a 1 
%patch -p1 

%build 
%configure 
%make

%install 
%makeinstall

%clean 
rm -rf $RPM_BUILD_ROOT 

%files 
%defattr(-,root,root,0755) 
%doc README NEWS COPYING AUTHORS 
%{_mandir}/man1/gif2png.1*
%{_mandir}/man1/web2png.1*
%{_bindir}/gif2png 
%{_bindir}/web2png 

%changelog 
* Mon Nov 02 1999 Camille Begnis <camille@mandrakesoft.com> 2.0.1-1mdk
- Upgraded to 2.0.1 

* Mon Oct 25 1999 Camille Begnis <camille@mandrakesoft.com> 2.0.0-1mdk
- Specfile adaptations for Mandrake
- add python requirement
- gz to bz2 compression

Let's then analyze in details each line of this file.

Be careful, a % at the beginning of a line may tell different things :

4.4.1. Header section

%define name gif2png
%define version 2.0.1
%define release 1mdk

These three lines define constants that may be used in many following sections of the spec file, named %{name}, %{version} and %{release}.

Then, we can fill up some information fields for rpm :

Name: %{name}

The name of the package as used in package's name and package database on the user's machine.

Note that the "%{name}" is a reference to the previous define.

Version: %{version}
Release: %{release}

This is the moment to explain how is formed the name of a package. It is important to always respect this standard in order to make your work understandable to others.

There are also some tags that you might want to know about, but are not in the example spec file. There are some that you might encounter. It is not expected that you remember all of this if you just started building rpms, but after some time, this list makes good reference!

  • A binary package is named as: name-version-release.arch.rpm

  • A source package is named as: name-version-release.src.rpm (e.g. gif2png-2.0.1-1mdk.src.rpm for our example)

The name is generally chosen to be the name of the main binary of the package, though with adequate reasons this you can get away with another name.

The version is the number from the unpatched sources. It is the version number in the name of the original archive file: name-version.tar.gz.

The release is a number followed by mdk (stands for "Mandrake"; this is absolutely mandatory) which is incremented at each new build of the package. This may be due to a patch applied to the sources, a modification to the spec file, the addition of an icon, etc.

Summary: tools for converting websites from using GIFs to using PNGs

This line is a one-liner of the package description.

Source: http://www.tuxedo.org/~esr/gif2png/%{name}-%{version}.tar.bz2 

This line tells rpm what source file to use for building this package. Note that the filename is preceded by a complete URL (which is optional) pointing to the site where the original source is available; rpm will remove the url, keep the filename only, and search in the SOURCES directory. Although we say that the complete URL is optional, it is highly recommended as people will know where to find new sources should they take a liking to upgrading the source and do a recompilation.

When there are more than one source file, use other lines with Source1: ..., then Source2: ..., etc.

Patch: gif2png-2.0.1-bugfix.patch.bz2

Two reasons for this optional tag:

  1. You fixed a bug on the program sources. So you generated a patch file to be applied to the sources before compilation.

    Note that the patches are all bzipped, too. Even though if a patch is small you might not benefit from bzip2 compression it has to be bzipped, to be consistent.

  2. You've been warned of the existence of a patch for your software's version somewhere on the net, and downloaded it.

Note that the patch file must be placed into the SOURCES directory; as for the sources, there can be several patches, they will be named Patch1, Patch2, etc.

URL: http://www.tuxedo.org/~esr/gif2png/

This line (optional but highly recommended) points to the home page of the program.

Group: Multimedia

This is to tell rpm in which part of the general package tree to place this package. This feature is used with package managers front-end such as rpmdrake or kpackage.

The complete group structure to use, which is different from the one RedHat uses, is shown in Appendix C. It is mandatory to follow it, otherwise your package will mess with the other ones, in the package tree selection of Mandrake Linux installer, or in package manager front-ends.

BuildRoot: %{_tmppath}/%{name}-buildroot

This line is very important and cannot be omitted. It tells rpm that to install the program, it will have to use a special root directory (a fake "/") onto the compiling machine. There are two reasons for that:

  1. When building a rpm, you don't have root access to the machine, so you cannot install the package in normal directories ;

  2. The installation into the working tree of a working machine will probably mess the package's files with other files, and most important, it may be dangerous if the package is already installed. A lot of people like to use /var/tmp or /tmp for the buildroot. This is not necessarily a problem if you are the only user of your machine, but if you have multiple users on you machine, and they compile the same package at the same time rpm will barf. Therefore it is important that you define %{_tmppath}, and within your own home directory!

License: MIT-like

This tag (superseding Copyright) defines the license chosen by the copyright holder that will apply to the software being packed. In most cases it is GPL. See Appendix E for complete valid licenses list.

Here is a list of other licenses.at FSF. If you find that a package has a very similar license to a particlar license listed, but is not *quite* that license, you can put a suffix -like (see above.) for example, BSD-like.

Requires: python

This line was added because one of the programs included in the package is a python script. It then needs python to be executed. You can put optional minimum (or equal) version, for example: Requires: python >= 1.5.1

%description
Tools for converting GIFs to PNGs. The program gif2png converts GIF files
to PNG files. The Python script web2png converts an entire web tree, also
patching HTML pages to keep IMG SRC references correct.

This is a quite special tag inside the header of the spec file, because it is of a whole text made of various lines and paragraphs if needed. It contains the full description of the software being installed in order to help the user to decide whether he wants to install the package or not.

You may be asking yourself at this point: "And what about translations?" Actually, to improve readability of spec files, translations of summary and description tags are strored in a special file called <package>.po.

These files are stored on poSPECS module into cooker cvs. When a new package is created, the base po file is automatically created in this module for future translations.

This method implies that all text into a .spec file is written in english. However, an exception to that is for packages intended to a special language (ispell-de for example). It is then recommended to have the text in both languages: English and the specific package language. You will use special tags for that: Summary(de): .. and %description -l de.

4.4.2. Prep section

%prep  
rm -rf $RPM_BUILD_ROOT 
%setup -a 1 
%patch -p1 

Into this section, is written the first script being executed by rpm. Its role is to:

  • create the top-level build directory (into BUILD),

  • unpack the original sources into the build directory,

  • apply optional patches to the sources.

It may be then followed by any command wanted by the packager to get the sources into a ready-to-build state.

rm -rf $RPM_BUILD_ROOT

This is the first of the commands being executed into the %prep section, it cleans up a possible previous install directory.

%setup -a 1 

This is a buit-in script macro which

  • cd's into the build tree,

  • extract the source(s)

  • change owner and permissions of source files.

It defaultly extracts the first source; you have to use parameters for any other sources, in our example -a 1 tells that we want also the extraction of the source number 1.

%patch -p1

The macro responsible for applying the patch to the sources; its parameter "-p<num>" is passed to the patch program. Imagine if you had another patch declared Patch1: .. in the header section, you would add another line: %patch1 -p1. Adding a -b .your_suffix would also be nice, as you can let others know what your patch does, or who did the patch. For example, if Fred did the patch, then he could do %patch -p1 -b .fred, or if Barney did the patch then it could be %patch -p1 -b .barney

4.4.3. Build section

%build 

This section will contain the script responsible for the actual build of the software.

It consists of the commands being issued when building a package from an untarred source tree.

%configure

This is the line used for configuring autoconf'ed sources. %configure issues a ./configure with many add-ons such as export CFLAGS="$RPM_OPT_FLAGS" before the configure, and options such as i586-mandrake-linux --prefix=/usr --datadir=/usr/share etc.

Sometimes these arguments are not supported by the configure script. In such case, you have to discover the reason, and issue the ./configure with appropriate parameters. Give the target platform to the configure call, if supported, with %{_target_platform}; of course, specification of an architecture must be avoided in specfiles; on ix86, this will expand to i586-mandrake-linux, as shown in the example above.

Note that you will need the libtool package to use %configure with packages building shared libraries.

Important

When building, and when testing your package, you should verify that the target host is actually a i586 ; in particular, when compiling on a higher processor type, the default behaviour of the configure script is to discover your processor, and optimize for it. The target of the %configure macro is to avoid this behaviour.

%make

This is a simple macro that basically performs a make with appropriate multiprocessor parameter -j<num>.

For sources using xmkmf, you should replace the next make with:

make CDEBUGFLAGS="$RPM_OPT_FLAGS" CXXDEBUGFLAGS="$RPM_OPT_FLAGS" 

For other packages, in many (but not all) cases a simple make will do.

4.4.4. Install section

%install 

This section will contain the script responsible for actually install the package into the simulation installation dir.: $RPM_BUILD_ROOT.

It'll contain all commands necessaries to have the software ready to run on the user's system.

%makeinstall

This line finally installs the software into the simulation installation directory for autoconf'ed sources. This macro will expand to "make install" with many options in order to install in the simulation directory $RPM_BUILD_ROOT, e.g. prefix=$RPM_BUILD_ROOT/usr bindir=$RPM_BUILD_ROOT/usr/bin etc.

In some cases the configure script will be partially broken and you may need to lurk in the Makefiles to guess the additional parameters to have it install correctly. One of the most common ones is that sometimes you have to use make DESTDIR=$RPM_BUILD_ROOT install.

To save both disk space and download time, Mandrake uses bzip2 to compress man- and info-pages. However, this aspect is handled directly by the Mandrake custom rpm program. At this point of the spec file, older packages contained some lines like find $RPM_BUILD_ROOT/usr/man -type f -exec bzip2 -9f {} \;

It is the same for old strip $RPM_BUILD_ROOT/usr/bin/* || : lines: they have to be removed

All this stuff is to prepare the files to be ready to be packed.

%clean

This section is meant to clean the build directory tree, $RPM_BUILD_ROOT.

rm -rf $RPM_BUILD_ROOT

This is where the job is done.

4.4.5. Files section

%files 

This section consists of a list of files that will be picked from our simulation directory tree to be packed into the package. See the fine manual for the different options not being used in that simple example.

The file list must be written by hand in the spec file. It may be constructed by listing all files created by rpm in the build directory tree. In order to do that, issue a rpm -bi mypackage.spec in order to stop the building process just after the simulated install. Then, look in the simulated installation directory, ~/rpm/tmp/gif2png-buildroot in our case, to see which files you want to put in your package (most of the time, you will put them all).

Note that you should never use find to build a list of files to include but explicitely list all files (this'll show up bugs in new versions). The only exceptions is for locales for which you should use %find_lang %{name} in %install section and replace %files by %files -f %{name}.lang (see Appendix B).

Note about directory structure: The files being installed by your package "should" follow the FHS recommendations at http://www.pathname.com/fhs

%defattr(-,root,root,0755)

This tag defines the attributes to be applied to each file being copied to the user's system. The four arguments given means:

  • -: all the attributes for regular files are remained unchanged,

  • root: the owner of the file is root,

  • root: the group of the file is root,

  • 0755: the attributes applied to all directories owned by this package are 0755.

%doc README NEWS COPYING AUTHORS

The special tag %doc designates files being part of the documentation of the package. The files so-called will be placed in /usr/doc/gif2png-2.0.1/. This directory will be also automatically created. Files specified by %doc are relative to your untarred source directory in BUILD.

%{_mandir}/man1/gif2png.1*
%{_mandir}/man1/web2png.1*

Here also it is recommended to list each man or info file separately.

Note

Also you may wonder why telling gif2png.1* and not gif2png.1.bz2. This is to preserve compatibility with other systems that could use gzip compression instead of Mandrake bzip. If you find such referencies to bz2 compression into spec files, change them to a wildcard. Most of the time you can even use %{_mandir}/man1/*, this will take all the files it can find.

%{_bindir}/gif2png
%{_bindir}/web2png

As you can see, you have macros for every kind of path you need. Here are the most useful ones (look at /usr/lib/rpm/macros for everything) : %{_prefix}, %{_bindir}, %{_sbindir}, %{_datadir}, %{_libdir}, %{_sysconfdir}, %{_mandir}, %{_infodir}. For games, use %{_gamesbindir} and %{_gamesdatadir}.

4.4.6. Changelog section

%changelog 

This section is to keep track of different changes made to the package. Every new release build of the package must correspond to a paragraph in this section as well as an increase in the release number (if not in the version number). The structure of these paragraphs have to be respected as following:

* Mon Nov 02 1999 Camille Begnis <camille@mandrakesoft.com> 2.0.1-1mdk 

  • The first line of the paragraph begins with * and, in order, each one separated by a space:

  • three letters for the day of the week,

  • three letters for the month,

  • two figures for the day of the month,

  • four figures for the year,

  • First name of the packager,

  • Last name of the packager,

  • e-mail of the packager between <>.

  • version and release of current modifs.

- Upgraded to 2.0.1

Then follow one line per modification applied to the package beginning by a -.

These are examples:

- spec file stolen from korganizer. 
- last snapshot before release 
- Mandrake adaptations. 
- Fix bug in /etc/zsh use USERNAME instead of USER. 
- Remove petit bouchon which annoy other players. 
- Improve /etc/z* to source the /etc/profile.d/ files. 
- fix typo in examples directory name 
- fixed QT libs version requirements 
- add patch to handle Earl Grey tea 

4.5. The build

Our spec file is finally complete. Take a long breathe, sit down and type rpm -ba mypackage.spec

Note

You may also add the --clean option which cleans the BUILD directory after package building completes. Usefull if you have little disk space.

There are then two possibilities for the last line of your process:

You are in the second case? Congratulation you passed the test, you are not an alien.

Good luck so long, have a look to rpm building options (man rpm) to debug your work, look at other persons' specfiles, etc..

There is a very clean way to build package: use rpm -bs --rmspec --rmsource (in order to remove anything from the original build) and then do a rpm --rebuild.