How to create an RPM package

From FedoraProject

(Difference between revisions)
Jump to: navigation, search
(%install section)
(%files section)
Line 421: Line 421:
  
 
=== %files section ===
 
=== %files section ===
The %files section identifies what files and directories were added by the package - and thus, which files and directories are ''owned'' by the package.  Ownership is important - when you type "rpm -qif ''blah''",  you'll see who owns ''blah''.  This section is used when performing the ''bin'' stage, to determine which files are placed into each binary RPM file.
+
This section declares which files and directories are owned by the package, and thus which files and directories will be placed into the binary RPM.
  
 
==== %files Basics ====
 
==== %files Basics ====
  
The %files section normally begins with a %defattr line which sets the default file permissions. The format of this is %defattr(<file permissions>, <user>, <group>, <directory permissions>), that is, one can specify the permissions to apply to files and directories in the %files section. The fourth parameter is often omitted. Usually one uses %defattr(-,root,root,-), where "-" means "use the default permissions".
+
The <code>%defattr</code> set the default file permissions, and is often found at the start of the <code>%files</code> section. Note that this is no longer necessary unless the permissions need to be altered. The format of this is:
 +
%defattr(<file permissions>, <user>, <group>, <directory permissions>)
 +
The fourth parameter is often omitted. Usually one uses <code>%defattr(-,root,root,-)</code>, where "<code>-</code>" uses the default permissions.
  
