Fedora Compliant Packaging

This page describes how to craft an RPM specfile and build an RPM that will meet Fedora packaging conventions. Packaging conventions are largely documented on the Fedora web pages but this is an attempt to simplify and enhance that documentation into a step by step guide and to fill out some of the missing information. References will be made to Fedora documentation as necessary.

Making a package Fedora compliant is a good idea as it encourages many good practices. Hence it is good to follow these guidelines even if you are not intending to (or cannot due to licensing or content) submit the package for review and inclusion in the Fedora Everything repository. Initially building packages following these guidelines will take longer, but soon the steps will be second nature.

This document is aimed largely at users who have never packaged an RPM before, but there are plenty of compliance tips that will apply to advanced users of RPM.

Don't Reinvent the Wheel

Before building an RPM for a piece of software from scratch check first that nobody else has done the work for you, even if it was for a different distribution/architecture - a lot of the problems might already have been solved.

There are good places to look for existing RPMs for software - RPM Bone and RPM Find are two of note. Also it is worth checking the local Extras repository of SL5 (/pkgs/master/rpms/sl5/extras) and the Everything repository of Fedora 10 for example. Its also possible to look at Debian packages to inform the creation of an RPM so no harm checking if any of these exist for the software as well. Or even just searching for the software name in Google (with .src.rpm as an extra search term) can throw up something.

The rest of this document assumes you can't find anything in the wild and are building an RPM from scratch.

Create RPM Build Root

If you have not already done so you will need to create a build root for RPM.

    mkdir -p ~/RPM/{BUILD,RPMS,SPECS,SOURCES,SRPMS}

You will then need to create a ~/.rpmmacros file. A basic one for the build root created above would look like below.

    %_topdir        %(rpmroot)
    %_sourcedir     %{_topdir}/SOURCES
    %_rpmdir        %{_topdir}/RPMS
    %_specdir       %{_topdir}/SPECS
    %_srcrpmdir     %{_topdir}/SRPMS
    %_builddir      %{_topdir}/BUILD
    %_tmpdir        /tmp

You might also add stuff for signing and handling multiple architectures within the build root into this file but we won't bother covering that yet.

Finally you need to set an environment variable to point at your build root.

    export RPMROOT=~/RPM

Add the line above to your ~/.brc file to make sure it is set automatically every time you login. Source it now, . ~/.brc, before following any other instructions below.

Download Source

Now get the source archive for the package you are building. Won't say much about this because it varies from provider to provider. What you want to end up with is a .tar.gz (or .tgz or .zip etc) file containing the source code. This file should be put into the $RPMROOT/SOURCES directory.

You must be able to build the package from source for it to be Fedora compliant however this is not a requirement for packages solely for DICE as some of these have to be built from binaries (commercial software where it is not possible to obtain the source). See No inclusion of pre-built binaries or libraries for further details.

Create SPEC file

The SPEC file defines how to build an RPM package from the source. The SPEC file should be created in the $RPMROOT/SPECS directory. It will be called NAME.spec where NAME is the name of the package. In general this will be the same as the name on the source archive. It should not include any version or release code. It should all be in lowercase even if the source is in upper or mixed case (unless there is a very good reason for retaining the case). For example if the application we are building is called Wibble and the source file is wibble-1.23.tar.gz then the SPEC file will be wibble.spec, or if the package is WibbleFubar and the source file is Wibble-Fubar-1.23.tgz then the SPEC file will be wibble-fubar.spec. A summary of the basic naming rules are as follows.

  • use the same name as used on the upstream source archive
  • use lowercase letters only (unless there is a good reason to maintain upper or mixed case)
  • use dashes to separate name parts
  • the spec file for the package should have the same name as the package

There are of course exceptions (Perl packages being the most common one likely to be met where the mixed case naming is retained). For the full conventions on package naming see Packaging Naming Guidelines.

Now edit the SPEC file and create the package description and build instructions.

Name

Your package should be named appropriately. The first line in your SPEC file should be as below.

    Name:       wibble

This should match the same given for the base name of the SPEC file itself (ie. everything up to the .spec bit).

There are of course exceptions. For the full conventions on package naming see Packaging Naming Guidelines.

Version

The next line in your SPEC file should be the software version. This should be the same as on the source archive downloaded. In most cases this is easy, however if the version is non-numeric (this happens in the case of pre-release and post-release packages but also sometimes if the author has simply chosen to version their software in a strange way) then sometimes the letters in the version will need to be transferred to the Release: field (see next section). However, for wibble-1.23.tar.gz we would put the following in our SPEC file.

    Version:    1.23

