FIRST DRAFT: RPM Packaging as Normal User - with an example

RPM is now part of Linux standards. For administrators, RPM packages allow easy, silent installation and removal. For developers, RPM provides separation of packaging and original source and working on different distributions and platforms with just recompilation.

In this tutorial, we package an example application 'wget'. We start from scratch, so we will also install everything needed to build it.

First, we'll manually compile target and install it to a test directory. We'll discard the resulting program binary, but remember how we got it built. Then we'll install and configure rpm-build. Finally, we'll package the target application.

Test Compiling and Installing Target Program

Packaging a target program means automating the targets compiling and installation. Before automating, we must know how to do that manually.

First, we will get sources for our chosen target 'wget' from programs homepage. We can use a generic search engine like google.com or the biggest free software directory freshmeat.net to locate wget homepage http://www.gnu.org/software/wget/. After making sure this is the correct homepage for our target program, we locate and download the source code http://ftp.gnu.org/pub/gnu/wget/wget-1.9.1.tar.gz. It is the latest (biggest version number) tarball (.tar.gz or .tar.bz) in the download directory.

$ wget http://ftp.gnu.org/pub/gnu/wget/wget-1.9.1.tar.gz

Then extract the tarball

$ tar -zxvf wget-1.9.1.tar.gz
$ cd wget-1.9.1

Most programs automate compiling with GNU make and related tools. './configure' detects computer architechture and installed libraries and writes this information to "Makefile". 'make' run on this same directory does the compiling by running compiler with given arguments.

$ ./configure
configuring for GNU Wget 1.9.1
checking build system type... i686-pc-linux-gnu
..
$ make
cd src && make CC='gcc' CPPFLAGS='' DEFS='-DHAVE_CONFIG_H -DSYSTEM_WGETRC=\"/usr/local/etc/wgetrc\" -DLOCALEDIR=\"/usr/local/share/locale\"' CFLAGS='-O2 -Wall -Wno-implicit' LDFLAGS='' LIBS='-lssl -lcrypto -ldl ' prefix='/usr/local' exec_prefix='/usr/local' bindir='/usr/local/bin' infodir='/usr/local/info' mandir='/usr/local/man' manext='1' .. make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/tee/wget-1.9.1/windows'

After a while, compiling ends. Find and run the resulting binary to see that it works.

$ ./src/wget

Now we have successfully compiled the program from source.

To install it in a directory we choose, we must change some settings and compile it again. Clean up compiled binary and temporary files used in compiling.

$ make clean

Create a directory for installing wget, and a new makefile that tells 'make install' to use that directory. Use a path from your own system instead of /home/tero. You can see the current path with 'pwd'.

$ mkdir myinstall
$ ./configure --prefix=/home/tero/wget-1.9.1/myinstall

Compile wget again, and install it to the directory we just created. Do not run 'make install' as superuser root.

$ make
$ make install

Once compiling and installation is finished, you should have a working installation of wget in myinstall/. Try running the wget installed in myinstall/. To type the whole, absolute path, start with './'. If you don't start the path with a dot, you end up running the wget that came with your Linux distribution instead of the one you compiled.

$ ls myinstall
bin etc info man share
$ ./myinstall/bin/wget wget: missing URL ..

If it says "wget: missing URL" instead of "No such file or directory" or "segfault", well done, we've compiled wget and installed it to a directory we have created. The compiled or installed wget is not needed. We need to remember how we got it compiled and installed, because soon we will automate this process by packaging wget.

Prepare Rpmbuild Environment

Rpmbuild must be installed and configured before we can use it. Some old writings mistakenly guide users to compile rpms with root (superuser) priviledges. Here, we install and configure rpmbuild as root, but use it as a user - just like any other program.

Installing and Configuring rpmbuild

# yum -y install rpm-build

# /etc/rpm/macros # (c) GPL 2003 Tero.Karvinen at-sign iki.fi
%packager %(echo "$USER")
%_topdir %(echo "$HOME")/rpmbuild
%_rpmtopdir %{_topdir}/%{name}
%_builddir %{_rpmtopdir}/BUILD
%_rpmdir %{_rpmtopdir}
%_sourcedir %{_rpmtopdir}
%_specdir %{_rpmtopdir}
%_srcrpmdir %{_rpmtopdir}
%_tmppath %{_rpmtopdir}/TMP
%_buildroot %{_tmppath}/%{name}-root
# http://www.iki.fi/karvinen/rpm-build-as-user.html