This is followed by names or patterns of the directories or files to be installed and owned by this package. You should use macros for directory names, e.g., use %{_bindir}/myfile instead of /usr/bin/myfile, and %{_sbindir}/killaccount instead of /usr/sbin/killaccount. If a name or pattern begins with "/" when expanded, then it is presumed to have been copied into the %{buildroot} followed by that pattern; when installed on the final system, it will be copied into that name ''without'' the buildroot prefix.  If you don't precede the pattern with "/", then it is presumed to be in the current directory (e.g., inside the build directory) - this is used for "documentation" files. So if your package just installs /usr/sbin/mycommand, then your %files section ''could'' simply say:
+
You should then list all the files and directories to be owned by the package. Use macros for directory names where possible, which can be viewed at [[Packaging:RPMMacros]] (e.g. use <code>%{_bindir}/mycommand</code> instead of <code>/usr/bin/mycommand</code>). If the pattern begins with a "<code>/</code>" (or when expanded from the macro) then it is taken from the <code>%{buildroot}</code> directory. Otherwise, the file is presumed to be in the current directory (e.g. inside <code>%{_builddir}</code> (such as documentation files that you wish to include). If your package only installs a single file <code>/usr/sbin/mycommand</code>, then the <code>%files</code> section can simply be:
 
  %files
 
  %files
%defattr(-,root,root,-)
 
 
  %{_sbindir}/mycommand
 
  %{_sbindir}/mycommand
  
Any file or directory identified in the %files section is ''owned'' by the defining package. You should make sure that you declare ownership of every new file or directory the package creates.  You can use wildcards (*) which match a set of files - this makes the package less sensitive to changes. For example, you can declare that all the files that were copied into %{buildroot}/usr/bin are owned by this package by declaring:
+
To make your package less sensitive to upstream changes, declare all files within a directory to be owned by the package with a pattern match:
 
  %{_bindir}/*
 
  %{_bindir}/*
  
Note that "%{_bindir}/*" does not claim that this package owns the /usr/bin directory - it claims that all the files that were installed inside the ''build root'' 's /usr/bin are owned by the package.
+
To include a single directory:
If you list a ''directory'' in the %files section, then you are claiming that this package owns that subdirectory and all files and directories in it, recursively (''all'' the way down) if they are present in the build root.  Do not list the "/usr/bin" or "%{_bindir}" directories directly in your %files list, because that would claim ownership of /usr/bin and everything inside it.  Claiming ownership of "%{_bindir}/*" is fine, though; that just claims ownership of the subdirectories and files you placed ''under'' %{buildroot}/%{_bindir}.  If you create a subdirectory such as %{_datadir}/%{name}, (/usr/share/NAME), you ''should'' include that directory in the %files list:
+
 
  %{_datadir}/%{name}/
 
  %{_datadir}/%{name}/
  
It's usually easier to use wildcards for filenames, and that's also better at coping with changes in upstream.  Older RPM documentation typically shows long lists under %files with individual names, such as /usr/bin/program1 followed by /usr/bin/program2. Because of the way Fedora now uses buildroots, that is no longer necessary.
+
Note that <code>%{_bindir}/*</code> does not claim that this package owns the <code>/usr/bin</code> directory, but only the files contained within. If you list a directory, then you are claiming that the package owns that directory and all files and subdirectories contained within. Thus, do '''not''' list <code>%{_bindir}</code> and be careful of directories that may be shared with other packages.
  
It's an error if ''no'' file matches the wildcard of a line, so only note the directories that actually matter.  Also, you can't identify the same file or directory more than once.  Finally, it's an error to have something in the buildroot and ''not'' listed under %files; the whole point of copying something into the buildroot is because you intend to have it installed in the final system.  If you don't intend that, remove those files during the %install process.
+
An error will occur if:
 +
* a pattern match does not match any file or directory
 +
* a file or directory is listed or matched more than once
 +
* a file or directory in the <code>%{buildroot}</code> has not been listed
  
It is also possible to exclude files from a previous match by using a %exclude glob. This can be useful for including "almost all" of the files that match a different glob. However, note that, like any other file glob, even a %exclude glob will fail if it matches nothing. (This might be considered counterintuitive, as the whole point is essentially to ensure that a certain file ISN'T there, so this rule is especially important to remember.)
+
It is also possible to exclude files from a previous match by using the <code>%exclude</code> glob. This can be useful for including almost all of the files included by a different pattern match, but note that it will also fail if it does not match anything.
  
 
==== %files prefixes ====
 
==== %files prefixes ====
You may need to add one or more prefixes to a %files entry (if more than one, use a space to separate them).
+
You may need to add one or more prefixes to lines in the <code>%files</code> section; seperate them with a space. See [http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html Max RPM section on %files directives].
  
Typically there is a "%doc" entry with a list of documentation files that didn't get copied into the buildroot; usually there is at least a README and LICENSE file.  You ''must'' include the license file, if there is one. You may prefix some of these with %attr(mode, user, group) to set the file permission mode, user, or group.  You don't need to claim ownership of the /usr/share/doc/%{name} directory, that's automatic if there's a %doc entry.  Any %doc entry must not affect the runtime of the application (if it is in %doc, the program must run properly if it is not present).
+
Usually, "<code>%doc</code>" is used to list documentation files within <code>%{_builddir}</code> that were not copied to <code>%{buildroot}</code>. A <code>README</code> and <code>INSTALL</code> file is usually included. They will be placed in the directory <code>/usr/share/doc/%{name}-%{version}</code>, whose ownership does not need to be declared.
  
There is a potential 'gotcha' with %doc entries: if you have a %doc entry, then you can't use commands during %install to copy files into the documentation directory descending from %_defaultdocdir. That's because if there's a %doc entry, rpmbuild will automatically remove the docdir files created by %install before installing the files listed with %doc. This can hit you if, for example, you want an "examples" subdirectory in the documentation directory.  In this case, don't use "%doc" to mark documentation.  Instead, create the directories and copy the files into %{buildroot}%{_defaultdocdir}/%{name}-%{version}/ during %install, and make sure that %files includes an entry for "%{_defaultdocdir}/%{name}-%{version}/".  They will still be correctly marked as documentation.
+
'''Note:''' If specifying a <code>%doc</code> entry, then you can't copy files into the documentation directory during the <code>%install</code> section. If, for example, you want an "examples" subdirectory within the documentation directory, don't use <code>%doc</code>, but instead create the directories and copy files over manually into <code>%{buildroot}%{_defaultdocdir}/%{name}-%{version}</code> during the %install section. They will be correctly marked as documentation. Make sure you include <code>%{_defaultdocdir}/%{name}-%{version}/</code> as an entry in the %files section.
  
If you save configuration files (under /etc - don't put them under /usr), you should normally prefix them with %config(noreplace) unless this program version uses a non-backwards-compatible configuration format (in which case, prefix them with %config).
+
Configuration files should be placed in <code>/etc</code> and are normally specified like this (which makes sure user changes aren't overwritten on update):
 +
%config(noreplace) %{_sysconfdir}/foo.conf
 +
If the update uses a non-backwards-compatible configuration format, then specify them like this:
 +
%config %{_sysconfdir}/foo.conf
  
Prefixing a %files entry with "%attr(mode, user, group)" lets you set the permissions for particular file(s), e.g., "%attr(0644, root, root)".  A "-" means "use the default".
+
"<code>%attr(mode, user, group)</code>" can be used for finer control over permissions, where a "<code>-</code>" means use the default:
 +
%attr(0644, root, root) FOO.BAR
  
If a file is in particular natural language, use %lang to note that. E.G.:
+
If a file is in particular natural language, use <code>%lang</code> to note that:
 
  %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
 
  %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
  
Programs using Locale files should follow the
+
Programs using Locale files should follow the [[Packaging:Guidelines#Handling_Locale_Files|recommended method of handling i18n files]]:
[[Packaging:Guidelines#Handling_Locale_Files|recommended method of handling the i18n files]]:
+
 
+
 
* find the filenames in the <code>%install</code> step: <code> %find_lang ${name}</code>
 
* find the filenames in the <code>%install</code> step: <code> %find_lang ${name}</code>
 
* add the required build dependencies: <code>BuildRequires: gettext</code>
 
* add the required build dependencies: <code>BuildRequires: gettext</code>
 
* use the found filenames: <code>%files -f ${name}.lang</code>
 
* use the found filenames: <code>%files -f ${name}.lang</code>
  
Some documentation claims that %license and %readme are valid prefixes; they are ''not'' valid in Fedora.  Use %doc instead.
+
These prefixes are '''not''' valid in Fedora: <code>%license</code> and <code>%readme</code>.
  
 
==== %files and Filesystem Hierarchy Standard (FHS) ====
 
==== %files and Filesystem Hierarchy Standard (FHS) ====
  
You should follow the [http://www.pathname.com/fhs/ Filesystem Hierarchy Standard (FHS)], i.e., ordinary application executables go into /usr/bin, global configuration files go into /etc, ordinary libraries go into /usr/lib, and so on, with one exception: executables that should ''not'' normally be executed directly by users or administrators should go into a subdirectory of /usr/libexec; usually you'd refer to the necessary directory as "%{_libexecdir}/%{name}".
+
You should follow the [http://www.pathname.com/fhs/ Filesystem Hierarchy Standard (FHS)]. Executables go in <code>/usr/bin</code>, global configuration files go in <code>/etc</code>, libraries go into <code>/usr/lib</code> (or <code>/usr/lib64</code>) and so on. There is one exception: executables that should not normally be executed directly by users or administrators should go in a subdirectory of <code>/usr/libexec</code>, which is referred to as <code>%{_libexecdir}/%{name}</code>.
  
You shouldn't be installing files under /usr/local; that is where ''unpackaged'' files go.
+
Do '''not''' install files into <code>/opt</code> or <code>/usr/local</code>.
Typically there will be a "prefix" attribute that lets you set the prefix to be "/usr" instead of "/usr/local".
+
  
Unfortunately, many programs' "normal" installation routines do not follow the FHS.
+
Unfortunately, many programs do not follow the FHS by default. In particular, architecture-independent libraries get placed in <code>/usr/lib</code> instead of <code>/usr/share</code>. The former is for architecture-dependent libraries, while the latter is for architecture-independent libraries, which means that systems with different CPU architectures can share <code>/usr/share</code>. There are many exceptions in Fedora (such as Python and Perl), but Fedora applies this rule more strictly than some distributions. <code>rpmlint</code> will generally complain if you put anything other than ELF files into <code>/usr/lib</code>.
In particular, many programs normally place architecture-independent libraries under /usr/lib, instead of
+
under /usr/share as the FHS requires.
+
The [http://www.pathname.com/fhs/pub/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA FHS /usr/lib section] says that
+
/usr/lib is for architecture-''dependent'' data (e.g., ELF files like .so files), while
+
[http://www.pathname.com/fhs/pub/fhs-2.3.html#USRSHAREARCHITECTUREINDEPENDENTDATA /usr/share] is for
+
architecture-''independent'' data.  That way, systems with different CPUs can share /usr/share.
+
There are many exceptions to this rule in Fedora (e.g., Python and Perl), but Fedora applies this rule more
+
strictly than some distributions. Note, for example, that rpmlint will complain if you
+
put just about anything other than ELF files into /usr/lib.
+
  
 
==== %files example ====
 
==== %files example ====
Line 490: Line 485:
 
Here's a simple example of a %files section:
 
Here's a simple example of a %files section:
 
  %files
 
  %files
%defattr(-,root,root,-)
 
 
  %doc README LICENSE
 
  %doc README LICENSE
 
  %{_bindir}/*
 
  %{_bindir}/*
 
  %{_sbindir}/*
 
  %{_sbindir}/*
 
  %{_datadir}/%{name}/
 
  %{_datadir}/%{name}/
 +
%config(noreplace) %{_sysconfdir}/*.conf
  
 
==== Finding duplicates ====
 
==== Finding duplicates ====
 
The Fedora guidelines require that
 
"A Fedora package must not list a file more than once in the spec
 
file's %files listings."
 
  
 
You can list any duplicates of two binary packages by doing:
 
You can list any duplicates of two binary packages by doing:

Revision as of 15:19, 8 February 2012

Contents

Creating packages HOWTO

This page describes in detail how to create an RPM package, and in particular, how to create a SPEC file. Unlike other RPM guides, this page explains the specifics for Fedora with links to Fedora-specific guidelines. Since it is maintained through the Fedora Wiki, it is likely to be more up-to-date than other guides. Despite the focus on Fedora, most of this document does apply to other RPM-based distributions. If you're impatient, you might start by looking at the briefer How to create a GNU Hello RPM package.

This page gives some practical warnings on what will or will not work, which may save you hours of time later. Some topics are not discussed in depth, but links to more detailed documents are provided in these cases.

Please note that these are not the official package guidelines for Fedora, which can be viewed in the Packaging Guidelines and Package Naming Guidelines. Having said that, this page should be compatible with them.

If you plan to create an RPM package for the Fedora repository, follow the procedure for joining the package collection maintainers.

Setting up your system and account

Before you create RPM packages on Fedora, you need to install some core development tools and set up the account(s) you will use. As root user:

 # yum install @development-tools
 # yum install fedora-packager

You can create a dummy user specifically for creating RPM packages so that a build process gone wrong can't trash your files or send your private keys to the world.

Stop (medium size).png
You should never create your packages as the root user.

Create a new user named makerpm, set a password and login as that user:

 # /usr/sbin/useradd makerpm
 # passwd makerpm

Once you're logged in as the dummy user, create the required directory structure in your home directory by executing:

 $ rpmdev-setuptree

The rpmdev-setuptree program will create the ~/rpmbuild directory and a set of subdirectories (e.g. SPECS and BUILD), which you will use for creating your packages. The ~/.rpmmacros file is also created, which can be used for setting various options.

The packaging guidelines recommend preserving file timestamps; you can make this automatic if you use wget or curl to get the source files. If you use wget to get source files, add the text "timestamping = on" to ~/.wgetrc. If you use curl, add the text "-R" to ~/.curlrc.

You won't normally need to do these steps again.

The basics of building RPM packages

To create an RPM package, you will need to create a ".spec" text file that provides information about the software being packaged. You then run the rpmbuild command on the SPEC file, which will go through a series of steps to produce your packages.

Normally, you should place your original (pristine) sources, such as .tar.gz files from the original developers, into the ~/rpmbuild/SOURCES directory. Place your .spec file in the ~/rpmbuild/SPECS directory and name it "NAME.spec", where NAME is the base name of the package. To create both binary and source packages, change directory to ~/rpmbuild/SPECS and run:

$ rpmbuild -ba NAME.spec

When invoked this way, rpmbuild will read the .spec file and go through in order the stages listed below. Names beginning with % are predefined macros (see the next table down).

Stage Reads Writes Action
%prep %_sourcedir %_builddir This reads the sources and patches in the source directory %_sourcedir. It unpackages the sources to a subdirectory underneath the build directory %_builddir and applies the patches.
%build %_builddir %_builddir This compiles the files underneath the build directory %_builddir. This is often implemented by running some variation of "./configure && make".
%check %_builddir %_builddir Check that the software works properly. This is often implemented by running some variation of "make test". Many packages don't implement this stage.
%install %_builddir %_buildrootdir This reads the files underneath the build directory %_builddir and writes to a directory underneath the build root directory %_buildrootdir. The files that are written are the files that are supposed to be installed when the binary package is installed by an end-user. Beware of the weird terminology: The build root directory is not the same as the build directory. This is often implemented by running "make install".
bin %_buildrootdir %_rpmdir This reads the files underneath the build root directory %_buildrootdir to create binary RPM packages underneath the RPM directory %_rpmdir. Inside the RPM directory is a directory for each architecture, and a "noarch" directory for packages that apply to any architecture. These RPM files are the packages for users to install.
src %_sourcedir %_srcrpmdir This creates a source RPM package (.src.rpm) inside the source RPM directory %_srcrpmdir. These files are needed for reviewing and updating packages.


As you can tell, certain directories have certain purposes in rpmbuild. These are:

Macro Name Name Usually Purpose
%_specdir Specification directory ~/rpmbuild/SPECS RPM specifications (.spec) files
%_sourcedir Source directory ~/rpmbuild/SOURCES Pristine source package (e.g. tarballs) and patches
%_builddir Build directory ~/rpmbuild/BUILD Source files are unpacked and compiled in a subdirectory underneath this.
%_buildrootdir Build root directory ~/rpmbuild/BUILDROOT Files are installed under here during the %install stage.
%_rpmdir Binary RPM directory ~/rpmbuild/RPMS Binary RPMs are created and stored under here.
%_srcrpmdir Source RPM directory ~/rpmbuild/SRPMS Source RPMs are created and stored here.

If a stage fails, look at the output to see why it falied and change the .spec file (or other input) as needed.

Getting ready to package a particular program

If there are special programs that are required to build or run the program you are packaging, install those other programs and write down what they are.

To package a program for the Fedora repository, you must package pristine (original) sources, along with the patches and build instructions; it's not okay to start with pre-compiled code. Install the file with the original source (usually a .tar.gz file) in the ~/rpmbuild/SOURCES directory (of the RPM building user account).

Read through the manual installation instructions for your program. It's often a good idea to do a "dry run" by manually building the program before attempting to do so via RPM, especially if you're unfamiliar with RPM. With a few exceptions, all program binaries and program libraries included in Fedora packages must be built from the source code that is included in the source package.

Split up the program

Application source code is often released with the source code of other external libraries "bundled" into them. Do not bundle external libraries with the main application into a single package. Instead, split them up into separate packages.

Licensing

Only package software that is legal for you to package.

As noted in the packaging guidelines' legal section, if you intend for it to be in the Fedora repository, be sure to follow Licensing:Main and Packaging:LicensingGuidelines. In general, you need to only package software that is released as open source software (OSS) using an approved OSS license (such as the GNU GPL, GNU LGPL, BSD-new, MIT/X, or Apache 2.0 licenses). Check to make sure that the software really is licensed this way (e.g. spot-check source code headers, README files, and so on). If there are bundled libraries, make sure they are also OSS.

Reuse existing package information

Try to reuse what you can. Obviously, make sure you aren't packaging something that is already packaged; you can find a list of existing packages in Fedora Package Collection in the Fedora Package Database. Also check the In Progress Review Requests for packages that are currently being reviewed and the Retired Packages list. Failing that, see if someone has already started to package it for Fedora. Google for "PROGRAMNAME Fedora rpm" or similar and maybe you can pick up where they started. You can use Fedora Packages Git Repositories directly to view .spec files (and patches) of any similar packages already in Fedora. You can download the source RPMs using a program from the yum-utils package, by: Note:You may have to install yum-utils before execute yumdownloader

$ yum -y install yum-utils
$ yumdownloader --source sourcepackage-name

Alternatively, get the source manually from the http/ftp page of a Fedora mirror within the releases/16/Everything/source/SRPMS directory. Replace "16" with the Fedora release you want and download the .src.rpm package you want.

Once you have the SRPM, running the following command installs the SRPM into ~/rpmbuild:

$ rpm -ivh sourcepackage-name*.src.rpm

You can also unpack the SRPM into a directory using rpm2cpio:

$ mkdir PROGRAMNAME_src_rpm
$ cd PROGRAMNAME_src_rpm
$ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i

Sometimes it's easiest to start with an existing package and then clean it up for Fedora. RPM Find may help you find RPMs for non-Fedora systems. You can install SRPMs for other systems the same way as for Fedora. Failing that, you might look at the source package files (not binary .deb) for Ubuntu or Debian (source package files are standard tarballs with a "debian/" subdirectory). If the FreeBSD ports collection has it, you could download the FreeBSD ports tarball and see if their packaging information helps as a starting point. However, this is sometimes not helpful at all. Different distributions have different rules, and what they do may be quite inappropriate for Fedora.

Creating a spec file

You now need to create a SPEC file in the ~/rpmbuild/SPECS directory. You should name it after the program name (e.g. "program.spec"). Use the archive name or the name advocated by the software author where you can, but be sure to follow the Package Naming Guidelines.

Creating a blank spec file

When you're creating a SPEC file for the first time, vim (as of 7.1.270-1) or emacs will automatically create a template for you:

 $ cd ~/rpmbuild/SPECS
 $ vim program.spec

Here's an example of what that template will look like:

Name:		
Version:	
Release:	1%{?dist}
Summary:	
Group:		
License:	
URL:		
Source0:	
BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

BuildRequires:	
Requires:	

%description

%prep
%setup -q

%build
%configure
make %{?_smp_mflags}

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

%clean
rm -rf %{buildroot}

%files
%defattr(-,root,root,-)
%doc

%changelog


You can use $RPM_BUILD_ROOT instead of %{buildroot}. Both are acceptable, but just be consistent.

You may also use the rpmdev-newspec command to create a SPEC file for you. rpmdev-newspec NAME-OF-NEW-PACKAGE can create an initial SPEC file for a new package, tailored to various types of packages. It will guess what kind of template to use based on the package name, or you can specify a particular template; see /etc/rpmdevtools/spectemplate-*.spec for available templates. See rpmdev-newspec --help for more information. For example, to create a new SPEC file for a python module:

cd ~/rpmbuild/SPECS
rpmdev-newspec python-antigravity
vi python-antigravity.spec

An example: eject

Here's a simple example showing a Fedora 9 SPEC file for the eject program:

Summary: A program that ejects removable media using software control
Name: eject
Version: 2.1.5
Release: 11%{dist}
License: GPL
Group: System Environment/Base
Source: http://metalab.unc.edu/pub/Linux/utils/disk-management/%{name}-%{version}.tar.gz
Source1: eject.pam
Patch1: eject-2.1.1-verbose.patch
Patch2: eject-timeout.patch
Patch3: eject-2.1.5-opendevice.patch
Patch4: eject-2.1.5-spaces.patch
Patch5: eject-2.1.5-lock.patch
Patch6: eject-2.1.5-umount.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
URL: http://www.pobox.com/~tranter
ExcludeArch: s390 s390x
BuildRequires: gettext
BuildRequires: automake
BuildRequires: autoconf
BuildRequires: libtool

%description
The eject program allows the user to eject removable media (typically
CD-ROMs, floppy disks or Iomega Jaz or Zip disks) using software
control. Eject can also control some multi-disk CD changers and even
some devices' auto-eject features.

Install eject if you'd like to eject removable media using software
control.

%prep
%setup -q -n %{name}
%patch1 -p1 -b .versbose
%patch2 -p1 -b .timeout
%patch3 -p0 -b .opendevice
%patch4 -p0 -b .spaces
%patch5 -p0 -b .lock
%patch6 -p1 -b .umount

%build
%configure
make

%install
rm -rf %{buildroot}

make DESTDIR=%{buildroot} install

# pam stuff
install -m 755 -d %{buildroot}/%{_sysconfdir}/pam.d
install -m 644 %{SOURCE1} %{buildroot}/%{_sysconfdir}/pam.d/%{name}
install -m 755 -d %{buildroot}/%{_sysconfdir}/security/console.apps/
echo "FALLBACK=true" > %{buildroot}/%{_sysconfdir}/security/console.apps/%{name}

install -m 755 -d %{buildroot}/%{_sbindir}
pushd %{buildroot}/%{_bindir}
mv eject ../sbin
ln -s consolehelper eject
popd

%find_lang %{name}

%clean
rm -rf %{buildroot}

%files -f %{name}.lang
%defattr(-,root,root)
%doc README TODO COPYING ChangeLog
%attr(644,root,root) %{_sysconfdir}/security/console.apps/*
%attr(644,root,root) %{_sysconfdir}/pam.d/*
%{_bindir}/*
%{_sbindir}/*
%{_mandir}/man1/*

%changelog
* Wed Apr 02 2008 Zdenek Prikryl <zprikryl at, redhat.com> 2.1.5-11
- Added check if device is hotpluggable
- Resolves #438610

SPEC file pieces explained

Other useful guides:

You will need to follow the Fedora guidelines: Package Naming Guidelines, Packaging guidelines, and Package review guidelines.

Insert comments with a leading '#' character, but avoid macros (beginning with %) that are potentially multiline (as they are expanded first). If commenting out a line, double the percent signs (%%). Also avoid inline comments on the same line as a script command.

The major tags are listed below. Note that the macros %{name}, %{version} and %{release} can be used to refer to the Name, Version and Release tags respectively. When you change the tag, the macros automatically update to use the new value.

  • Name: The (base) name of the package, which should match the SPEC file name. It must follow the Package Naming Guidelines and in most cases be lowercase.
  • Version: The upstream version number. See Version tag section of the packaging guidelines. If the version contains tags that are non-numeric (contains tags that are not numbers), you may need to include the additional non-numeric characters in the Release tag. If upstream uses full dates to distinguish versions, consider using version numbers of the form yy.mm[dd] (e.g. 2008-05-01 becomes 8.05).
  • Release: The initial value should normally be 1%{?dist}. Increment the number every time you release a new package for the same version of software. When a new upstream version is released, change the Version tag to match and reset the Release number to 1. See Release tag section of the packaging guidelines. Dist tag describes the optional "dist" tag that might be useful.
  • Summary: A brief, one-line summary of the package. Use American English, and do not end in a period.
  • Group: This needs to be a pre-existing group, like "Applications/Engineering"; run "less /usr/share/doc/rpm-*/GROUPS" to see the complete list. Use the group "Documentation" for any sub-packages (e.g. kernel-doc) containing documentation.
  • License: The license, which must be an open source software license. Do not use the old "Copyright" tag. Use a standard abbreviation (e.g. "GPLv2+") and be specific (e.g. use "GPLv2+" for GPL version 2 or greater instead of just "GPL" or "GPLv2" where it's true). See Licensing and the Licensing Guidelines. You can list multiple licenses by combining them with "and" and "or" (e.g. "GPLv2 and BSD").
  • URL: The full URL for more information about the program (e.g. the project website). Note: This is not where the original source code came from which is meant for the "Source0" tag below.
  • Source0: The full URL for the compressed archive containing the (original) pristine source code, as upstream released it. "Source" is synonymous with "Source0". If you give a full URL (and you should), its basename will be used when looking in the SOURCES directory. If possible, embed %{name} and %{version}, so that changes to either will go to the right place. Preserve timestamps when downloading source files. If there is more than one source, name them Source1, Source2 and so on. If you're adding whole new files in addition to the pristine sources, list them as sources after the pristine sources. A copy of each of these sources will be included in any SRPM you create, unless you specifically direct otherwise. See Source URL for more information on special cases (e.g. revision control).
  • Patch0: The name of the first patch to apply to the source code. If you need to patch the files after they've been uncompressed, you should edit the files and save their differences as a "patch" file in your ~/rpmbuild/SOURCES directory. Patches should make only one logical change each, so it's quite possible to have multiple patch files.
  • BuildArch: If you're packaging files that are architecture-independent (e.g. shell scripts, data files), then add "BuildArch: noarch". The architecture for the binary RPM will then be "noarch".
  • BuildRoot: This is where files will be "installed" during the "%install" process (after the "%build" process). This is a macro that creates a new special directory under /var/tmp; in Fedora it generally does not need to be changed. Newer versions of RPM will ignore this value and instead place the build root in "%{_topdir}/BUILDROOT/".
  • BuildRequires: A comma-separated list of packages required for building (compiling) the program. This field can be (and is commonly) repeated on multiple lines. These dependencies are not automatically determined, so you need to include everything needed to build the program. Some common packages can be omitted, such as gcc. You can specify a minimum version if necessary (e.g. "ocaml >= 3.08"). If you need the file /EGGS, determine the package that owns it by running "rpm -qf /EGGS". If you need the program EGGS, determine the package that owns it by running "rpm -qf `which EGGS`". Keep dependencies to a minimum (e.g. use sed instead of perl if you don't really need perl's abilities), but beware that some applications permanently disable functions if the associated dependency is not present; in those cases you may need to include the additional packages. The "auto-br-rpmbuild" command may be helpful.
  • Requires: A comma-separate list of packages that are required when the program is installed. Note that the BuildRequires tag lists what is required to build the binary RPM, while the Requires tag lists what is required when installing/running the program; a package may be in one list or in both. In many cases, rpmbuild automatically detects dependencies so the Requires tag is not always necessary. However, you may wish to highlight some specific packages as being required, or they may not be automatically detected.
  • %description: A longer, multi-line description of the program. Use American English. All lines must be 80 characters or less. Blank lines indicate a new paragraph. Some graphical user interface installation programs will reformat paragraphs; lines that start with whitespace will be treated as preformatted text and displayed as is, normally with a fixed-width font. See RPM Guide.
  • %prep: Script commands to "prepare" the program (e.g. to uncompress it) so that it will be ready for building. Typically this is just "%setup -q"; a common variation is "%setup -q -n NAME" if the source file unpacks into NAME. See the "%prep" section below for more.
  • %build: Script commands to "build" the program (e.g. to compile it) and get it ready for installing. The program should come with instructions on how to do this. See the "%build" section below for more.
  • %check: Script commands to "test" the program. This is run between the "%build" and "%install" procedures, so place it there if you have this section. Often it simply contains "make test" or "make check". This is separated from "%build" so that people can skip the self-test if they desire.
  • %install: Script commands to "install" the program. The commands should copy the files from the BUILD directory %{_builddir} into the buildroot directory, %{buildroot}. See the "%install" section below for more.
  • %clean: Instructions to clean out the build root. Typically this contains only:
rm -rf %{buildroot}
  • %files: The list of files that will be installed. See the "%files" section below for more.
  • %changelog: Changes in the package. Use the format example above.
  • ExcludeArch: If the package does not successfully compile, build or work on a particular architecture, list those architectures under this tag.
  • You can add sections so that code will run when packages are installed or removed on the real system (as opposed to just running the "%install" script, which only does a pseudo-install to the build root). These are called "scriptlets", and they are usually used to update the running system with information from the package. See the "Scriptlets" section below for more.

RPM also supports the creation of several packages (called subpackages) from a single SPEC file, such as name-libs and name-devel packages.

Do not use these tags:

  • Packager
  • Vendor
  • Copyright

Do not create a "relocatable" package; they don't add value in Fedora and make things more complicated.

 %prep section

The %prep section describes how to unpack the compressed packages so that they can be built. Typically, this includes the "%setup" and "%patch" commands with reference to the Source0 (and Source1 etc.) lines. See the Maximum RPM section on %setup and %patch for more details.

The %{patches} and %{sources} macros are available since RPM 4.4.2 and are useful if you have a large list of patches or sources:

for p in %{patches}; do
    ...
done

However, keep in mind that using these will make your SPEC incompatible with RPMS used in RHEL and other RPM-based dirstributions.

 %prep section: %setup command

The "%setup" command unpacks a source package. Switches include:

  • -q : Suppress unecessary output. This is commonly used.
  • -n name : If the Source tarball unpacks into a directory whose name is not the RPM name, this switch can be used to specify the correct directory name. For example, if the tarball unpacks into the directory FOO, use "</code>%setup -q -n FOO</code>".
  • -c name : If the Source tarball unpacks into multiple directories instead of a single directory, this switch can be used to create a directory named name and then unpack into it.

There are more %spec options if you are unpacking multiple files, which is primarily useful if you are creating subpackages (see below). The key ones are:

-a number Only unpack the Source directive of the given number after changing directory (e.g. "–a 0" for Source0).
-b number Only unpack the Source directive of the given number before changing directory (e.g. "–b 0" for Source0).
-D Do not delete the directory before unpacking.
-T Disable the automatic unpacking of the archives.

 %prep section: %patch commands

The "%patch0" command applies Patch0 (and %patch1 applies Patch1 etc.). Patches are the normal method of making necessary changes to the source code for packaging. The usual "-pNUMBER" option applies, which passes that argument onto the program patch.

Patch file names often look like "telnet-0.17-env.patch", which is the format %{name} - %{version} - REASON.patch" (though sometimes version is omitted). Patch files are typically the result of "diff -u"; if you do this from the subdirectory of ~/rpmbuild/BUILD then you won't have to specify a -p level later.

This is a typical procedure for creating a patch for a single file:

cp foo/bar foo/bar.orig
vim foo/bar
diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch

If editing many files, one easy method is to copy the whole subdirectory underneath BUILD and then do subdirectory diffs. After you have changed directory to "~rpmbuild/BUILD/NAME", do the following:

cp -pr ./ ../PACKAGENAME.orig/
... many edits ...
diff -u ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/NAME.REASON.patch

If you edit many files in one patch, you can also copy the original files using some consistent ending such as ".orig" before editing them. Then, you can use "gendiff" (in the rpm-build package) to create a patch with the differences.

Try to ensure that your patch match the context exactly. The default "fuzz" value is "0", requiring matches to be exact. You can work around this by adding "%global _default_patch_fuzz 2" to revert to the value found in older versions of RPM in Fedora, but it is generally recommended to avoid doing this.

As explained in Packaging/PatchUpstreamStatus, all patches should have a comment above them in the SPEC file about their upstream status. This should document the upstream bug/email that includes it (including the date). If it is unique to Fedora, you should mention why it is unique. The Fedora Project tries not to deviate from upstream; see PackageMaintainers/WhyUpstream for the importance of this.

 %prep section: Unmodified files

Sometimes, one or more of the Source files do not need to be uncompressed. You can "prep" those into the build directory like this (where SOURCE1 refers to the relevant Source file):

cp -p %SOURCE1 .

 %build section

The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.

Many programs follow the GNU configure approach (or some variation). By default, they will install to a prefix of "/usr/local", which is reasonable for unpackaged files. However, since you are packaging it, change the prefix to "/usr". Libraries should be installed to either /usr/lib or /usr/lib64 depending on the architecture.

Since GNU configure is so common, the macro "%configure" can be used to automatically invoke the correct options (e.g. change the prefix to /usr). Some variation of this often works:

 %configure
 make %{?_smp_mflags}

To override makefile variables, pass them as parameters to make:

make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}

More more information, see "GNU autoconf, automake, and libtool" and "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer.

Some programs use cmake. See Packaging/cmake.

 %check section

If self-tests are available, it is generally a good idea to include them. They should be placed in the %check section (which immediately follows the %build section) instead of within the %build section itself, so that they can be easily skipped when necessary.

Often, this section contains:

make test

 %install section

This section involves script commands to "install" the program, copying the relevant files from %{_builddir} to %{buildroot} (which usually means from ~/rpmbuild/BUILD to ~/rpmbuild/BUILDROOT) and creating directories inside %{buildroot} as necessary.

Some of the terminology can be misleading:

  • The "build directory", also known as %{_builddir} is not the same as the "build root", also known as %{buildroot}. Compilation occurs in the former directory, while files to be packaged are copied from the former to the latter.
  • During the %build section, the current directory will start at %{buildsubdir}, which is the subdirectory within %{_builddir} that was created during %prep stage. This is usually something like ~/rpmbuild/BUILD/%{name}-%{version}.
  • The %install section is not run when the binary RPM package is installed by the end-user, but is only run when creating a package.

Normally, some variation of "make install" is performed here:

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

Removal of %{buildroot} is no longer necessary, except for EPEL 5.

Ideally you should use DESTDIR=%{buildroot} if the program supports it, as it redirects file installations to the specified directory and is exactly what we want to happen during the %install section.

If the program does not support DESTDIR (and only if), you can workaround it in one of several (inferior) ways:

  • Patch the makefile so that is supports DESTDIR. Create directories inside DESTDIR where necessary and submit the patch upstream.
  • Use the "%makeinstall" macro. This method might work, but can lead to subtle failures. It expands to something like "make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install", which can result in some programs failing to work properly. Create directories inside %{buildroot} where necessary.
  • Consider using the auto-destdir package. This requires "BuildRequires: auto-destdir", and changing "make install" to "make-redir DESTDIR=%{buildroot} install". This only works well if the installation uses only certain common commands to install files, like cp and install.
  • Perform the installation by hand. This would involve creating the necessary directories under %{buildroot} and copying files from %{_builddir} to %{buildroot}. Be especially careful with updates, which often contain new or changed filenames. An example of this procedure:
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{_bindir}/
cp -p mycommand %{buildroot}%{_bindir}/

As noted in Packaging:Guidelines#Timestamps, try to preserve timestamps if the makefile lets you override commands:

make INSTALL="install -p" CP="cp -p" DESTDIR=%{buildroot} install

 %files section

This section declares which files and directories are owned by the package, and thus which files and directories will be placed into the binary RPM.

 %files Basics

The %defattr set the default file permissions, and is often found at the start of the %files section. Note that this is no longer necessary unless the permissions need to be altered. The format of this is:

%defattr(<file permissions>, <user>, <group>, <directory permissions>)

The fourth parameter is often omitted. Usually one uses %defattr(-,root,root,-), where "-" uses the default permissions.

You should then list all the files and directories to be owned by the package. Use macros for directory names where possible, which can be viewed at Packaging:RPMMacros (e.g. use %{_bindir}/mycommand instead of /usr/bin/mycommand). If the pattern begins with a "/" (or when expanded from the macro) then it is taken from the %{buildroot} directory. Otherwise, the file is presumed to be in the current directory (e.g. inside %{_builddir} (such as documentation files that you wish to include). If your package only installs a single file /usr/sbin/mycommand, then the %files section can simply be:

%files
%{_sbindir}/mycommand

To make your package less sensitive to upstream changes, declare all files within a directory to be owned by the package with a pattern match:

%{_bindir}/*

To include a single directory:

%{_datadir}/%{name}/

Note that %{_bindir}/* does not claim that this package owns the /usr/bin directory, but only the files contained within. If you list a directory, then you are claiming that the package owns that directory and all files and subdirectories contained within. Thus, do not list %{_bindir} and be careful of directories that may be shared with other packages.

An error will occur if:

  • a pattern match does not match any file or directory
  • a file or directory is listed or matched more than once
  • a file or directory in the %{buildroot} has not been listed

It is also possible to exclude files from a previous match by using the %exclude glob. This can be useful for including almost all of the files included by a different pattern match, but note that it will also fail if it does not match anything.

 %files prefixes

You may need to add one or more prefixes to lines in the %files section; seperate them with a space. See Max RPM section on %files directives.

Usually, "%doc" is used to list documentation files within %{_builddir} that were not copied to %{buildroot}. A README and INSTALL file is usually included. They will be placed in the directory /usr/share/doc/%{name}-%{version}, whose ownership does not need to be declared.

Note: If specifying a %doc entry, then you can't copy files into the documentation directory during the %install section. If, for example, you want an "examples" subdirectory within the documentation directory, don't use %doc, but instead create the directories and copy files over manually into %{buildroot}%{_defaultdocdir}/%{name}-%{version} during the %install section. They will be correctly marked as documentation. Make sure you include %{_defaultdocdir}/%{name}-%{version}/ as an entry in the %files section.

Configuration files should be placed in /etc and are normally specified like this (which makes sure user changes aren't overwritten on update):

%config(noreplace) %{_sysconfdir}/foo.conf

If the update uses a non-backwards-compatible configuration format, then specify them like this:

%config %{_sysconfdir}/foo.conf

"%attr(mode, user, group)" can be used for finer control over permissions, where a "-" means use the default:

%attr(0644, root, root) FOO.BAR

If a file is in particular natural language, use %lang to note that:

%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*

Programs using Locale files should follow the recommended method of handling i18n files:

  • find the filenames in the %install step:  %find_lang ${name}
  • add the required build dependencies: BuildRequires: gettext
  • use the found filenames: %files -f ${name}.lang

These prefixes are not valid in Fedora: %license and %readme.

 %files and Filesystem Hierarchy Standard (FHS)

You should follow the Filesystem Hierarchy Standard (FHS). Executables go in /usr/bin, global configuration files go in /etc, libraries go into /usr/lib (or /usr/lib64) and so on. There is one exception: executables that should not normally be executed directly by users or administrators should go in a subdirectory of /usr/libexec, which is referred to as %{_libexecdir}/%{name}.

Do not install files into /opt or /usr/local.

Unfortunately, many programs do not follow the FHS by default. In particular, architecture-independent libraries get placed in /usr/lib instead of /usr/share. The former is for architecture-dependent libraries, while the latter is for architecture-independent libraries, which means that systems with different CPU architectures can share /usr/share. There are many exceptions in Fedora (such as Python and Perl), but Fedora applies this rule more strictly than some distributions. rpmlint will generally complain if you put anything other than ELF files into /usr/lib.

 %files example

Here's a simple example of a %files section:

%files
%doc README LICENSE
%{_bindir}/*
%{_sbindir}/*
%{_datadir}/%{name}/
%config(noreplace) %{_sysconfdir}/*.conf

Finding duplicates

You can list any duplicates of two binary packages by doing:

cd ~/rpmbuild/RPMS/ARCH # Substitute "ARCH" for your architecture
rpm -qlp PACKAGE1.*.rpm | sort > ,1
rpm -qlp PACKAGE2.*.rpm | sort > ,2
comm -12 ,1 ,2

Scriptlets

You can add sections so that code will run when packages are installed or removed on the real system (as opposed to just running the %install script, which only does a pseudo-install to the build root). These are called "scriptlets", and they are usually used to update the running system with information from the package.

The scriptlets in %pre and %post are run before and after a package is installed (respectively). The scriptlets %preun and %postun are run before and after a package is uninstalled. The scriptlets %pretrans and %posttrans are run at start and end of a transaction. See Packaging/ScriptletSnippets for more examples and details. For example, every binary RPM package which stores shared library files (not just symlinks) in any of the dynamic linker's default paths, must call ldconfig in %post and %postun (post-install and post-uninstall). If the package has multiple subpackages with libraries, each subpackage should also have a %post/%postun section that calls /sbin/ldconfig. For example:

%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig

Beware: The "-p" option specifies what command processor to use for the commands on the following lines. If there are no following lines, then using /sbin/ldconfig as the "command processor" is a minor efficiency improvement compared to putting "/sbin/ldconfig" on the next line, and letting the shell invoke it. That's because by using "-p", the shell isn't invoked simply to invoke a single program. But if you have multiple shell commands, don't use "-p" or /sbin/ldconfig after it! Instead, leave it blank, and include the shell commands under it.

If you are going to run programs in scriptlets, they must be installed before you run them. You have to use special variants of the "Requires:" tag, so that the program will be installed before you try to use it. These are of the form "Requires(CONTEXT):", e.g., "Requires(post)".

Most scriptlets (%pre, %post, %preun, and %postun) provide an argument you can use, accessed via $1, which is the number of packages of this name which will be left on the system when the action completes. Don't compare for equality with 2; check if they are greater than or equal than 2, since users can arrange to have multiple versions of a package installed simultaneously. For %pretrans and %posttrans, $1 is always 0.

For example, after adding an info manual to the system the dir file which indexes the info manuals should be updated. Basically, after you install the info manual, you need to run the program install-info. That's fine, except that install-info is part of package info, and there's no guarantee that info is installed unless we require it. Also, if "install-info" fails, we don't want to fail all processing. Here's one way to do that:

Requires(post): info
Requires(preun): info
...
%post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
%preun
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi

There is another glitch related to installing info files. The install-info command will update the info directory, but we have to prevent the install of a useless, empty directory file from the RPM_BUILD_ROOT environment, by deleting it in the %install section:

rm -f $RPM_BUILD_ROOT%{_infodir}/dir

Another scriptlet-like abilility are triggers. You can define triggers for when other packages are installed or uninstalled. See Maximum RPM for more information about triggers.

Macros

Spec files may contain "macro" references (text beginning with "%"), which are replaced with other values. You can follow % by a word, e.g., "%name", but just like shell variables you must bracket the name with {...} if letters or digits immediately follow, e.g., "%{name}".

As noted in the Packaging Guidelines, There are two styles for referring some values such as the rpm Build Root and Optimization Flags:

  • "macro style": %{buildroot}, %{optflags}
  • "variable style": $RPM_BUILD_ROOT, $RPM_OPT_FLAGS

Pick a style and use it consistently throughout your packaging; this document uses "macro style".

Here are some typical macros:

Macro Typical Expansion Meaning
 %{_bindir} /usr/bin Binary directory (where executables are usually stored)
 %{_builddir} ~/rpmbuild/BUILD Build directory; files are compiled a subdirectory of the build directory. See %buildsubdir.
 %{buildroot} ~/rpmbuild/BUILDROOT Build root, where files are "installed" during %install. The %install stage copies files from a subdirectory of %{_builddir} to a subdirectory of %{buildroot}. Historically %{buildroot} was in "/var/tmp/".
 %{buildsubdir}  %{_builddir}/%{name} Build subdirectory, where files are compiled during %build. It's under %{_builddir}, set after %setup.
 %{_datadir} /usr/share Share directory.
 %{_defaultdocdir} /usr/share/doc Default documentation directory.
 %{dist} .fcNUMBER Distribution+version short name (e.g., ".fc9")
 %{fedora} NUMBER Number of fedora release (e.g., 9)
 %{_includedir} /usr/include
 %{_infodir} /usr/share/info
 %{_initrddir} /etc/rc.d/init.d
 %{_libdir} /usr/lib
 %{_libexecdir} /usr/libexec
 %{_localstatedir} /var
 %{_mandir} /usr/share/man
 %{name} Name of package, set by Name: tag
 %{_sbindir} /usr/sbin
 %{_sharedstatedir} /var/lib
 %{_sysconfdir} /etc
 %{version} Version of package, set by Version: tag

To see more about macros you can look in /etc/rpm/* and the "macros" files under "/usr/lib/rpm/", especially /usr/lib/rpm/macros. You can also use "rpm --showrc" to show the values rpm will use for all of the options currently set in rpmrc and macro configuration files.

You can set your own macro values using %global; be sure to define them before you use them. Macro definitions can refer to other macros. For example:

%global myvalue 50

You can use rpmbuild to find the value of some macro, using its "-E" (--eval) option. For example, to find the current expansion of %{_bindir} in myfile.spec, you can run:

rpmbuild -E '%{_bindir}' myfile.spec

Packaging/RPMMacros has more information on macros, as does RPM Guide chapter 9.

Other tags

We noted the "Requires" and "BuildRequires" tags earlier. There are a few other tags for controlling dependencies: Provides, Obsoletes, Conflicts, and BuildConflicts.

  • "Provides:" lets you list virtual package names that this package provides. Sometimes there are several different packages that can provide a function, and using packages won't care which one. In that case, each of the packages that provide the function should "provide" a virtual package, and then using packages can list the virtual package name under "Requires:". For example, several different packages might provide "latex"; if you depend on the virtual package "tex(latex)", then users can choose which package to get "latex" from. If you provide virtual packages, you might also want to use the "alternatives" system, but be careful: "alternatives" settings are system-wide, so if multiple users on the same system might want different defaults, don't use the alternatives system. You can find out what a given package provides (both virtual and non-virtual names) by querying "rpm -q --provides PACKAGENAME". Some virtual packages in Fedora are:
    • MTA : Used for mail transport agents, such as sendmail.
    • tex(latex) : Used for latex
  • "Obsoletes:" lets you state that installing this package should (normally) cause the removal of the other named package(s). This is useful when a package's name changes, or when a package wholly replaces a different package.
  • "Conflicts:" lets you state what packages cannot be installed simultaneously this one. Obviously, try to avoid this if you can; see Packaging/Conflicts if you think you need to use it.
  • "BuildConflicts:" lets you state what packages cannot be installed when building this package. Obviously, try to avoid this if you can.

You can control which architectures a package builds (or doesn't build). For example, if your package can't compile on ppc, you can do this:

ExcludeArch: ppc

There's also an "ExclusiveArch" tag. The valid architectures one can specify in these tags are listed in the Architectures section.

Subpackages

A spec file can define more than one binary package, e.g., client and server, or runtime and developer packages. If there's a large amount of documentation, it may be split into a NAME-doc subpackage. You will always have one spec file and one source RPM (SRPM), even if there are multiple binary RPMs that they generate. A spec file that produces multiple binary packages still has only one creation process, so there is only one %prep, %build, %check, and %install section that creates all the files for all the packages.

In a spec file, use the %package directive to start defining a subpackage:

%package sub_package_name

By default, the subpackage name is PACKAGE_NAME, "-", SUBPACKAGE_NAME; you can use "-n" to override this and make a new name:

%package -n new_sub_package_name

After the %package directive, list the tags for the subpackage. This should include at least the "Summary:" and "Group:" tags and directives "%description SUBPACKAGE_NAME" and "%files SUBPACKAGE_NAME". Anything not specified by the subpackage will be inherited from its parent. For the directives, if you used "-n" with %package, you'll need it again for these directives. You need to specify the name for the other directives, e.g., %pre and %post, if you use them in the subpackage.

See the RPM Guide section on subpackages for more information.

Conditionals

You can insert conditional statements. E.G., you can test if you are creating a binary for a certain architecture with:

%ifarch ARCHITECTURE_NAME

the negated version with:

%ifnarch ARCHITECTURE_NAME

or the more general conditional:

%if TRUE_OR_FALSE

There is an optional "%else" section; all of these are closed with "%endif".

Application Specific Guidelines

There are many application-specific guidelines that can help you (e.g., for specific programming languages, applications, libraries, and build systems). Many of them are listed as part of the Application Specific Guidelines of Packaging/Guidelines. Examples of application-specific guidelines are those for:

Failing that, some other ways of finding application-specific help are:

Miscellaneous hints

Try to write your scripts so that when upstream makes changes, the packaging is likely to work when you change the version number and reload the source file(s). For example, if it contains *.txt files with execute bits, instead of doing:

 chmod a-x Filename1.txt Filename2.txt Filename3.txt

consider doing this, which will handle new filenames that use the same file naming convention:

 chmod a-x *.txt

If you want to see lots of examples of scriptlets, you can show all the scriptlets on installed programs using:

 rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less

Packaging/FrequentlyMadeMistakes has information on frequently-made mistakes.

Don't try to interact with the user; RPM is designed to support batch installs. If an application needs to show a EULA, that needs to be part of its initial execution, not its installation.

You might not want to start services, because in a big install that could slow things down. If you install an init script, consider using chkconfig to arrange for the service to be started and stopped on the next reboot. Before uninstalling you should normally try to stop its services if it's running.

Uninstall should reverse most changes made during installation, but don't remove any user-created files.

Normally, if there are binary executables, a separate "debug" package is created with the symbols, and the symbols are stripped from the normal binary packages. If this shouldn't happen, you can disable the package-creation and stripping with:

%global _enable_debug_package 0
%global debug_package %{nil}
%global __os_install_post /usr/lib/rpm/brp-compress %{nil}

To prevent stripping you may also need to do this in the %install section:

export DONT_STRIP=1

A way to check for the version of Fedora in a spec file for conditional builds is:

%if 0%{?fedora} <= <version>

(The ? causes the macro to evaluate to blank if %fedora is not defined, and this causes the end result to be "0", which is a number and thus ok, while not interfering with the result if there is actually a value for %fedora.)

Note that the previous trick DOES NOT work in Koji "scratch" builds - %fedora is set during the creation of a source RPM. (Thus, this trick does work in actual Koji builds as the system extracts sources from the source RPM and rebuilds the source RPM with the appropriate %fedora value.)

There are also some recommendations and controversial tricks on PackageMaintainers/Packaging Tricks.

GUI programs must have a desktop entry (so that people can invoke it from a graphical menu). The Fedora packaging guidelines discuss desktop files. See also the desktop entry spec (for .desktop files) and icon theme spec (for icon-related materials such as those in /usr/share/icon).

Older RPM documents

Some older documents about RPM have the most information, but some older documents make claims that are no longer true:

  • rpm files are no longer placed in a shared /usr/src/redhat directory. This is an obsolete way of using rpm and not recommended; modern systems set a %{_topdir} instead like ~/rpmbuild.
  • the %install process does not install files in their final location. Instead, it "installs" files to the buildroot.
  • The "rpm" command no longer creates packages (e.g., "rpm -ba" was once legal). Use the separate "rpmbuild" program instead.
  • Many historical specs use the "%define" command to define macros. However, "%define" creates a locally defined submacro within other macro definitions; this is very rarely needed, and using %define incorrectly can cause subtle bugs. For nearly all uses, use "%global" instead. (See PackagingDrafts/global_preferred_over_define.)
  • The "BuildRoot:" value is now ignored.

Quick test with rpmlint

Before trying to build anything from it, you should run rpmlint on the spec file:

$ rpmlint program.spec

This will catch many errors early. If the reported error doesn't make sense, run it again with the "-i" option (this gives longer messages).

Generally, you should not have errors from rpmlint, but sometimes rpmlint is excessively noisy. The Fedora packaging guidelines explain which ones to ignore, e.g., ignore "no-packager-tag" and "no-signature" errors.

Creating RPMs from the spec file

Once you've create a spec file, say "program.spec", you can create source and binary RPMs by simply running this:

 $ rpmbuild -ba program.spec

If this works, then your binary RPM files will be created underneath ~/rpmbuild/RPMS/ and the source RPM will be in ~/rpmbuild/SRPMS.

When things go wrong, you can "cd" into the appropriate directory and see what's left over. If you want to skip earlier stages, use the "--short-circuit" option; this is handy if you had a successful build, but have an error in the %install section. For example, to restart at the %install stage (skipping earlier stages), do this:

 $ rpmbuild -bi --short-circuit program.spec

If you just want to create a source RPM (.src.rpm), do this in the SPECS directory:

rpmbuild -bs program.spec

This will create the source RPM in ~/rpmbuild/SRPMS. Creating only a source rpm (.src.rpm) is quite quick, because rpm simply needs to copy the .spec file and associated SOURCES files into a .src.rpm file. Creating a binary rpm typically takes much longer, because this requires running the %prep, %build, and %install scripts.

Testing RPMs you've built (including rpmlint)

Run rpmlint on the .spec files, generated binary RPM, and generated source RPM. Rpmlint works on .spec files, binary RPMs, and source RPMs, finding different things in each. You need to eliminate or justify rpmlint warnings before posting a package. If you are in the SPECS directory, do this:

$ rpmlint NAME.spec ../RPMS/*/NAME*.rpm ../SRPMS/NAME*.rpm

Normally rpmbuild will build a binary RPM with debugging information - this will handle that.

If you "cd" to the "~/rpmbuild/RPMS" directory, and then cd to the architecture subdirectory, you'll find some binary rpms. You can quickly see their files and their permissions by using rpmls (check to see that they are what you expect):

$ rpmls *.rpm

If those look okay, you can become root and try to install them:

# rpm -ivp XYZ1.rpm XYZ2.rpm XYZ3.rpm ...

Then, you can test them out. Use it a few different ways and see if it works correctly. If it's a GUI tool, make sure it shows up in the menu (if it doesn't, something is wrong with your .desktop entry).

You can uninstall packages later using:

# rpm -e XYZ1 XYZ2 XYZ3

If that works, you can use Mock to do a more rigorous test that you have accurate build dependencies. Basically, mock will create a nearly-empty environment and try to rebuild the package; if it fails, then you forgot to list something in a "BuildRequires:" statement. See Using Mock to test package builds for more information about how to use Mock; once your account is a member of the "mock" group, you can run commands like this to do local testing:

$ mock -r fedora-9-i386 rebuild path_to_source_RPM

If a mock build fails, or the resulting program doesn't work correctly, then you almost certainly have one or more missing BuildRequires packages.

Once Mock works on your system, you can use Koji (which uses Mock) to do builds on many different systems, some of which you may not have. PackageMaintainers/Join and PackageMaintainers/UsingKoji have more information about Koji. Once it's set up, you can test your source RPM on a variety of platforms by running commands like:

$ koji build --scratch dist-f9 path_to_source_RPM

You can replace dist-f9 with dist-f8, dist-f10, etc., to try other releases. Don't use "dist-rawhide", that's not really rawhide. Remember, the values of %fedora, %fc9, etc., will not be correct for a scratch build, so this won't work if your spec file does something different based on those values.

Your koji builds can only depend on packages that are actually in the TARGET distribution repository. Thus, you can't use koji to build for released distributions if your package depends on other new packages that Bodhi hasn't released yet. You can use koji to build for rawhide (the next unreleased version), even if it depends on other new packages, as long as the other packages were built in the CVS "devel" section as described below. If you need to build against a package that is not yet a stable released update, you can file a ticket with rel-eng at: https://fedorahosted.org/rel-eng/newticket and request that that package be added as a buildroot override.

Helpful tools

The "rpmdevtools" package has a number of helpful tools; "rpm -qil rpmdevtools" will show you what it installs. One particularly useful tool is rpmdev-bumpspec, which has this form:

rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES

rpmdev-bumpspec will bump the release tag in the spec file(s), and add a changelog comment with the right datetime and version format. COMMENT should typically start with "- ".

Similarly, "yum-utils" has a number of yum-specific tools. "yumdownloader" is especially helpful; you can download the source RPM of a package by simply running "yumdownloader --source PACKAGENAME". You can then use "rpm -U SOURCEPACKAGENAME" to install the source files. E.G., "yumdownloader --source glib; rpm -Uvh glib*.src.rpm".

The auto-buildrequires package has a pair of nice tools for helping to figure out the proper BuildRequires entries. After installing this package, replace "rpmbuild" with "auto-br-rpmbuild" and you'll see an automatically-generated buildrequires list.

You might find RUST useful (GPL). It is "a drag & drop RPM creation GUI and a 'sandboxing' toolkit that allows you to do software installations within a chrooted environment and automatically generate RPMs from arbitrary source code, without ever seeing a spec file." If you're creating spec files, it can help you determine the %files. Note, however, that it does not create .spec files, nor does it create packages of adequate quality for the Fedora repository; it is primarily a tool for making quick-and-dirty binary RPM packages. (Note: it is no longer at "rusthq.com".)

Alien converts between package formats. It won't produce clean source RPMs, but converting an existing package might provide helpful information.

Guidelines and rules

When you create your packages, you'll need to follow the following rules and guidelines:

There are many official guidelines that will help you with specific circumstances (Java programs, OCaml programs, GNOME programs, etc.); the Packaging Guidelines include cross-references to those guidelines. You can also learn more from the SIGs and Package Maintainers sections. You can also see the list of all Wiki pages about Packaging to see if any apply.

Failing that, you might find some useful recommendations in the unofficial Packaging Drafts and Packaging Drafts To Do. These are unofficial, obviously. You might find ideas from SuSE, Debian, but distributions differ in their rules, so do not presume they can be used directly.

The .spec files that you create must be open source software, as noted in the CLA.

Maintaining the package

Once your package is accepted, you (or your co-maintainers) need to maintain it. See the Package update HOWTO and Package update guidelines for more information. If you update the version in multiple releases of Fedora, do it "backwards" in time, e.g., release for Fedora N, then once that's accepted, Fedora N-1 (the system presumes that later versions of Fedora have the same or later versions of programs).

Encourage the upstream developers to use standard source code release conventions. Using standard conventions makes packaging much easier. For more information, see:

For more information

The Package Maintainers page links to many other useful pages, and the Package update HOWTO describes how to update an existing package you already maintain in Fedora.

For more information, outside of the Fedora Wiki, see:

Note: The rpm5.org site has some documentation, but do not depend on it; that is the home of a fork of RPM maintained by Jeff Johnson. The RPM used by Fedora (and Novell/SuSE) is instead based at rpm.org. lwn.net has a brief article about this.