See Version for the full conventions on the package version.

Release

The release of a package is the version associated with the SPEC file. Essentially it is for tracking when something has changed in the SPEC file and the corresponding RPM package but where the underlying source archive has not changed. This might be the addition of a local patch or modifications to build for different architectures. Where the release gets complicated is when it needs to encode information from the version in the original source archive (for letters indicating pre and post releases for example). We won't cover that here. For now all that needs to matter is that if you change something in the SPEC file after the package has been built and deployed then you should increase the release number. Initially however the next line in the SPEC file should look like below.

    Release:    1%{?dist}

So if we made a change this would be changed to 2{%dist}. Note that if the change was because a new version of the source was being built we would generally reset the release to 1.

Note the %{?dist} which automatically adds a distribution tag if one is set. You shouldn't need to worry about this just yet but it is good practice to include this.

A word about how our package will be named now that we have the Name, Version and Release defined. Once we have built the package we will get a binary RPM called wibble-1.23-1.i386.rpm which is NAME-VERSION-RELEASE.ARCH.rpm. If we produce a new release then we would get wibble-1.23-2.i386.rpm. If we then get the next version of the software we would get wibble-1.24-1.i386.rpm.

See Release for the full conventions on the package release, including handling pre/post releases.

Summary

This is a short one line (keep to less than 60 characters) description of the software the package contains. Usually this can simply be grabbed from the web site where the source archive was downloaded - the Home page or About page will usually have something snappy that can be used (alternatively look at the README file in the source archive itself). The line in the SPEC file should look like below. The summary line should not have a full stop at the end.

    Summary:    Ruling the World Management Toolset

See Summary and Description for the full conventions on this field.

Group

This is used to indicate roughly what the software is or does. The value for this field should in general be chosen from the list at /usr/share/doc/rpm-4.4.2/GROUPS, although this is getting old and only provides a coarse description. The line in the SPEC file should look like below.

    Group:      Applications/Productivity

In general the Applications/Productivity group is where a lot of packages will be categorized.

License

This can be a minefield! Your package must be suitably licensed. In general this means some form of open source license, such as GPL or BSD. If packaging software purely for DICE purposes this does not matter quite so much (although need to be careful that any EULA does not preclude local re-distribution of the software) other than perhaps affecting which bucket the packages should be submitted into once built. However, to build packages which will be Fedora compliant will require checking the licensing very carefully and making sure all of the files in the source archive comply with one or more of the supported ones. These must then exactly match the license(s) specified in the License field of the SPEC file. Ultimately for a lot of software the line in the SPEC file ends up pretty simple and will look like below.

    License:    GPLv2

although it might also be GPLv2+ or LGPL. Most software we use is licensed under the GNU Public License.

The License field essentially contains one (or more) tags identifying the licenses that the source archive has been distributed under. While this can often be found out by looking on the software web site ("this software is licensed under the GPL") this should not be treated as reliable - you must look at the content of the source archive itself. To do this manually extract the source somewhere and have a look inside.

    cd /tmp
    tar zxvf $RPMROOT/SOURCES/wibble-1.23.tar.gz
    cd wibble-1.23

Look for files indicating the license - there might be a COPYING file or LICENSE file at the top level, or maybe its mentioned in the README. That is your starting point. Every compilable source file and header file should include the license in comment at the top. Any installable script should include the license in comment at the top. Note that the source can easily have multiple licenses, for example where it includes copies of source from someone else under a different license. If so all the multiple licenses must be present with suitable comment in the License field in the SPEC file.

For full documentation on suitable licenses see Licensing and for how to record those in the SPEC file see Packaging Licensing Guidelines.

URL

This is the originating web site for the software. The line in the SPEC file should look like below.

    URL:        http://www.wibble.org/

Source

This is the URL to download the source archive (as ended up in $RPMROOT/SOURCES). To be Fedora compliant the source archive that is packaged must match the one obtained via this URL (checked by MD5 sum). The line in the SPEC file should look like below.

    Source0:    http://www.wibble.org/downloads/%{name}-%{version}.tar.gz

Note that we are using %{name} to expand to the value of the Name field in the SPEC file (wibble) and %{version} to expand to the value of the Version field in the SPEC file (1.23). Where possible this is the preferred way to do it (if you want to rebuild for a new version of the software you just need to change the Version field and not any other references to the version in the SPEC file). Sometimes the download URL naming makes this awkward (it might be wibble-123.tar.gz for example).

