Preparation

To be able to build an RPM package as a normal user, a few minor preparations are necessary in the user's home directory. This includes creating the build root directory and modifying the configuration files for the RedHat Package Manager.

Directories

So that the RedHat Package Manager knows where all source files and later RPMs are to be located, it is recommended to create a build root directory structure similar to that of CentOS/RHEL.

 Example:

cd ~/
mkdir -p ~/rpmbuild/BUILD
mkdir -p ~/rpmbuild/RPMS
mkdir -p ~/rpmbuild/SOURCES
mkdir -p ~/rpmbuild/SPECS
mkdir -p ~/rpmbuild/SRPMS

Configuration of the RedHat Package Manager

The RedHat Package Manager is controlled and configured via two files /usr/lib/rpm/macros and /usr/lib/rpm/redhat/rpmrc. As a normal user, you can copy these into your own build root directory.

 Example:

cd ~/
cp /usr/lib/rpm/macros ~/.rpmmacros
cp /usr/lib/rpm/redhat/rpmrc ~/.rpmrc
In ~/.rpmmacros

Now the correct directories for the user must be entered. For this, the relevant macro definitions must be changed or re-entered as follows.

 Example:

%_home /home/„user“
%_topdir %{_home}/rpmbuild
%_builddir %{_topdir}/BUILD
%_rpmdir %{_topdir}/RPMS
%_sourcedir %{_topdir}/SOURCES
%_specdir %{_topdir}/SPECS
%_srcrpmdir %{_topdir}/SRPMS

Alternative:

su - „user“
cp -r /usr/src/redhat/ ~/rpmbuild
echo '%_topdir %(echo $HOME)/rpmbuild' >> ~/.rpmmacros

Sources

The source files "source-paket".tar.gz must be located in the directory ~/rpmbuild/SOURCES in order to be found by the Redhat Package Manager with the above configuration.

First test

To make sure that the package can be compiled, it is advisable to check this once beforehand using configure, makes.

Example:

mkdir -p ~/tmp
tar -C ~/tmp -xvfz ~/rpmbuild/sources/<paket>.tar.gz
cd ~/tmp/<paket>
./configure
make

2.2 Makefile (. in, .am)

If no problems have occurred during the translation test, the Makefile can now be addressed. Here it is important to determine whether the DESTDIR mechanism is supported. This is used to verify whether the package and all associated files can be installed in any directory. This is absolutely necessary to be able to install the files as a normal user and then have the Redhat Package Manager pack them into an RPM package.
Use the text editor to check the Makefile created by the command . /configure for the following entries:

  • an entry of the form: DESTDIR =
  • entries in the install area to the form: install ... $(DESTDIR)/$(prefix)/ ...

If the above entries are not present, there are two possibilities for the creation of the . rpm to be successful:

  • you add the entries manually to the Makefile.in and create a patch
  • one modifies the "name". spec

Although the second variant will probably be the easier one in most cases, I will describe the first variant in more detail here. In some source directories you will find a file called Makefile.am. This file is used by automake to create all the necessary files, such as the configure script or the Makefile.in. If the programme is not installed from a CVS source, where the automake process is common, the Makefile.in file can be used.
The Makefile.in file is used by configure to create the actual Makefile. Therefore, it is advisable to redesign the Makefile.in so that the DESTDIR mechanism works without problems. To do this, proceed as follows. Delete the directory of the previously unpacked sources and unpack them again (without re-running . /configure and make).

  • rm -rf ~/tmp/"package"
  • tar -C ~/tmp -xvfz ~/rpmbuild/sources/"package".tar.gz
  • cd ~/tmp/"package"
  • save the file Makefile.in in its original form: cp Makefile.in Makefile.in.orig
  • edit the file Makefile.in as described before
  • create a . patch file with reference to the original sources and copy it into the ~/rpmbuild/SOURCES directory
  • gendiff ~/tmp/"package". orig ~/rpmbuild/SOURCES/"package". patch
  • alternative
  • diff -uNr Makefile.in.orig Makefile.in >> ~/rpmbuild/SOURCES/Makefile.patch

The "package". spec File

The "paket". spec file informs the RedHat Package Manager how to compile the programme, install it and then pack the files into the RPM package. Some developers include a "paket". spec file in their source package, which can usually be used after a few minor adjustments to the distribution. Since this is not always the case, I assume that the "paket". spec file has to be written by yourself. Special sections in the "paket". spec file start with a "%". The most important ones are called:

  • define
  • description
  • prep
  • setup
  • patch
  • build
  • install
  • files
  • clean
Definitions

Definitions serve to provide an overview and easy handling of the . spec file. In the best case, one change to the definitions is enough and it can be used again for another programme.

Package details

At this point, the RedHat Package Manager asks for the name of the package, the version, etc. The RedHat Package Manager will also ask for the name of the package. At this point, the above definitions can serve very well as a reference.

Example:

%define name ntp
%define pkg ntpd
%define ver 4.2.4p7
%define release 21.el5.maj
%define nsusr ntp
%define nsgrp ntp
%define nnmmsg logger -t %{name}/rpm
%define mibdir %{_datadir}/mibsSummary: System time synchronization using the Network Time Protocol (NTP)
Name: %{name}
Version: %{ver}
Release: %{release}
License:
distributableBuildroot: %{_tmppath}/%{name}-root
Provides: ntpserver ntpclient sntpclient
Requires(pre): /usr/sbin/groupadd /usr/sbin/useradd
Requires(pre): /bin/awk sed grep
Requires(post): /sbin/chkconfig
Requires(preun): /sbin/chkconfig
Requires(preun): /sbin/service
Requires(postun): /sbin/service
Requires: libcap
Requires: ntpdate = %{version}-%{release}
%{?with_avahi:BuildRequires: avahi-compat-libdns_sd-devel}
BuildRequires: perl-HTML-Parser
BuildRequires: libcap-devel
BuildRequires: readline-devel
BuildRequires: ncurses-devel
BuildRequires: openssl-devel
BuildRequires: lm_sensors-devel
BuildRequires: kernel-headers
Obsoletes: xntp3 ntpstat
%description
The Network Time Protocol (NTP) is used to synchronize a computer's time with another reference time source. This package contains utilities and daemons to synchronize the computer's time to Coordinated Universal Time (UTC) via the NTP protocol and other NTP servers. It includes ntpdate (a program for retrieving the date and time from remote machines via a network) and ntpd (a daemon which continuously adjusts system time).

The last definition describes in which directory the programme should be installed. This directory is later referenced with ${RPM_BUILD_ROOT}. Without a summary definition, the RedHat Package Manager will give an error message. The summary definition is a one-line short description of the actual package, in the %description definition contains the detailed description. This is terminated with the next section usually %prep.

Sources and patches

The source package is specified via the definition Source. Several source files can be referenced.

 Example:

Source0: %{name}-%{ver}.tar.gz
Source1: %{name}-refclock
Source2: %{name}.init

The specification of patches is done via the definition patch, also here several files can be referenced.

Example:

Patch0: Makefile.ini.patch
Patch1: %{name}.sysconfig

The source and patch files are unpacked in the %prep section and prepared for compilation. These instructions are commands that are interpreted with the standard shell (/bin/sh). To simplify matters, the Redhat Package Manager provides predefined macros for this purpose %setup and %patch.
A small overview of the arguments available through the %setup macro, more details via The %setup and %patch Macro.

%build section

In the section %build, the commands for compiling the sources are defined. As in the %prep section, these commands are interpreted by the /bin/sh shell. In this section, compiler flags (optimisations) can be communicated to the configure script supplied. The installation path is also defined here, which could also be done with %{_prefix} if it was suitably defined in ~/. rpmmacros.

%install section

This section contains all the commands to successfully install the files previously translated by the %build section. For this, it is necessary that the DESTDIR mechanism has been built into the Makefile.in.

Example:

%install
make DESTDIR=${RPM_BUILD_ROOT} install

If the DESTDIR mechanism is not built into the Makefile.in, this can alternatively be done at this point by a fixed assignment.

Example:

%install
make prefix=${RPM_BUILD_ROOT}%{prefix} install

Note that other variables, such as mandir, datadir, may need to be redefined for the installation process. Also note that there may be complications with the library assignment due to the link from %{prefix} to ${RPM_BUILD_ROOT}%{prefix}. Furthermore, within the %install section, it is recommended to unpack the manpages and install them within the later file system.

Example:

gzip -9 ${RPM_BUILD_ROOT}%{_mandir}/*/*

Using the tools find and sed, a file list for the %files section can be created at this point.

Example:

cd ${RPM_BUILD_ROOT}
find . -type d | sed '1,2d;s:^\.:\%attr(-,root,root) \%dir :' > ${RPM_BUILD_DIR}/file.list.%{name}
find . -type f | sed 's:^\.:\%attr(-,root,root) :' >> ${RPM_BUILD_DIR}/file.list.%{name}
find . -type l | sed 's:^\.:\%attr(-,root,root) :' >> ${RPM_BUILD_DIR}/file.list.%{name}

%files section

This section contains a list of files and corresponding user and rights assignments which the package should contain.

If not every single file or group is to be listed, a file list can alternatively be specified. The file list should be adapted beforehand. Since it is possible that some files already exist, all subdirectories are entered as belonging to the package starting from ${RPM_BUILD_ROOT}. This can lead to unwanted warning messages when removing the package.

%clean section

The %clean section has the task of cleaning up the ${RPM_BUILD_ROOT} directory after building, compiling and installing the package.
%clean rm -rf ${RPM_BUILD_DIR}/%{name}-%{ver} rm -rf
${RPM_BUILD_DIR}/file.list.%{name} rm -rf ${RPM_BUILD_ROOT}

Finalise the RPM package

Once the sources and the "name". spec file have been created, you can start with a first attempt.

rpmbuild -ba -vv "specfile" | tee ~/rpmbuild.out

The command just shown will trigger the following actions. The sources and the "name". spec file packed by cipio and archived in the directory ~/rpmbuild/SRPMS. This file can be used for a later rebuild. Unpacked the sources, compiled and formed the package and moved it to the directory ~/rpmbuild/RPMS.
In addition, it is possible to display detailed information during RPM creation using the -vv option and the output is redirected to a file in the user home directory.