| Revision History | ||
|---|---|---|
| Revision A | 09 Sep 2002 | trf |
| Revised with help of John Stile, also described the purpose of some of the sections in a .spec file. | ||
| Revision B | 06 Oct 2003 | trf |
| Revision C | 27 May 2005 | trf |
| Updated bibliography links and switched to DocBook 4.1.2 and using xmlto to process. | ||
Table of Contents
Distributing binary packages of your software is an excellent way to get exposure. The more exposure that your project gets, the more interest there will be in the project, and hopefully that will attract developers.
In this document, I will discuss how to prepare RPM packages. I don't have any special love for RPMs. Packages are packages as far as I'm concerned, but I'm more familiar with making RPMs so I will cover those first. In later documents, I will cover Debian packages, apt-get, and the FreeBSD ports collection.
This is how to create the RPM build directories and how to setup your ~/.rpmmacros.
For more information see [IBMRPM2] and [FRFIGHT].
Put something similiar to the following in a file called .rpmmacros in your home directory:
%packager T.R. Fullhart <kayos@genetikayos.com> %vendor Name of your project %_topdir /home/kayos/rpm
The .rpmmacros file is used by rpmbuild to provide defaults. You may find references to the .rpmrc file, but it has been deprecated in favor of this file.
The first 2 lines will add information to each RPM package you build so others can know who made the package
The last line is so you can build packages as a user. It's not good practice to build packages as root.
In order to build packages as a user, you will also need to create build directories. By default, rpm will expect to find and use the following directories:
%{_topdir}/BUILD
%{_topdir}/RPMS
%{_topdir}/RPMS/i386
%{_topdir}/SOURCES
%{_topdir}/SPECS
%{_topdir}/SRPMS
You will need to manually create the directories. For example, on my machine I use the example .rpmmacros file above. I set %_topdir to /home/kayos/rpm, so I had to run the following commands to create the build tree:
mkdir /home/kayos/rpm/BUILD mkdir /home/kayos/rpm/RPMS mkdir /home/kayos/rpm/RPMS/i386 mkdir /home/kayos/rpm/SOURCES mkdir /home/kayos/rpm/SPECS mkdir /home/kayos/rpm/SRPMS
For more information on making .spec files and RPMs, check out the bibliography at the end of this document for some great links and examples.
Making an RPM for software that comes as a tarball and uses the ./configure and make conventions is easy.
Put your .spec file in the SPECS subdirectory that you created in the previous section. Put your tarball in the SOURCES subdirectory.
I'll cover the major sections in the .spec file, but the key sections that actually build the software in an RPM are the %build, %install, and %files sections.
The %prep section is where you unpack your sources so you can do the build. In the sample below, I use the %setup macro. The %setup macro uses the Source: line at the top of the file to find a file in the SOURCES directory. Then it unpacks the file into the BUILD directory. The %setup macro is smart, it knows how to unpack .tar, .zip, .bz2, and .gz files.
In the %build section, you usually want to run something like ./configure and then make.
In the sample I have below, it checks to see if the configure script exists, and if it doesn't, it runs ./autogen.sh, a shell script that was included in the package that, in turn, runs Autoconf to regenerate the configure script.
Also notice that I passed --prefix=%{_prefix} to ./configure. That is so you can adjust whether you want the package installed in /usr, /opt, or /usr/local by changing the Prefix: line near the top of the .spec file.
In the %install script, you usually just run something like 'make install', but you have to somehow make it install to the directory pointed to by $RPM_BUILD_ROOT, that's where RPM will look for the files that it puts into the RPM package. In the sample I have below, I pass DESTDIR=$RPM_BUILD_ROOT. For Makefiles that are generated by Automake, DESTDIR overrides where it installs to.
Sample .spec file
%define name skstream
%define version 0.2.2
%define release 1
Summary: Portable C++ classes for IP(sockets) applications.
Name: %{name}
Version: %{version}
Release: %{release}
Source: ftp://ftp.worldforge.org/pub/worldforge/libs/%{name}-%{version}.tar.gz
Vendor: The WorldForge Project
URL: http://www.worldforge.org/
License: LGPL
Group: System Environment/Libraries
Prefix: %{_prefix}
%description
This library contains C++ utility classes for using IP(sockets).
%package devel
Summary: Libraries, includes to develop applications with %{name}.
Group: Development/Libraries
Requires: %{name} = %{version}
%description devel
The %{name}-devel package contains the header files and static libraries for
building applications which use %{name}.
%prep
%setup -q
%build
if [ -x ./configure ]; then
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix}
else
CFLAGS="$RPM_OPT_FLAGS" ./autogen.sh --prefix=%{_prefix}
fi
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%clean
rm -rf $RPM_BUILD_ROOT
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root)
%doc AUTHORS ChangeLog COPYING INSTALL NEWS README TODO
%{_prefix}/lib/lib*.so.*
%files devel
%defattr(-,root,root)
%doc AUTHORS ChangeLog COPYING INSTALL NEWS README TODO
%{_prefix}/bin/*-config
%{_prefix}/lib/lib*.a
%{_prefix}/lib/lib*.so
%{_prefix}/include/*
%{_prefix}/share/aclocal/*
%changelog
* Thu Mar 7 2002 T.R. Fullhart <kayos@kayos.org>
- First draft of the spec file
GNU Autotools is being widely adopted by open-source software, including the WorldForge Project, so that makes building RPM packages very easy. Basically, it's just like doing it from a tarball, but you can use autoconf to fill in some of the blanks in your .spec file so you don't have to maintain it very much between releases.
Sample .spec.in file
Change configure.in.
Rerun ./autogen.sh.
Run ./configure
Make a dist, make dist.
Put the sources and patches in the SOURCES directory and then run rpm -ba package.spec. Rpm will use the spec to figure out how to unpack and build the package and then it will dump a binary RPM in RPMS/i386 and a source RPM in SRPMS.
Or, if you have a tarball will a .spec file in it, run rpm -ta package.tar.gz. Rpm will extract the .spec file from the inside of the tarball, put the tarball in the SOURCES directory, and then it will start building just as above.
It's important that your RPM packages comply with certain conventions and standards because, hopefully, you want your package to work on a variety of systems. You can use a program called rpmlint to check your binary packages for commonly overlooked errors.
The configuration file of rpmlint is actually a small Python program to set some variables. You won't need to learn Python to configure rpmlint, it's fairly easy. You can find a bit of documentation with rpmlint, but here is what my ~/.rpmlintrc file looks like:
from Config import *
setOption("Vendor", "The WorldForge Project")
setOption("Packager", "T.R. Fullhart <kayos@kayos.org>")
setOption("Distribution", None)
[IBMRPM1] Packaging Software with RPM, Part 1.
[IBMRPM2] Packaging Software with RPM, Part 2.
[IBMRPM3] Packaging Software with RPM, Part 3.
[RPMHOWTO] RPM HOWTO: RPM at Idle.
[MAXRPM] Maximum RPM.