In certain cases it is not possible to specify a URL (the download site uses some re-direction and there is not an explicit named URL to refer to). For handling such situations see Packaging Source URL. Also refer to this if you downloaded the software from Sourceforge.

Sometimes a package will need to specify multiple sources. For example, the documentation may be distributed in a separate archive, there may be an ancillary program that needs to be built with the main program that is distributed separately or there may be a locally crafted startup script for the program. In all cases these are specified in the same way with an increasing number in the SourceN field. Some examples below.

    Source1:    http://www.wibble.org/downloads/%{name}-manual.pdf
    Source2:    wibble-startup.sh

As can be seen additional sources do not need to be source archives and in the case of a file or archive that is only distributed as part of the package being built it cannot be specified as a URL.

All the files or archives specified by URL or explicit name in the Source field must be present in the $RPMROOT/SOURCES directory in order to build the package. Download each one that is required and put them in that directory. Hand crafted files should be added into that directory as well.

BuildRoot

The package will be built in temporary space and the BuildRoot field defines how to constuct the temporary directory name. While there are a number of approved forms it is recommended the line in the SPEC file should look exactly like the one below.

    BuildRoot:  %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

See BuildRoot Tag for further details.

BuildRequires

This is a bit more fiddly. Basically this defines the packages that need to be installed on the machine in order to build the software. It won't be possible to get these details exactly right until the build is tried out under mock (see later) but a first pass is often possible. You need to look at the content of the README or INSTALL files in the source archive as they will hopefully describe any pre-requisite software (the originating web site is also likely to list anything non-standard thats needed). You will be looking for statements like "in order to build wibble make sure you have fubar installed" and "you will need wacko version 2.9 to build this software as version 2.7 won't cut it". In these cases the corresponding lines in the SPEC file would look like below.

    BuildRequires:  fubar
    BuildRequires:  wacko = 2.9

You can specify as many BuildRequires lines as you like. Each contains the name of the package and optionally an equals version string (or a ">= VERSION"). There are further forms we won't go into here as you are unlikely to need them. Note that you need to be careful to make sure the name specified matches the name of the package as found by RPM, for example by doing rpm -q fubar.

Not all build requirements need to be explicit, eg. things like gcc, make, etc. are assumed to be present (for a full list see Exceptions). For more details on build requirements see BuildRequires.

Often development packages are needed as build requirements that are not normally installed on DICE whereas the base package is. For example, lofty might be installed but lofty-devel might not and it is probably lofty-devel that you want in the BuildRequires field as that will contain libraries the software needs to be linked against when built. Once you have added the requirement to the SPEC file you can temporarily install the required package as root by doing rpm -i /pkgs/master/rpms/SL5/extras/lofty-devel-VERSION-RELEASE.i386.rpm. It will get uninstalled again overnight but it will be around for you to try out the build. If the package required is not in SL5/extras (or sometimes SL5/distro for -devel type packages) the chances are you will need to get an RPM from somewhere else (see earlier), and failing that get the source from somewhere else and follow this whole documented procedure for that package as well.

If there does not seem to be any mention of build requirements in the installation instructions in the source archive or on the originating web site just don't bother putting any in the SPEC file to start off with. It will probably just build on DICE or it may be that when you do the build you will get errors indicating any missing requirements.

Requires

Like BuildRequires except this describes additional software that is needed to run the application after it is built and installed. For example, an application may not need python installed to build it but needs it in order to run. Often there is some commonality between the two (a build requirement will also be a runtime requirement) in which case the required software package needs to be listed in both fields. Again its a case of looking at the installation documentation in the source archive or on the originating web site to see if any specific software is mentioned as a pre-requisite for running this software. If it is you will the need lines in the SPEC file would like below.

    Requires:       fubar
    Requires:       wacko = 2.9

The syntax is the same as for BuildRequires. Again, if there does not seem to be any mention of run time requirements in the installation instructions in the source archive or on the originating web site then just don't bother putting any in the SPEC file to start off with and see what happens.

Note that RPM actually works out most of the package runtime requirements itself when built (in particular for C/C++ libraries and Perl modules) so often you will not need to (and should not) add explicit Requires lines to the SPEC file. See Requires for further details.

Description