Per-user configuration and directory structure

If you are still root, exit.

Create directories as described in /etc/rpm/macros

$ mkdir -p $HOME/rpmbuild/wget/
$ cd $HOME/rpmbuild/wget/
$ mkdir TMP/ BUILD/

Package Target Program

Create a spec file. Start with a template from teromplates. Modified lines marked with bold. %files part is copy-pasted from rpmbuild error message.

# $HOME/rpmbuild/wget/wget.spec
# Minimum to get it to package as rpm
# (c)2004 Tero Karvinen 
Summary	: Does foo for bar. 
Name		: wget
Version		: 1.9.1
Release		: 1
License		: check_COPYING
Group		: check_usr_share_doc_rpm_GROUPS
URL		: http://program.homepage.invalid
Source		: http://program.homepage.invalid/%{name}-%{version}.tar.gz
BuildRoot	: /var/tmp/%{name}-buildroot
#Requires	: requires_to_run

%description
Long description could be taken from README. 

%prep
rm -rf BUILD/* TMP/* /var/tmp/%{name}-buildroot/
%setup -q

%build
%configure
make

%install
%makeinstall

%files
%defattr(-,root,root)
%doc README
%{_bindir}/*
   /etc/wgetrc
   /usr/share/info/wget.info-1.gz
   /usr/share/info/wget.info-2.gz
   /usr/share/info/wget.info-3.gz
   /usr/share/info/wget.info-4.gz
   /usr/share/info/wget.info.gz
   /usr/share/locale/bg/LC_MESSAGES/wget.mo
   /usr/share/locale/ca/LC_MESSAGES/wget.mo
   /usr/share/locale/cs/LC_MESSAGES/wget.mo
   /usr/share/locale/da/LC_MESSAGES/wget.mo
   /usr/share/locale/de/LC_MESSAGES/wget.mo
   /usr/share/locale/el/LC_MESSAGES/wget.mo
   /usr/share/locale/es/LC_MESSAGES/wget.mo
   /usr/share/locale/et/LC_MESSAGES/wget.mo
   /usr/share/locale/fr/LC_MESSAGES/wget.mo
   /usr/share/locale/gl/LC_MESSAGES/wget.mo
   /usr/share/locale/he/LC_MESSAGES/wget.mo
   /usr/share/locale/hr/LC_MESSAGES/wget.mo
   /usr/share/locale/hu/LC_MESSAGES/wget.mo
   /usr/share/locale/it/LC_MESSAGES/wget.mo
   /usr/share/locale/ja/LC_MESSAGES/wget.mo
   /usr/share/locale/nl/LC_MESSAGES/wget.mo
   /usr/share/locale/no/LC_MESSAGES/wget.mo
   /usr/share/locale/pl/LC_MESSAGES/wget.mo
   /usr/share/locale/pt_BR/LC_MESSAGES/wget.mo
   /usr/share/locale/ro/LC_MESSAGES/wget.mo
   /usr/share/locale/ru/LC_MESSAGES/wget.mo
   /usr/share/locale/sk/LC_MESSAGES/wget.mo
   /usr/share/locale/sl/LC_MESSAGES/wget.mo
   /usr/share/locale/sv/LC_MESSAGES/wget.mo
   /usr/share/locale/tr/LC_MESSAGES/wget.mo
   /usr/share/locale/uk/LC_MESSAGES/wget.mo
   /usr/share/locale/zh_CN/LC_MESSAGES/wget.mo
   /usr/share/locale/zh_TW/LC_MESSAGES/wget.mo
   /usr/share/man/man1/wget.1.gz

%changelog
* Sat May 29 2004 Tero Karvinen tero.karvinen  iki.fi
- Initial spec-file

$ rpmbuild -ba wget.spec

<< Back to homepage

Tested with Fedora Core 1 and 2.

Copyright 2003-2004 Tero Karvinen. All Rights Reserved. Not yet valid XHTML Basic 1.0