This is a multi line description of the software the package contains. Usually this can simply be grabbed from the web site where the source archive was downloaded - the Home page or About page will usually have a few paragraphs that can be used as-is or with minimal editing (alternatively look at the README file in the source archive itself). Note that lines in the description should be properly formatted and not wrap around the default terminal width (80 characters) without a newline. The lines in the SPEC file should look like below.

    %description
    A toolset useful to anyone that has ended up managing the world.
    Contains speeches and controls that can be used to manipulate
    any situation that might arise.

See Summary and Description for the full conventions on this field.

Prep and Setup

This part of the SPEC file defines how to extract the source(s) into a directory from which the software can be built. This directory will be in $RPMROOT/BUILD. The default behaviour is usually fine - this is where an archive wibble-1.23.tgz extracts into a single directory named after the software and version as in the earlier parts of the SPEC file definition, ie. wibble-1.23. In this case the setup would look like below.

    %prep
    %setup -q

You must have the -q argument for Fedora compliancy so setup extracts quietly. The above will automatically extract whatever Source0 is whether it is .tar.gz, .tgz or .zip extension on the assumption that it extracts to a directory name %{name}-%{version}. If it doesn't you can work around this easily enough by doing below.

    %prep
    %setup -q -n %{name}

Following the -n argument is the actual name the archive extracts to, in this case just the name as given in the SPEC file without the version. Another example - if Source0 was Wibble-1.23 and extracted to Wibble-Software-1.23 you would use %setup -q -n Wibble-Software-%{version}.

Another common scenario is where the archive does not extract into a single directory, instead all the files are created at the top level. In this case you need to create a suitable directory first. This is generally done as below.

    %prep
    %setup -q -c %{name}-%{version}

This results in a directory being created first (named %{name}-%{version} or wibble-1.23) and the archive is then extracted within that.

A final common scenario is when multiple sources are required. Sometimes the additional sources also need to be extracted. You can do this as follows.

    %prep
    %setup -q -a 1 -a 2

In the above Source0 is extracted as normal creating the parent directory which is then where Source1 with the -a 1 argument and Source2 with the -a 2 argument are then extracted.

Various other combinations and convolutions are possible but the above are the most common. Ultimately you can if necessary not use the %setup macro at all and do the extraction manually.

Build

This section of the SPEC file defines how to compile the source to produce binaries for installation. This section and the Install section following are the hardest to describe as they are the least procedurally defined, that is they depend very much on the actual source software. Some basic guidelines are given. All build sections should start like below.

   %build

Following that are standard shell commands to perform the build. The best place to find out what you need to do will be in the source archive itself, perhaps in the README file or in the INSTALL file. A common GNU style package would look something like below.

   %build
   ./configure --prefix=/usr
   make

At this point you may be better extracting the source manually somewhere else and trying to build it from the command line as instructed before bundling the sequence into the RPM SPEC file.

The most likely problems to hit with the build will be configuring the install locations to be suitable, over and above the software simply not building in a straightforward way on DICE. There may also be missing pre-requisite software not obviously listed that will need to be built, packaged and installed first.

Install

This step installs the built software into the build root defined earlier. This is like a mock root filesystem containing only files and directories that the software installs. All install sections should start like below.

   %install
   rm -rf %{buildroot}

This makes sure the software has an empty buildroot to install into and any previous builds will not interfere. See PreppingBuildRootForInstall.

After that depends on the software. Look at what the README or installation documentation says and copy the commands from that into the install section of the SPEC file. A very common (and simple) install section would look like below.

   %install
   rm -rf %{buildroot}
   make install DESTDIR=%{buildroot}

Software using standard GNU build tools is likely to just need something like the above. The make install would normally install the software into the real root filesystem so the DESTDIR argument tells it to install into the mock root filesystem instead.

Unfortunately plenty of software will not be like the above, it may not have an obvious way to redirect the installation to the mock root either - this will require looking at other possible arguments to the Makefile or potentially patching.

You can use any shell commands in the install section and so you can use this to do additional tweaking.

Clean

This step in the build process is done last and removes the temporary root directory the software has been installed into. It should generally consist of the following only.

    %clean
    rm -rf %{buildroot}

Files

This part of the SPEC file identifies all the files in the mock root directory that need to be packaged as part of the RPM - generally this is all of them, although taking care over directories. The best way to create this entry is to look at the content of the installed files before they are deleted. You can do this using rpmbuild -bi NAME.spec to process the RPM up to and including the install phase. Then have a look at the %{buildroot}. Files can also be taken directly from the build directory, this is usually the case for documentation and licensing information.

It is important that your RPM does not own directories other than what it creates itself. To see what this means imagine the RPM creates the following in the build root.

    %{buildroot}/usr/bin/wibble
    %{buildroot}/usr/share/wibble-1.23/data

In the above our RPM should own /usr/bin/wibble but not /usr/bin as that directory is common to many pieces of software and is actually created by another RPM. To find out what owns any particular directory on a system if you are not sure do rpm -qf /usr/bin for example - in summary if a directory exists already on your machine then the RPM should not be owning it as for the most part it must already be owned by an RPM (it might also be LCFG created). In the above our RPM should own the /usr/share/wibble-1.23 directory as that is specific to this software and it should own the /usr/share/wibble-1.23/data file but it should not own /usr/share as again that is common. The above would be written as follows in the SPEC file.

    %files
    %{_bindir}/wibble
    %{_datadir}/*

So this RPM contains the /usr/bin/wibble file from the mock root (but not its parent directory) and anything from the mock root that is within /usr/share but not /usr/share itself (or /usr/bin itself). Note the use of macros to expand to the full paths of installation directories, where possible these should be used as it is more portable (they are defined by RPM as standard to the system it is running on making the SPEC file more generic). A brief list is below.

    %{_bindir}        /usr/bin
    %{_libdir}        /usr/lib
    %{_includedir}    /usr/include
    %{_datadir}       /usr/share
    %{_sysconfigdir}  /etc

You can list all the macros RPM knows about using rpmbuild --showrc.

We could also have done the following.

    %files
    %{_bindir}/wibble
    %{_datadir}/wibble-1.23

Specifically identifying the directory in /usr/share (and all its content) we wanted included. The first form is more preferable as we don't have to change as much if a new version of the software adds /usr/share/wibble-data-1.23 for example (although we could in this instance have done %{_datadir}/wibble-%{version} to work around that).

Another common part of the file directive in the SPEC file is to define documentation. This is automatically installed into /usr/share/doc/NAME-VERSION and must include licensing information for Fedora compliancy. An example is shown below.

    %files
    %doc LICENSE README docs/html/*
    %{_bindir}/wibble
    %{_datadir}/wibble-1.23

Note that files referred to in the %doc line are found relative to the $RPMROOT/BUILD/NAME-VERSION directory, they are not installed in the mock root. The above %doc line would install the files below for example.

    /usr/share/doc/wibble-1.23/LICENSE
    /usr/share/doc/wibble-1.23/README
    /usr/share/doc/wibble-1.23/index.html
    /usr/share/doc/wibble-1.23/example1.html

where LICENSE and README were found in the top level of the build directory and index.html and example1.html were in the docs/html directory within that. Any licensing information in the source package must be included in this way.

For this example the final binary RPM would contain the following list of files and directories to install.

    /usr/bin/wibble
    /usr/share/wibble-1.23
    /usr/share/wibble-1.23/data
    /usr/share/wibble-1.23/data/r1
    /usr/share/wibble-1.23/data/r2
    /usr/share/doc/wibble-1.23
    /usr/share/doc/wibble-1.23/LICENSE
    /usr/share/doc/wibble-1.23/README
    /usr/share/doc/wibble-1.23/index.html
    /usr/share/doc/wibble-1.23/example1.html

Note importantly above that the binary RPM does not own/create/install /usr/bin, /usr/share or /usr/share/doc. If you did rpm -qf on each of those directories you would see they are already owned by another RPM and hence not something we should be concerned with in our own package (actually you will see that rather than these directories just being owned by the filesystem RPM you will see that they are also owned by a number of other naughty RPMs!).

Changelog

Every time you make a change to the SPEC file to reflect a new version of the source or a modification to the SPEC file itself (to fix a bug or add support for a new architecture for example) a changelog entry should be pre-pended to the %changelog section. Note that this is not necessary during package development but is once a package has been submitted/deployed and you want to submit/deploy the modified version. The first entry should look something like below.

    %changelog
    * Wed Nov 26 2008 Tim Colles <timc@inf.ed.ac.uk> - 1.2.3-1
    - initial attempt

There are various approved forms, but stick to the one above, ie. * DDD MMM DD YYYY FIRST LAST - VERSION-RELEASE, followed by on the next line one or more lines starting with a dash space for appropriate comment. If the package had been submitted/deployed and we wanted to do a new version the entry might look like below.

    %changelog
    * Thu Nov 27 2008 Tim Colles <timc@inf.ed.ac.uk> - 1.2.3-2
    - missing a startup script which has been added now
    - had to patch one of the source files to work properly

    * Wed Nov 26 2008 Tim Colles <timc@inf.ed.ac.uk> - 1.2.3-1
    - initial attempt

Keep a blank line between each distinct changelog entry and avoid line wrapping.

See Changelogs.

Building

With the SPEC file complete you are ready to try building the package. This is done within the $RPMROOT/SPECS directory as below.

    rpmbuild -ba wibble.spec

The above will produce screeds of output eventually (you hope) ending up with lines like the following.

    Wrote: /home/timc/RPM/SRPMS/wibble-1.23-1.src.rpm
    Wrote: /home/timc/RPM/RPMS/i386/wibble-1.23-1.i386.rpm

The first thing produced is the .src.rpm which contains everything necessary to rebuild the package anywhere else, so includes all the items referred to in Source lines and Patch lines as well as the SPEC file itself. You can check by doing rpm -qpl $RPMROOT/RPM/wibble-1.23-1.src.rpm. The second thing produced is the binary RPM which is what contains everything referred to in the %files section of the SPEC file and is what will be installed on the system when the package is used. You can do rpm -qpl on this as well to check the content is as expected.

Of course you may not get anything produced if there is a syntax error in your SPEC file, if the build process breaks in some way (note that the RPM environment is different from your own so if it works for you it doesn't mean it will work for rpmbuild), if the packaging breaks in some way (generally if the %files section is missing some files that were installed in the mock root or vice versa is referring to files not found in the mock root) or various other possible problems.

Testing

Next up would be to test the RPM installs and the programs it installs work. This can be quickly done on the machine you are building on. Do the following.

    nsu
    rpm -U $RPMROOT/RPMS/i386/wibble-1.23-1.i386.rpm

This will install (or upgrade) the RPM manually. This will be undone when updaterpms runs overnight or is run manually at any point. You can then check that the files installed by the RPM are in place and that the program(s) installed run as expected.

Checking

For Fedora compliance your package must be passed cleanly by rpmlint. To check for errors run rpmlint on the spec file .src.rpm and each .ARCH.rpm files. For example:

    rpmlint -iv $RPMROOT/SPECS/wibble.spec
    rpmlint -iv $RPMROOT/SRPMS/wibble-1.23-1.src.rpm
    rpmlint -iv $RPMROOT/RPMS/i386/wibble-1.23-1.i386.rpm

For help on rmplint error and warning messages see Common Rpmlint Errors.

Your package must also meet all the basic Fedora compliance guidelines. By following this document you should already be close however to be sure see Review Guidelines for a partial summary of requirements for Fedora compliance and cross check against your package.

Your package must build under the mock environment for Fedora compliance. This will also help identify any missing build requirements (as specified in BuildRequires in the SPEC file).

Need some instructions on using mock.

Submitting

The package can now be submitted for deployment. Submitting simply copies the source and binary RPMs into a central repository (and auto generates a header used by updaterpms).

    /usr/sbin/rpmsubmit -B world $RPMROOT/RPM/i386/wibble-1.23-1.i386.rpm

Submitting the binary RPM will automatically find the associated source RPM and submit that as well. Assuming your package is Fedora compliant (built from source and under an approved open source license) then the world bucket is always the place it should go. The other buckets, uoe and inf, are only used when the package licensing restricts deployment to within the University or within Informatics.

You can check the package submitted correctly by looking directly at the repository directory.

    ls -l /pkgs/master/rpms/sl5/world/wibble-1.23-1.i386.rpm
    ls -l /pkgs/master/rpms/sl5/world/.wibble-1.23-1.i386.rpm
    ls -l /pkgs/master/srpms/sl5/world/wibble-1.23-1.src.rpm

There is no simple command to remove packages once submitted, there is not normally a need to do so. It is however necessary/useful sometimes and can be done as below.

    nsu linux
    cd /pkgs/master/rpms/sl5/world/
    rm wibble-1.23-1.i386.rpm .wibble-1.23-1.i386.rpm
    cd /pkgs/master/srpms/sl5/world/
    rm wibble-1.23-1.src.rpm

Adding to DICE

The final step in deploying your package onto DICE is to edit one of the header files listing packages to install. These are in the LCFG Subversion repository. If you haven't already got a copy of this you can check one out as below.

    cd ~/
    svn checkout svn+ssh://lcfgsvn.inf.ed.ac.uk/svn/lcfg/core

Make sure the package lists are up to date before making any changes.

    cd ~/core/packages/dice
    svn update

Choose an appropriate header.

    dice_sl5_env.rpms
    dice_sl5_i386_rat_env.rpms
    dice_sl5_i386_teaching_and_research.rpms
    dice_sl5_i386_unsupported_env.rpms
    dice_sl5_rat_env.rpms
    dice_sl5_teaching_and_research.rpms
    dice_sl5_unsupported_env.rpms

This document is not at the moment concerned with building for multiple architectures so in general you will be editing dice_sl5_i386_teaching_and_research.rpms. Simply add your package at the bottom of the file with a suitable comment, something like below.

    wibble-1.23-1/i386                        /* Joe Bloggs, RT99999 */

Then commit your change.

    svn commit -m "added wibble for Joe" dice_sl5_i386_teaching_and_research.rpms

DICE machines on the develop release will have the package installed overnight, but most DICE machines won't get it until the next stable release. You can add it manually to any DICE machine not on the develop release in advance if necessary (when user needs it quickly) by adding the following into the machine profile.

    /* REMINDER: timc added package wibble until next stable 05/12/08 */
    !profile.packages        mEXTRA(wibble-1.23-1/i386)

On a develop machine or a machine with a modified profile above run om updaterpms run to install the package immediately.

Adding to Fedora

Ultimately the purpose of building a package to Fedora compliancy guidelines is that it can be pushed upstream into the Fedora Everything repository where it will be built automatically for all architectures and hopefully other people will help support it if it breaks or for when changes are needed for new versions of the source archive. However this process can only be carried out by timc and sxw at present (although anyone can take a package through the review process to get sponsored). So once you have built and deployed onto DICE what you believe to be a Fedora compliant package be sure to let one of us know so we can review it locally and push it upstream.

Advanced Fedora Compliant Packaging

Thats the basics. The following sections cover some slightly more advanced processes associated with package building.

Patching

Often the source will not build cleanly, or even if it does will not install cleanly. In these cases it is necessary to patch the software and keep a record of those patches as part of the package (the original source should never be modified directly). Patching creates a file recording the differences made to parts of the software to get it to work. This can be achieved as below, assuming that an rpmbuild -ba wibble.spec has been done and failed.

    cd $RPMROOT/BUILD/wibble-1.23
    cp abc.c abc.c.inf

Now edit abc.c.inf to make the changes that will get it to work.

    diff -Naur abc.c abc.c.inf > $RPMROOT/SOURCES/wibble-abc.patch

The above creates a patch file (differences between the original source and the modified source that works). This needs to be added into the SPEC file so that it is bundled with the source package. This is done by adding a PatchN line for each separate patch file after the %sourceN lines as below.

    Source0:    http://www.wibble.org/downloads/%{name}-%{version}.tar.gz
    # fix a problem with building with v2.9 of wacko
    Patch0:     %{name}-abc.patch

For Fedora compliance the PatchN line should ideally be preceeded by a comment stating that the problem has been reported to the upstream provider of the source (with a URL for a bug tracking page if the upstream provider has such a thing), however it should at least be preceeded by a comment stating what the patch is for. It is always worth pushing the patch upstream if the patch is likely to fix a problem other users might have, even if it is not a package we would normally consider pushing upstream to Fedora. The hope is that the upstream provider will include the patch in the software in a future release and the local patch can be dropped. See Patches for further details.

The patch must then be applied before the package is built and this is done in the %prep section as below.

    %prep
    %setup -q
    %patch0

The %patch0 refers to the particular patch file and runs the patch command to apply it automatically as part of the rpmbuild process. There are other options to the patch command to specify how to process the patch file, see man patch for more details.

It is possible to have a patch file for each modified file in the original source, however if the patch is common to a lot of files (i.e. it is the same change being made to more than one file) then it is common to have the changes to each file in a single patch file. This is achieved by doing a diff -Naur across two directories - one the original source directory and the other a copy of that with each file modified as necessary.

Architecture Exclusion

A Fedora compliant package must build on at least one supported architecture, but if it does not build on all architectures those on which it doesn't need to be explicitly excluded. This may be something you know beforehand (the README might say that the software won't work on 64bit machines) but often its the build using mock that will reveal any incompatibilities. These should be fixed if possible) but if not the broken architectures need to be excluded in the SPEC file as below.

    # Fails one test on ppc64 architecture
    ExcludeArch:    ppc64

Each excluded architecture line should be preceeded by a comment explaining why the architecture was excluded (failed to build). For exact compliance a bug report should be made for each broken architecture and the bug number included in the comment, see Review Guidelines.

Multiple Packages

Often it is preferable to build more than one binary package from a single SPEC file. A common use is to separate runtime components from development components (which would be in %{name}-devel instead) as a lot of users might only need to install the runtime package if they are running the software and not actually doing development work with the software. Another common use is to separate large chunks of documentation from the runtime components. Yet another common use is where the software consists of a number of modules, each of which may have different external software requirements and the user only actually needs to install one of the modules (and may not have or want to have the software installed to meet the requirements for other modules). There are some Fedora compliancy rules governing the naming of multiple packages for Documentation and Static Libraries. Defining additional packages in a SPEC file is done as below.

    %package devel
    Group:          Development/Libraries
    Summary:        Wibble Library - Development Files
    Requires:       %{name} = %{version}-%{release}

    %description devel
    Libraries to build against wibble.

Something like the above should be included for each sub-package. The %package devel line declares a new package to be created as part of the rpmbuild process, in this case it would be called %{name}-devel. The immediately following Group, Summary and Requires lines are identical to the corresponding lines for the base package but describe and refer to the sub-package instead (it is possible for other directives to be included for sub-packages as well, for example BuildRequires is quite common). Finally the following %description is again as for the base package but refers to the sub-package instead. Next the list of files needs to be defined for the sub-package, i.e. the %install stage must install everything into the mock root however some of these installed files need to be associated with the base package and some with, in this case, the devel sub-package). In the SPEC file this might look something like below.

    %files
    %doc LICENSE README docs/html/*
    %{_bindir}/wibble
    %{_datadir}/*

    %files devel
    %{_libdir}/*

So in the example files in the wibble binary package will be:

    /usr/bin/wibble
    /usr/share/wibble-1.23
    /usr/share/wibble-1.23/data
    /usr/share/wibble-1.23/data/r1
    /usr/share/wibble-1.23/data/r2
    /usr/share/doc/wibble-1.23
    /usr/share/doc/wibble-1.23/LICENSE
    /usr/share/doc/wibble-1.23/README
    /usr/share/doc/wibble-1.23/index.html
    /usr/share/doc/wibble-1.23/example1.html

and files in the wibble-devel binary package will be:

    /usr/lib/libwibble.so.1
    /usr/lib/libwibble.a

Running rpmbuild -ba wibble.spec will produce a source package and two binary packages, when its finished you should see something like below at the bottom of the output.

    Wrote: /home/timc/RPM/SRPMS/wibble-1.23-1.src.rpm
    Wrote: /home/timc/RPM/RPMS/i386/wibble-1.23-1.i386.rpm
    Wrote: /home/timc/RPM/RPMS/i386/wibble-devel-1.23-1.i386.rpm

The additional sub-package must be tested, checked and submitted in just the same way as for the base package.

Signing Packages

It is good practice to sign RPMs before submitting them into the repository (not least it means if the RPM master is compromised it vastly speeds up the package verification process). In order to do this you need to add something like the following lines to your ~/.rpmmacros file.

    %_signature     gpg
    %_gpg_path      /home/timc/.gnupg
    %_gpg_name      Tim Colles (Package Authority) <timc@inf.ed.ac.uk>
    %_gpgbin        /usr/bin/gpg

Then you can sign the binary and source RPM before submission as below.

    rpmsign --resign $RPMROOT/SRPMS/wibble-1.23-1.src.rpm
    rpmsign --resign $RPMROOT/RPMS/i386/wibble-1.23-1.i386.rpm

For this to work you will of course need to have setup keys with GPG - this is in the simplest case just done by running gpg --gen-key, choosing defaults at the prompts and entering a personal pass phrase. When asked for User-ID the real name, comments and email should match those given under %_gpg_name in the ~/.rpmmacros file above (in this case real name would be Tim Colles, comments would be Package Authority and email would be timc@inf.ed.ac.uk) - this ensures this particular key will be used for package signing by rpmsign. Then when you use rpmsign enter the same pass phrase when prompted to sign the package.

Fedora compliant packages that are being made available upstream in the Fedora repositories must be signed using the appropriate Fedora keys.

Further Resources

More details on Fedora compliant packaging can be found in the Packaging Guidelines including specific guidelines for application specific packages (packages for Perl, Python, R, Haskell etc).

-- TimColles - 12 Aug 2008

Topic revision: r8 - 09 Dec 2008 - 15:07:17 - TimColles
 
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback
This Wiki uses Cookies