From Fedora Project Wiki

(→‎For more information: Add a link to the "fedora developer portal")
(365 intermediate revisions by 72 users not shown)
Line 1: Line 1:
== Creating Package HOWTO ==
{{autolang|base=yes}}
{{DISPLAYTITLE:Creating RPM Packages with Fedora}}


This page describes the basic mechanics of how to create an RPM package specifically for Fedora (such as
{{admon/note|This document is under construction to better conform to the packaging guidelines and to use {{package|fedpkg}} instead of rpmbuild throughoutWe apologize for any conflicting or confusing information while these changes are underway.}}
how to create a .spec file).  It also gives some practical warnings about stuff that will or won't work, which may save you hours of time later.
This is ''not'' the list of official package guidelines for Fedora (though it ''should'' be compatible with them).
This doesn't go into depth on some issues, but it does point to other documents that doUnlike many RPM Howto documents, this document explains the specifics for Fedora (with lots
of links to Fedora-specific guidelines) and it tends to be
more up-to-date (because it is maintained through the Fedora Wiki).


If you plan to create an RPM package for the Fedora repository, follow the process for
<div style="float: right; margin-left: 0.5em;" class="toclimit-2">__TOC__</div>
[[PackageMaintainers/Join|How to join the Fedora Package Collection Maintainers]],
including following the various Fedora guidance.


Nearly all Linux distributions can install and uninstall programs as "packages".
== Introduction ==
Fedora, and many other Linux distributions, use the "RPM" format for packages.
There are tools that make it easy to create RPM packages. The main task is to write
a ".spec" file that explains to RPM how to build and install the program.
This page describes how to create RPM packages specifically for Fedora, concentrating
on that very important ".spec" file.


== Setting up your system and account ==
This page describes in detail how to create an RPM package, and in particular how to create a specfile. Unlike other RPM guides, this page explains the specifics for Fedora with links to Fedora-specific guidelines and usage of Fedora-specific utilities. Despite the focus on Fedora, much of this document does apply to other RPM-based distributions.


Before you create RPM packages on Fedora, you need to install some core
Fedora Documentation had released a draft guide for packagers, see [http://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide Packagers Guide]. It is archived.
development tools and set up the account(s) you will use. As root (don't type the "#"!):
  # yum groupinstall "Development Tools"
  # yum install rpmdevtools


You can create a new "dummy user" specifically for
Please note that this document is merely a gentle introduction and will leave out many of the details which you may need in order to package more complicated softwareIt also assumes that you have familiarity with the shell and are familiar with the process of building and installing (outside of RPM) the software you wish to package. Finally, this document is '''NOT''' an official Fedora packaging guideline. This page is open for editing by the general Fedora packaging community, while the actual packaging guidelines are managed by the [[Packaging:Committee|Packaging Committee]]. For reference, here are some of the most referenced guideline pages:
creating rpm packagesThat way, if something goes terribly wrong, the
program or build process can't trash your files, or
send your private files/keys to the world. At the very least,
you should ''never'' create your packages as user root.


You can create a new user named "makerpm" quickly by doing:
* [[Packaging:Guidelines|Packaging Guidelines]]
  # /usr/sbin/useradd makerpm
* [[Packaging:LicensingGuidelines |Licensing Guidelines]]
Then log in as that special dummy user (makerpm).
* [[Packaging:Naming| Package Naming Guidelines]]
* [[Packaging:DistTag| Dist Tag Guidelines]]
* [[Packaging:ReviewGuidelines| Package Review Guidelines]]
* [[Packaging:Scriptlets| Recipes for RPM scriptlets]]


Once you're logged in as the user who is creating packages,
[[Packaging:Guidelines]] and [[Packaging:Naming]] contain the main guidelines.  Having said that, this page should be compatible with them, though the guidelines do change over time and this page may diverge from them on occasion.
create the directory structure in your home directory by executing (don't type the "$"):
  $ rpmdev-setuptree


The "rpmdev-setuptree" program will create an "rpmbuild" directory in your $HOME
If you plan to submit a package to the official Fedora repository, you will also want to follow the procedure depicted in [[Join the package collection maintainers]].
directory. Underneath "rpmbuild" are a set of subdirectories
(such as SPECS and BUILD), which you will use for creating your packages.
The "rpmdev-setuptree" also creates an "~/.rpmmacros" file which will cause
rpm and rpmbuild to use them when appropriate.


Once you've set up the user account, you won't normally need
=== Some terminology ===
to do these steps again.


== Getting ready to package a particular program ==
; RPM
: The package manager used by Fedora, Red Hat Enterprise Linux, Mageia, OpenSUSE and others.  Originally RPM stood for "Red Hat Package Manager" but now it's just the recursive acronym "RPM Package Manager".


If there are special programs that are required to build or run the program you are packaging, install those
; specfile
other programs and write down what they were (you'll need that information).
: A plain text file containing information about a package and instructions used by RPM for actually compiling the included software.  It is named by appending <code>.spec</code> to the name of the package.


To package a program, you ''must'' package pristine (original) sources, along
; tag
with the patches and build instructions.
: A string, generally capitalized and followed by a colon, which appears at the top of the specfile to provide some important data about the RPM, such as <code>Name:</code>, <code>Version:</code> or <code>Summary:</code>.
It's generally ''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;
; section
you're going to be automating this by editing a ".spec" file, so you have
: A segment of the specfile which tells RPM how to perform some portion of the package construction process. Many, but not all, sections contain code that is simply passed to the shell, though RPM has significant flexibility around this which will not be covered at all in this document.
to understand what you're supposed to do first.
It's probably best if you try a "dry run", going through its installation
procedure without trying to do it via RPM first
(that's especially true if you're not familiar with RPM).


Try to reuse what you can.
; section header
Obviously, make sure you aren't packaging something that is already packaged;
: A short string, starting with <code>%</code> at the beginning of a line, which introduces a section. Examples include <code>%description</code>, <code>%prep</code> and <code>%files</code>.  
you can find a list of existing packages in Fedora Package Collection in the [https://admin.fedoraproject.org/pkgdb/packages/ Fedora Package Database].
Also check the [[PackageMaintainers/InProgressReviewRequests | In Progress Review Requests]] (for packages that are currently being reviewed)
and the [[PackageMaintainers/RetiredPackages | Retired Packages]] list.
Failing that, see if someone has already started to package it for Fedora.
Google for "PROGRAMNAME Fedora rpm" or similar... maybe you can pick up where
they started.
You can use
http://cvs.fedoraproject.org/viewcvs/rpms/
directly view .spec files (and patches) of any similar packages already in Fedora.
You can download the source RPMs and install them, too;
go to a [http://mirrors.fedoraproject.org/publiclist Fedora mirror]'s http or ftp page,
select releases/9/Everything/source/SRPMS
(replace "9" with the Fedora release you want),
and download the source RPMs you want (they end in .src.rpm).
If you followed the directions above, you can install the source RPM
(which places its .spec file into ~/rpmbuild/SPECS and source files in ~/rpmbuild/SOURCES)
by running:
$ rpm -ivh PROGRAMNAME-*.src.rpm


You can also unpack the .src.rpm in a directory using rpm2cpio:
; macro
  $ mkdir PROGRAMNAME_src_rpm
: A short string, always prefixed by <code>%</code> and generally surrounded by curly brackets (<code>{}</code>) which RPM will convert to a different and usually longer string.  Some macros can take arguments and some can be quite complex.  Some macros are provided by RPM, some are part of {{package|redhat-rpm-config}} and {{package|fedora-rpm-macros}}, but many other packages also provide them.  If you're curious, running <code>rpm --showrc</code> will show you all of the macros currently available on your system, but note that you really don't want to use most of the ones you see there. Note that some macros have named prefixed by underscores; the reasons for this are mostly lost to time.
  $ cd PROGRAMNAME_src_rpm
: The packaging guidelines have various [[Packaging:Guidelines#Macros|suggestions and restrictions]] regarding the use of various sets of macros. This document will use what the guidelines recommend, but won't necessarily explain the reasons in detail.
$ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i
: You may, in looking at other packages, see macros used without curly brackets. There are situations where this isn't strictly necessary, but these guidelines will use them wherever possible to make it more obvious when macros are being used and to avoid going into the rules about when the brackets are needed and when they aren't.


''Sometimes'' it's easiest to start with an existing package, and then clean it up for Fedora.
; mock
[http://rpmfind.net/ RPM Find] may help you find rpm's for non-Fedora systems.
: A system for building RPMs within their own separate small Fedora installation. This avoids the need to have a full set of build dependencies installed into your regular operating system installation, allows you to build packages for different Fedora releases, and in general is a good thing.
(You can install source RPMs for other systems the same way as for Fedora).
Failing that, you might look at the source package files (not the .deb binary package files)
for [http://packages.ubuntu.com/ Ubuntu] or
[http://www.debian.org/distrib/packages Debian]
(source package files are standard tarballs with a "debian/" subdirectory, possibly
associated with patch files).
If the [http://www.freebsd.org/ports/installing.html FreeBSD ports collection] has it,
you could
[ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz 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 ==
; koji
: The main Fedora build system: [https://koji.fedoraproject.org].


You now need to create a ".spec" file in the "~/rpmbuild/SPECS" directory.
== Editors for editing RPM spec files ==
You should name it after the program name, e.g., "program.spec", use the archive name or the name advocated by the software author.
Many editors (like text editors and IDEs) that are in the official repositories of Fedora have out-of-the-box syntax-highlighting support for RPM spec files, these include:


=== Creating a blank spec file ===
* [[CodeEditor]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[gedit]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[GNU nano]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[Joe]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[Kate]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[KWrite]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[Pluma]]. It does not syntax-highlight the shell script code found in RPM spec files.
* [[Vim]] (and, of course, its graphical counterpart, gVim). It also syntax-highlights the shell script code found in RPM spec files.


When you're creating a spec file for the first time, you can create its initial version using emacs or vim,
while the following are present in the official Fedora repositories but do not come with out-of-the-box syntax-highlighting for RPM Spec files, but do gain said support when optional packages/plugins are installed:
they will automatically create a template for you.  E.G.:
  $ cd ~/rpmbuild/SPECS
  $ vi program.spec


Here's an example of what that template will look like:
* [[Eclipse]] can develop RPM spec file editing support when the [https://apps.fedoraproject.org/packages/eclipse-rpm-editor RPM Spec file editor] package is also installed. This package also provides code linting (checking for RPM packaging errors) and make it easier to navigate the spec file.
  Name:
* [[GNU Emacs]] has editing support for RPM spec files when the [https://apps.fedoraproject.org/packages/emacs-rpm-spec-mode RPM spec mode] package is installed.
Version:
 
Release: 1%{?dist}
Editors that are not in the official repositories of Fedora but are available for Fedora and, with the appropriate plugins, can syntax-highlight RPM spec files include:
  Summary:
 
  Group:
* [[Atom]], with the [https://atom.io/packages/language-rpm-spec language-rpm-spec] package.
  License:
* [[Visual Studio Code]], with the [https://marketplace.visualstudio.com/items?itemName=1dot75cm.RPMSpec RPM Spec] extension.
  URL:
 
  Source0:
== Preparing your system ==
  BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
Before you create RPM packages on Fedora, you need to install some packaging tools and set up the account(s) you will use.  Run this as root:
dnf install fedora-packager fedora-review
 
This will install the {{package|fedora-packager}} utilities needed to work with and build packages in the same manner used to maintain official Fedora packages, including the {{package|fedora-review}} tool used by package reviewers to check package quality.
 
{{admon/caution|You should never create your packages as the <code>root</code> user. Indeed, you should never perform anything other than specific administration tasks as root.  Building RPMs as root is dangerous because it is possible for situations to exist (due to mistakes or typos in the spec file) for some package building operations to attempt to write files to system locations.  You must always build as a normal user to avoid corrupting parts of your system.  This document will generally use the {{package|mock}} system to build more complicated packages in a very safe manner.}}
 
As root, add yourself to the mock group:
usermod -a -G mock yourusername
This should be the last time you need root unless you wish to install packages you have developed.
 
You may afterwards need to run <code>newgrp</code> or log out and back in for this change to take effect.  Run the <code>id</code> command to see if the "mock" group appears in your group list.
 
If you have already obtained a Fedora account and accepted the contributor agreement, you can also set up your fedora certificates and such.  Just run (as your user, not as root):
fedora-packager-setup
 
If you wish, you can also create a separate user and use it for doing RPM development.  You should make sure that user is part of the "mock" group and has run <code>fedora-packager-setup</code>.
 
== First steps ==
 
To create an RPM package, you will need to create a directory to hold the package and, within that directory, the specfile.  This file provides information about the software being packaged, instructions for unpacking it, building it and installing it, as well as a list of files which will be included in the package.  You then run the <code>fedpkg</code> command with appropriate options, which will go through a series of steps to produce your package.
 
The construction of the specfile is often done iteratively (one relevant piece at a time), and that's what we'll do here.  But first we'll need someplace to make our package as well as something to package.  Run the following to create a directory to hold packaging work (called <code>packaging-work</code>), within it a place to hold our package (called "<code>howdy</code>), and within that a simple program to package (also called "<code>howdy</code>).  You can use any location you like but the directory name for the package should match the name of the package.
 
mkdir -p ~/packaging-work/howdy
cd ~/packaging-work/howdy
cat << EOF > howdy
#!/bin/bash
echo "Howdy, partner!"
EOF
chmod 644 howdy
 
You should be able to run <code>bash howdy</code> and receive the expected output.  Now we have something we can package, so let's start making a specfile.  We'll start with a very minimal template (which will have to be expanded for anything more complicated than this example).  Just start your editor on a new file called <code>howdy.spec</code>" and paste this in.  Please use spaces and not tabs.  It's not necessary to have everything like up but it does make it look nice.
 
<pre>
Name:    howdy
Version: 1
Release: 1%{?dist}
Summary: Say hello, Texas style
 
License: Public Domain
Source0: howdy
 
%description
A simple program to greet the user, Texas style.
 
%install
 
%files
 
%changelog
</pre>
 
So we've described the package, indicated a version and listed the one source file we have.  We have an <code>%install</code> and a <code>%files</code> section, both of which are empty.  Save your edits and run
fedpkg --release f{{FedoraVersionNumber|current}} local
This is called a "local build".  Assuming no typos or other issues, you should get some output and two RPM files.  One should be the source package, which contains everything necessary for someone else (or the Fedora build system) to build their own copy of your package.  The other is a binary package.  It doesn't actually have anything in it at this point, though, because we didn't tell RPM to actually include any files.  (It would not even have been created if we hadn't included the empty <code>%files</code> section.)
 
If you like, you can look at either package using <code>rpm -qip</code>, or just <code>less</code>.
 
== A useful package ==
So now we have a minimally functional specfile which builds and produces a rather useless binary package.
 
In order to actually make a package which does something, we must tell RPM how to install the program.  Edit the specfile and add this to the <code>%install</code> section (immediately after the line containing <code>%install</code>):
mkdir -p %{buildroot}/%{_bindir}
install -p -m 755 %{SOURCE0} %{buildroot}/%{_bindir}
The contents of the <code>%install</code> section is just a shell script!  Note that we've used three macros:
* <code>%{buildroot}</code> is set to a temporary directory called "the buildroot" that's set up by RPM to hold the complete tree of files we'll install.
* <code>%{_bindir}</code> is just /usr/bin.
* <code>%{SOURCE0}</code> refers to the file listed earlier in the spec with the <code>Source0:</code> tag.
 
This saves us from having to care about exactly where those files and directories are located on the filesystem while the package is built; instead we only care about where those files are ending up.  And without <code>%{buildroot}</code> we'd end up installing those files directly onto our development machine, which would be bad, especially if running as root.
 
Now do a local build. It failed!  But why?  Well, because of this:
error: Installed (but unpackaged) file(s) found:
    /usr/bin/howdy
We installed a file but didn't tell RPM about it.  RPM maybe could just include everything we install, but there are plenty of good reasons why it doesn't just do that.  So tell RPM about that file, by adding this to the <code>%files</code> section:
%{_bindir}/howdy
Note that <code>%files</code> is generally about files we've actually installed into the buildroot.  You do not use the <code>%{buildroot}</code> macro when listing files there.
 
Now do another local build.  If all goes well, you should have two updated RPMs, and the binary one should contain a file.  But there's one more thing we should add to the spec to make this a complete package.  Since all we're packaging is a shell script, there is no reason at all for this to be built separately on each architecture Fedora supports.  So edit the spec once more and add the following immediately after the <code>Source0:</code> line:
BuildArch: noarch
This tells RPM that there's nothing architecture-specific about a particular package.  You can reindent the spec if you like to make things line up, but please use spaces and not tabs.  Delete the existing <code>.rpm</code> files in this directory and do another local build.  Now you should have a pair of rpms: one with the updated source, and one ending in <code>.noarch.rpm</code> indicating an architecture-independent package.  You should now have your first complete package that you built yourself!  If you like, install it and try it out.  You'll probably want to remove it once you're done, unless you just like Texas-style greetings.
 
== Further things to do with our package ==
Have a glance at our current spec if you like.
<pre class="mw-collapsible mw-collapsed">
Name:     howdy
Version:   1
Release:   1%{?dist}
Summary:  Say hello, Texas style
 
License:  Public Domain
Source0:  howdy
BuildArch: noarch
 
%description
A simple program to greet the user, Texas style.
 
%install
mkdir -p %{buildroot}/%{_bindir}
install -p -m 755 %{SOURCE0} %{buildroot}/%{_bindir}
 
%files
%{_bindir}/howdy
 
%changelog
</pre>
 
You may recall that RPM handles dependencies, but we didn't indicate anything about that in the specfile.  Let's look.
  rpm -qp --requires howdy-1-1.fc{{FedoraVersionNumber|current}}.noarch.rpm
You'll see that RPM added some internal <code>rpmlib</code> dependencies, plus one on <code>/bin/bash</code> which matches up with the first line of the howdy program.  Often RPM will handle dependencies for your binary packages automatically.  Often times it won't, and we'll look into that later.
 
You can also replace <code>--requires</code> by <code>--provides</code> to see the other side of the dependency equation.  There's not much of interest there, but if something did depend on <code>howdy</code> then this package would provide it.
 
Next thing to do is run some checks on our package:
  fedpkg --release f{{FedoraVersionNumber|current}} lint
This will spit out a few complaints.  Four total about the lack of <code>%prep</code> and <code>%build</code> sections, one about the lack of a <code>URL:</code> tag, and one about the lack of a proper changelog.  You may also see other complaints, perhaps about permissions.  The full set of complaints may change over time as the checking program, {{package|rpmlint}} itself changes.  You may even have noticed these complaints earlier if your editor was configured to automatically check specfiles as you edit them.
 
We will ignore the complaints about the lack of the two sections and a URL.  We could make the complaints go away by adding empty sections and a dummy URL, but that's not productive and our next experiment will have them.
 
It would indeed be nice to have a changelog section, though.  Your editor may have the capability to add one automatically; in {{package|vim}} it's {{key press|\}}{{key press|c}} (unless you've changed the leader key) and in {{package|emacs}} it's {{key press|Ctrl|c}} {{key press|Ctrl|e}}.  If you want to do it manually, have a look at the relevant [[Packaging:Guidelines#Changelogs|guidelines]]. I'll add mine here:
  * Mon Sep 19 2016 Jason L Tibbitts III <tibbs@math.uh.edu> - 1-1
- Initial packaging.
 
=== Building in mock ===
The next interesting thing to do would be to see if our package will build in the way that the Fedora build system would do it.  To do this, just run:
  fedpkg --release f{{FedoraVersionNumber|current}} mockbuild
This will build your package in {{package|mock}}.  Running mock will set up a complete minimal Fedora installation inside a directory and then build the package within that.
 
{{admon/note|Please note that this can take a while.  It has to download a number of packages and can take quite some time if you do not have a fast link.  It will also take a nontrivial amount of disk space.  Fortunately the data it downloads will be cached so subsequent runs will be quicker, but if the disk usage (by default in <code>/var</code>), the time or the bandwidth usage are an issue for you, you can skip this step.  However, from this point on in the document, we will do mock builds rather than local builds, and later steps will require that mock builds be carried out.  You can continue to perform local builds where possible if you prefer, but eventually you will run into dependency issues that mockbuilds do not have.}}
 
The end result should be a significant amount of output, a results_howdy directory, and a couple of levels deep a three log files and two packages.  Feel free to look at those.
 
You can also build for other releases in this manner, by changing what you pass to the <code>--release</code> option.  This can be useful for testing, but it takes another big download so we'll skip that now.
 
=== Building in koji ===
If you had your Fedora account set up at the time you started following this document, you can build your package in the central Fedora build system, though the syntax can be a bit odd:
  fedpkg --release f{{FedoraVersionNumber|current}} scratch-build --target f{{FedoraVersionNumber|current}} --srpm
This will create a source package, upload it to the build servers, and give you some output including a URL you can visit to watch the process and download the built packages afterwards.  This can be useful to test that your package builds on the various different architectures that Fedora supports, although your current test package doesn't need such testing.
 
=== Running fedora-review ===
Package reviewers use {{package|fedora-review}} as part of the process of accepting new packages into the distribution.  You can run this tool yourself as a useful set of informative checks.  First, clean up your package directory:
rm -rf *rpm results*
Then create a source package and run the utility:
  fedpkg --release f{{FedoraVersionNumber|current}} srpm
fedora-review -n howdy
This will use mock to build your package and run a number of checks on it.  It will be silent while mock runs, so it may appear as if it has hung when in reality it is doing a large amount of downloading.  You can add <code>-v</code> to make it somewhat more verbose.
 
When done, you should have a <code>review-howdy</code> directory with various files and directories.  <code>rpmlint.txt</code> should have some additional rpmlint output for you.  <code>review.txt</code> is the template that a reviewer would fill in (in addition to checking the functionality of the software in your package, etc.)  Most of that is probably not of interest to you, but it doesn't hurt to have a look.
 
== On to a more complex program ==
Now that we've covered the absolute basics, we can move on to packaging something more complicated, which comes from a real upstream and has to be unpacked and built.  A good package to use as an example is [https://www.gnu.org/software/hello/ GNU Hello].  Have a look there, note the current version of Hello (2.10 as this document is being written) and the download URL, licensing information and such.  It's helpful to keep that page open for referenceLet's create a directory and work in it:
  mkdir -p ~/packaging-work/hello
  cd ~/packaging-work/hello
And create the following specfile named <code>hello.spec</code>:
<pre>
Name:    hello
Version: 2.10
Release: 1%{?dist}
Summary: GNU Hello
URL:    https://www.gnu.org/software/hello/
License: GPLv3+
 
Source0: https://ftp.gnu.org/gnu/hello/hello-%{version}.tar.gz
 
%description
The GNU hello program produces a familiar, friendly greeting. It allows
nonprogrammers to use a classic computer science tool which would otherwise be
unavailable to them. Because it is protected by the GNU General Public License,
users are free (in perpetuity) to share and change it.
 
%prep
 
%build
 
%install
 
%files
 
%changelog
</pre>
 
We've filled in a few things here.  There's now a <code>URL:</code> tag, pointing to the Hello homepage.  The <code>%description</code> was cribbed from the homepage.  The <code>License:</code> tag has changed, since the bottom of the homepage says that the license is "under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.".  Licensing is a difficult subject, and we'll cover it in more depth later, but for now it's sufficient to note that Fedora indicates this type of license with "GPLv3+".
 
Perhaps the most interesting change is to the <code>Source0:</code> tag.  It now has a URL instead of a filename: using a URL tells everyone, including the relevant Fedora utilities, where to actually get the source. And there's a macro in there: <code>%{version}</code> is automatically set to whatever you used for the <code>Version:</code> tag.  Combining the two lets things automatically get an updated copy of the source whenever the version changes.  But how do we actually get that source, since now we can't cut and paste that URL?  Try <code>spectool</code>:
spectool -g *spec
This quickly grabs all of the sources mentioned in the spec, and will leave us with <code>hello-2.10.tar.gz</code> in our package directory.  Have a look with that file:
less *tar.gz
and we see that everything in there unpacks unto a single directory named <code>hello-2.10</code>.  We'll need to tell RPM how to unpack that archive and how to find the files within.  Add this to the <code>%prep</code> section:
%autosetup
This is a rather complicated macro which RPM will replace with plain old shell code to unpack the archive, change into a directory and fix up some permissions.  It by default expects the directory to be named <code>%{name}-%{version}</code> (where <code>%{name}</code> is, you guessed it, what you gave for the <code>Name:</code> tag).  This can be changed by passing the <code>-n</code> option, but in our case the default is just what we need.  You can see exactly what it does by executing the <code>%prep</code> section with:
fedpkg --release f{{FedoraVersionNumber|current}} prep
This will call just the <code>%prep</code> section of your specfile, and should leave you with a directory named <code>hello-2.10</code> in your package directory.  Have a look around in there.  You'll see this is a standard GNU package with a <code>configure</code> file, and that tells us most of what we need to know in order to build it.  Add this to the <code>%build</code> section:
%configure
%make_build
This just calls the <code>configure</code> file with all of the arguments necessary to build in Fedora, and then calls <code>make</code> with the necessary options.  And while we're at it, let's add this to <code>%install</code>:
%make_install
This calls the usual <code>make install</code> with Fedora's special macros to get everything into the buildroot. If you do a mockbuild at this point, you'll see that the build fails, just like with the previous package, there are installed but unpackaged files. The list of files below the error heading in the output, tells us what we need to do next, but because there's an info page, a manpage and some locale files, we have a few different rules to follow.
 
== Old document below ==
{{admon/note|Beyond this point are remnants of the old document.  These will all be incorporated or removed as the reorganization and cleanup continues.  The information below is almost certainly out of date with regards to the current packaging guidelines.  Please keep that in mind if you read further.}}
 
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 <code>.tar.gz</code> file) in the
<code>~/rpmbuild/SOURCES</code> 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. With a few exceptions, all binaries and libraries included in Fedora packages must be built from the source code that is included in the source package.
 
== Creating a SPEC file ==
 
You now need to create a SPEC file in the <code>~/rpmbuild/SPECS</code> directory. You should name it after the program name (e.g. "<code>program.spec</code>").  Use the archive name or the name advocated by the software author where you can, but be sure to follow the [[Packaging/NamingGuidelines|Package Naming Guidelines]].
 
=== SPEC templates and examples ===
==== Templates ====
 
You may use the <code>rpmdev-newspec</code> command to create a SPEC file for you.  <code>rpmdev-newspec &lt;package-name&gt;</code> 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 <code>/etc/rpmdevtools/spectemplate-*.spec</code> for available templates, and see <code>rpmdev-newspec --help</code> for more information. For example, to create a new SPEC file for a python module:
 
cd ~/rpmbuild/SPECS
rpmdev-newspec python-antigravity
vim python-antigravity.spec
 
According to the [[Packaging:Guidelines#Writing_a_package_from_scratch|packaging guidelines]], new spec files should be created this way. Vim and emacs can automatically create simple templates, but these are different than those made with <code>rpmdev-newspec</code>. This is especially true for templates with names beginning with <code>python-</code> or <code>-perl</code>.
 
Here is an example auto-generated <code>.spec</code> template:
 
Name:          testprogram
Version:       
Release:        1%{?dist}
Summary:       
License:       
URL:           
Source0:       
   
   
  BuildRequires:
  BuildRequires:
  Requires:
  Requires:      
   
   
  %description
  %description
   
   
  %prep
  %prep
  %setup -q
  %setup -q
   
   
  %build
  %build
  %configure
  %configure
  make %{?_smp_mflags}
  %make_build
   
   
  %install
  %install
  rm -rf %{buildroot}
  %make_install
make install DESTDIR=%{buildroot}
   
   
%clean
rm -rf %{buildroot}
   
   
  %files
  %files
%defattr(-,root,root,-)
  %doc
  %doc
   
   
  %changelog
  %changelog
* Sun Apr  3 2016 makerpm
-
==== Examples ====
===== eject =====
Here's a simple example showing a Fedora specfile for the <code>eject</code> program:
<pre>
Summary:            A program that ejects removable media using software control
Name:              eject
Version:            2.1.5
Release:            21%{?dist}
License:            GPLv2+
Source:            %{name}-%{version}.tar.gz
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
URL:                http://www.pobox.com/~tranter
ExcludeArch:        s390 s390x
BuildRequires:      gettext
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
%autosetup -n %{name}
%build
%configure
%make_build
%install
%make_install
install -m 755 -d %{buildroot}/%{_sbindir}
ln -s ../bin/eject %{buildroot}/%{_sbindir}


%find_lang %{name}


You may have $RPM_BUILD_ROOT instead of %{buildroot}; just be consistent.
%files -f %{name}.lang
%license COPYING
%doc README TODO ChangeLog
%{_bindir}/*
%{_sbindir}/*
%{_mandir}/man1/*


=== An example: eject ===
%changelog
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.5-21
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild


Here's a simple example, a Fedora 9 package for the "eject" program:
* Fri Jul 02 2010 Kamil Dudka <kdudka@redhat.com> 2.1.5-20
- handle multi-partition devices with spaces in mount points properly (#608502)
</pre>


Summary: A program that ejects removable media using software control.
===== =====
Name: eject
{{Anchor|Spec_file_pieces_explained}}
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 &lt;zprikryl at, redhat.com&gt; 2.1.5-11
- Added check if device is hotpluggable
- Resolves #438610


You can also use the "BuildRoot:" entry from the template instead, although both are acceptable, the one from the template is the preferred one.
== SPEC file overview ==


=== Spec file pieces explained ===
Other useful guides:
* [http://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html RPM Guide] describes how to write a SPEC file.
The [http://docs.fedoraproject.org/drafts/rpm-guide-en/ch-creating-rpms.html RPM Guide, section on creating RPMs],
* The IBM series "Packaging software with RPM" [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3/ Part 3].
describes the details of how to fill in a spec file.
* [http://ftp.rpm.org/max-rpm/ Maximum RPM] has the most complete information, but is dated.
The developerWorks series "Packaging software with RPM" [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3] is also handy.
[http://rpm.org/max-rpm-snapshot/ Maximum RPM] has the most complete information, but is dated.


You will need to follow the Fedora guidelines, such as the
You will need to follow the Fedora guidelines: [[Packaging/NamingGuidelines|Package Naming Guidelines]], [[Packaging/Guidelines|Packaging guidelines]], and [[Packaging/ReviewGuidelines|Package review guidelines]].
[[Packaging/NamingGuidelines| Package Naming Guidelines]],
[[Packaging/Guidelines| Packaging Guidelines]], and
[[Packaging/ReviewGuidelines|Package review guidelines]].


You can insert comments with a leading "#" character, but
Insert comments with a leading "<code>#</code>" character, and beware of macros (beginning with <code>%</code>) that are potentially multi-line, as they are expanded first. When commenting out a line, double the percent signs (<code>%%</code>) of the macros appearing after the "<code>#</code>". Also avoid inline comments on the same line as script commands.
don't insert potentially-multiline-macros (words beginning with "%") in a comment
(macros are expanded first); if you're commenting out a line, double the percent signs ("%%"). Also, don't use inline comments ("#") on the same line after
a script command.


Here are the major fields/areas that you will need to fill in:
The major tags are listed below. Note that the macros <code>%{name}</code>, <code>%{version}</code> and <code>%{release}</code> 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.  It must follow the [[Packaging/NamingGuidelines| Package Naming Guidelines]].  In many cases, this will be in all lower case. Elsewhere in the spec file, you can refer to the name using the macro %{name} - that way, if the name changes, the new name will be used by those other locations. This name should match the spec file name.
* '''Name''': The (base) name of the package, which should match the SPEC file name.  It must follow the [[Packaging/NamingGuidelines|Package Naming Guidelines]] and generally be lowercase.
* Version: The upstream version number. See [http://fedoraproject.org/wiki/Packaging/NamingGuidelines#Package_Version Packaging/Naming guidelines - package version] for more information. If the version is non-numeric (contains tags that are not numbers or digits), you may need to include the additional non-numeric characters in the release field. If upstream uses full dates to distinguish versions, consider using version numbers of the form yy.mm[dd] (so a 2008-05-01 release becomes 8.05). Elsewhere in the spec file, refer to this value as %{version}.
* '''Version''': The upstream version number. See [[Packaging/NamingGuidelines#Version_Tag|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 <code>yy.mm[dd]</code> (e.g. <code>2008-05-01</code> becomes <code>8.05</code>).
* Release: The initial value of the release should normally be "1%{?dist}". Then, increment the number every time you release a new package for the same version of software. If a new version of the software being packaged is released, the version number should be changed to reflect the new software version, and the release number should be reset to 1. See [http://fedoraproject.org/wiki/Packaging/NamingGuidelines#Package_Release Name Guidelines - package release] for more. [[Packaging/DistTag]] describes the "dist" tag, which isn't required but can be useful. Use %{release} to reuse this value.
* '''Release''': The initial value should normally be <code>1%{?dist}</code>. 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 <code>1</code>. See [[Packaging/NamingGuidelines#Release_Tag|Release tag section]] of the packaging guidelines. The optional [[Packaging/DistTag|Dist tag]] might be useful.
* Summary: A brief, one-line summary of the package. Use American English, and ''do not'' end in a period.
* '''Summary''': A brief, one-line summary of the package. Use American English. '''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. If you create a sub-package "...-doc" with documentation, use the group "Documentation".
* '''Group''': This needs to be a pre-existing group, like "Applications/Engineering"; run "<code>less /usr/share/doc/rpm/GROUPS</code>" to see the complete list. Use the group "Documentation" for any sub-packages (e.g. <code>kernel-doc</code>) containing documentation'''''Note: This tag is deprecated since Fedora 17. See [https://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide/chap-Packagers_Guide-Spec_File_Reference-Preamble.html Spec File Reference Preamble] '''''
* License: Its license; for software, this must be an open source software license.  Use a standard abbreviation, e.g., "GPLv2+"Try to be specific, e.g., use "GPLv2+" (GPL version 2 or greater) instead of just "GPL" or "GPLv2" where it's true. See [[Licensing]] and the [[Packaging/LicensingGuidelines| Licensing Guidelines]] for more information.  Call this tag "License"; don't use the older, inaccurately named tag "Copyright".
* '''License''': The license, which must be an open source software license. Do ''not'' use the old Copyright tag. Use a standard abbreviation (e.g. "<code>GPLv2+</code>") and be specific (e.g. use "<code>GPLv2+</code>" for GPL version 2 or greater instead of just "<code>GPL</code>" or "<code>GPLv2</code>" where it's true).  See [[Licensing]] and the [[Packaging/LicensingGuidelines|Licensing Guidelines]]. You can list multiple licenses by combining them with "<code>and</code>" and "<code>or</code>" (e.g. "<code>GPLv2 and BSD</code>").
* URL: The URL for more information about the program, e.g., the project website. Note: This is NOT where the original source code came from, see "Source" (next!).
* '''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 URL for the compressed archive containing (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. '''Warning:''' ''Source0:'' and ''URL:'' are different - normally they are both URLs, but the "URL:" entry points to the project website, while the "Source0:" entry points to the actual file containing the source code (and is typically a .tar.gz file).  As noted in the guidelines, "When downloading sources, patches etc, consider using a client that preserves the upstream timestamps. For example wget -N or curl -R. To make the change global for wget, add this to your ~/.wgetrc: timestamping = on, and for curl, add to your ~/.curlrc: -R."  If there is more than one source, name them Source1, Source2, and so on. See [[Packaging/SourceURL]] for more information on special cases (using revision control, when upstream uses prohibited code, etc.).
* '''Source0''': The full URL for the compressed archive containing the (original) pristine source code, as upstream released it. "<code>Source</code>" is synonymous with "<code>Source0</code>". If you give a full URL (and you should), its basename will be used when looking in the <code>SOURCES</code> directory. If possible, embed <code>%{name}</code> and <code>%{version}</code>, so that changes to either will go to the right place. [[Packaging:Guidelines#Timestamps|Preserve timestamps]] when downloading source files. If there is more than one source, name them <code>Source1</code>, <code>Source2</code> 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 otherwiseSee [[Packaging/SourceURL|Source URL]] for more information on special cases (e.g. revision control).
* Patch0: The name of the first patch that you will apply to the source code.  If you need to patch the files after they've been uncompressed, you should edit the files, save their differences as a "patch" file in your ~/rpmbuild/SOURCES directoryPatches should make only one logical change, so it's quite possible to have multiple patch files.
* '''Patch0''': The name of the first patch to apply to the source codeIf 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 <code>~/rpmbuild/SOURCES</code> directory. Patches should make only one logical change each, so it's quite possible to have multiple patch files.
* BuildRoot: This is where files will be "installed" during the "%install" process (which happens after the %build compilation process)Normally you should just leave this line alone; under the usual Fedora setup, this will be a macro that will create a new special directory under /var/tmp.
* '''BuildArch''': If you're packaging files that are architecture-independent (e.g. shell scripts, data files), then add "<code>BuildArch: noarch</code>". The architecture for the binary RPM will then be "<code>noarch</code>".
* BuildRequires: A comma-separated list of packages required for building (compiling) the program. These are ''not'' automatically determined, so you need to include ''everything'' needed to build the program.  There are a few packages that are so common in builds that you don't need to mention them, such as "gcc"; see the [[Packaging/Guidelines| Packaging Guidelines]] for the complete list of the packages you may omit.  You can also specify minimum versions, if necessary, like this: "ocaml >= 3.08". You can have more than one line of BuildRequires (in which case they are all required for building). If you need file /EGGS, you can get its package by running "rpm -qf /EGGS"; if EGGS is a program, you determine its package quickly by running "rpm -qf `which EGGS`". Try to specify only the minimal set of packages necessary to properly build the package, since each one will slow down a "mock"-based build (e.g., try to use sed instead of perl if you don't really need perl's abilities). Watch out: Some applications permanently disable functions if their package isn't detected during the build; in those cases you may need to include those additional packages.
* '''BuildRoot''': This is where files will be "installed" during the %install process (after the %build process). This is now redundant in Fedora and is only needed for EPEL5. By default, the build root is placed in "<code>%{_topdir}/BUILDROOT/</code>".
* Requires: A comma-separate list of packages that are required when the program is installed.   Note that the list of packages for ''Requires'' (what's required when running) and ''BuildRequires'' (what's required to build the binary RPM) are independent; a package may be in one list but not the other, or it could be in both.  The "Requires" list is automatically determined by rpm, so normally you don't need to put anything here. But if you want to highlight some specific packages as being required, or require a package that rpm can't detect should be required, then add it here.
* '''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. It is possible to ensure you have specified all necessary build requires by [[Using_Mock_to_test_package_builds|performing a "mock build"]] of your package. You can specify a minimum version if necessary (e.g. "<code>ocaml >= 3.08</code>"). If you need the file <code>/EGGS</code>, determine the package that owns it by running "<code>rpm -qf /EGGS</code>". If you need the program <code>EGGS</code>, determine the package that owns it by running "<code>rpm -qf `which EGGS`</code>". Keep dependencies to a minimum (e.g. use <code>sed</code> instead of <code>perl</code> 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 {{package|auto-buildrequires}} package may be helpful.
* %description - A longer, multi-line description of the program. Use American English. All lines must be 80 characters or less.
* '''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, <code>rpmbuild</code> 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.
* %prep - Script commands to "prepare" the program, that is, to uncompress it so that it will be ready for building (compiling). Typically this is just "%setup -q" or some variation of it; a common variation is "%setup -q -n NAME" if the source file unpacks into NAME. See the "%prep" section below for more.
* '''%description''': A longer, multi-line description of the programUse 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 [https://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03.html RPM Guide].
* %build - Script commands to "build" the program, that is, 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.
* '''%prep''': Script commands to "prepare" the program (e.g. to uncompress it) so that it will be ready for buildingTypically this is just "<code>%autosetup</code>"; a common variation is "<code>%autosetup -n NAME</code>" if the source file unpacks into <code>NAME</code>. See the %prep section below for more.
* %check - Script commands to self-test the program. This is run after %build and before %install, so you should place it there if you have this sectionOften it simply contains "make test" or "make check". This is separated from %build so that people can skip the self-test if they desire. This isn't documented in many places.
* '''%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.
* %install - Script commands to "install" the program.  The commands should copy the files from the "build directory" %{_builddir} (which would be under ~/rpmbuild/BUILD) into the buildroot directory, %{buildroot} (which would normally be under /var/tmp). See the "%install" section below for more.
* '''%install''': Script commands to "install" the program.  The commands should copy the files from the <code>BUILD</code> directory <code>%{_builddir}</code> into the buildroot directory, <code>%{buildroot}</code>. See the %install section below for more.
* %clean - instructions to clean out the build root. Typically:
* '''%check''': Script commands to "test" the program. This is run after the %install procedure, so place it there if you have this section. Often it simply contains "<code>make test</code>" or "<code>make check</code>". This is separated from %build so that people can skip the self-test if they desire.
* '''%clean''': Instructions to clean out the build root. Note that this section is now redundant in Fedora and is only necessary for EPEL. Typically this contains only:
  rm -rf %{buildroot}
  rm -rf %{buildroot}
* %files - the list of files that will be installed.   See the "%files" section below for more.
* '''%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.
* '''%changelog''': Changes in the package.  Use the format example above. '''Do NOT put software's changelog at here.This changelog is for RPM itself.'''
* ExcludeArch: If the package does not successfully compile, build or work on an architecture, then those architectures should be listed in the spec in an ExcludeArch tag.
* '''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.
* 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.


Don't use the tags "Packager" or "Vendor".  Don't use "Copyright" - use "License" instead.
RPM also supports the creation of several packages (called [[How_to_create_an_RPM_package#Subpackages|subpackages]]) from a single SPEC file, such as <code>name-libs</code> and <code>name-devel</code> packages.
Don't create a "relocatable" package - they don't add value in Fedora yet they make things more complicated.
 
{{admon/caution|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.


RPM supports subpackages, that is, a single spec file can generate many
== SPEC file sections explained ==
binary packages.  For example, if the documentation is very large, you might generate
a separate "doc" subpackage.
[http://docs.fedoraproject.org/drafts/rpm-guide-en/ch10s04.html RPM Guide chapter 10] discusses how to create subpackages.


=== %prep section ===
=== %prep section ===
The "%prep" section describes how to unpack the compressed packages so that they can be built.
Typically, this is a set of "%setup" and/or %patch commands, which reference the Source0:, Source1:, etc. lines above.
See the [http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html Maximum RPM section on %setup and %patch] for more details.


'''Warning:''' In spec files, don't use in-line comments (a "#" comment on the same line after a command), and don't put macros (words beginning with "%") in a comment unless you quote the "%" as "%%". Macros can cause failures if they are in a comment, because they are always expanded (even when in a comment) and they can expand to multiple linesThis is true for %prep, %build, and so on.
The %prep section describes how to unpack the compressed packages so that they can be built. Typically, this includes the "<code>%autosetup</code>" command.  Alternatively, you can use "<code>%setup</code>" and "<code>%patch</code>" commands with reference to the Source0 (and Source1 etc.) lines. See the [http://ftp.rpm.org/max-rpm/s1-rpm-inside-macros.html 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 and %autosetup is not what you want, then you can do:
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: %autosetup command ====
 
The "<code>%autosetup</code>" command unpacks a source package. Switches include:
* '''<code>-n</code> ''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>%autosetup -n FOO</code>".
* '''<code>-c</code> ''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.
 
If you use "<code>%setup</code>" command instead, then ''<code>-q</code>''' is commonly used to suppress unecessary output.
 
There are [http://ftp.rpm.org/max-rpm/s1-rpm-inside-macros.html more %setup options if you are unpacking multiple files], which is primarily useful if you
are creating subpackages (see below).  The key ones are:
 
{|
|-
| <code>-a number</code> || Only unpack the Source directive of the given number after changing directory (e.g. "<code>–a 0</code>" for Source0).
|-
| <code>-b number</code> || Only unpack the Source directive of the given number before changing directory (e.g. "<code>–b 0</code>" for Source0).
|-
| <code>-D</code> || Do not delete the directory before unpacking.
|-
| <code>-T</code> || Disable the automatic unpacking of the archives.
|}
 
==== %prep section: %patch commands ====
 
If you have used "<code>%autosetup</code>" command, the following manual patch management is not necessary.  If you have complex requirements or need compatibility with EPEL, you may still need this. The "<code>%patch0</code>" 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 "<code>-pNUMBER</code>" option applies, which passes that argument onto the program <code>patch</code>.


The "%setup" command unpacks a source package, and takes several switches. Normally you should use "-q" (quiet) to prevent setup from babbling about every file it unpacks. Here are a few switches:
Patch file names often look like "<code>telnet-0.17-env.patch</code>", which is the format <code>%{name} - %{version} - REASON.patch</code>" (though sometimes version is omitted). Patch files are typically the result of "<code>diff -u</code>"; if you do this from the subdirectory of <code>~/rpmbuild/BUILD</code> then you won't have to specify a <code>-p</code> level later.
* -n ''name'': If the name of the rpm is something other than what the Source unpacks to, use this switch to state the ''name'' it unpacks to.  E.G., if the tarball unpacks into a directory MYNAME, use %setup -q -n MYNAME
* -c ''name'': If the tarball doesn't unpack into a single directory, this creates a directory named ''name'' and then unpacks into it.  Useful if you have one of those annoying tarballs that doesn't have a single common subdirectory embedded in it.


The "%patch0" command applies patch 0 (similar for 1, 2, etc.).  The normal "-pNUMBER" option applies, which simply passes that argument on to ''patch''.  The names of patch files are often %{name}, ".", some name that hints at the patch purpose, and ".patch". Patch files are typically the result of a "diff -u"; if you do this from the subdirectory of ~/rpmbuild/BUILD, you won't have to specify a -p level later.  You can use all the normal ways of creating a patch file.  If you're creating a patch file a single file FILENAME, a common way is to copy it to FILENAME.orig, modify it, and then save the results of "diff -u FILENAME.orig FILENAME":
This is a typical procedure for creating a patch for a single file:
  cp X/Y.Z X/Y.Z.orig
  cp foo/bar foo/bar.orig
  vim X/Y.Z
  vim foo/bar
  diff -u X/Y.Z.orig X/Y.Z > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
  diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
If you're going to edit many files, one easy method is to copy the whole subdirectory underneath BUILD, and then do subdirectory diffs; once you're in BUILD/whatever, you can:
 
  cp -pr . ../PACKAGENAME.orig
If editing many files, one easy method is to copy the whole subdirectory underneath <code>BUILD</code> and then do subdirectory diffs.  After you have changed directory to "<code>~rpmbuild/BUILD/NAME</code>", do the following:
  cp -pr ./ ../PACKAGENAME.orig/
  ... many edits ...
  ... many edits ...
  diff -u . ../PACKAGENAME.orig > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
  diff -ur ../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 "<code>.orig</code>" before editing them. Then, you can use "<code>gendiff</code>" (in the <code>rpm-build</code> package) to create a patch with the differences.
 
Try to ensure that your patch match the context exactly. The default "fuzz" value is "<code>0</code>", requiring matches to be exact. You can work around this by adding "<code>%global _default_patch_fuzz 2</code>" 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, you'll package just a straight file that doesn't need to be uncompressed, e.g., a "Source1:" that is just a simple PDF file. You can "prep" those into the build directory by doing this (replace "1" with whatever number it is):
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 <code>SOURCE1</code> refers to the relevant Source file):
  cp -p %SOURCE1 .
cp -p %SOURCE1 .


=== %build section ===
=== %build section ===
Line 323: Line 517:
The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.
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" (/usr/local/bin, /usr/local/lib, etc.), which is a reasonable default for unpackaged files - but since you ''are'' packaging it, you will want to change the prefix to "/usr". Often some variation of this will work:
Many programs follow the GNU <code>configure</code> approach (or some variation). By default, they will install to a prefix of "<code>/usr/local</code>", which is reasonable for unpackaged files. However, since you are packaging it, change the prefix to "<code>/usr</code>". Libraries should be installed to either <code>/usr/lib</code> or <code>/usr/lib64</code> depending on the architecture.
 
Since GNU <code>configure</code> is so common, the macro "<code>%configure</code>" can be used to automatically invoke the correct options (e.g. change the prefix to <code>/usr</code>). Some variation of this often works:
   %configure
   %configure
   make %{?_smp_mflags}
   %make_build
 
Sometimes you'll want to override the variables of a makefile; you can easily do that by passing them as parameters to make, like this:
make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}
 
If you need to do something complicated with GNU-generated configure, take a look at [http://sourceware.org/autobook/ "GNU autoconf, automake, and libtool"].  A good presentation on these as well as "make" is [http://www.suse.de/~sh/automake/automake.pdf "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer].


If you include some self-tests (and that's a good idea), put them in a separate "%check" section that immediately follows the "%build" area, instead of including them in %build.  That way, it will be easy for the system to skip unnecessary self-tests.
To override makefile variables, pass them as parameters to <code>make</code>:
  %make_build CFLAGS="%{optflags}" BINDIR=%{_bindir}


=== %check section ===
More more information, see [http://sourceware.org/autobook/ "GNU autoconf, automake, and libtool"] and [http://web.archive.org/web/20090411003817/http://www.suse.de/~sh/automake/automake.pdf "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer].


The "%check" section does testing, often it's "make test".
Some programs use <code>cmake</code>. See [[Packaging/cmake]].
This is not documented in many other sources of RPM info.


=== %install section ===
=== %install section ===


The "%install" section is a set of script commands to "install" the program. The commands in this section should copy the files from a directory inside the "build directory" %{_builddir} (normally ~/rpmbuild/BUILD/''something'') into the build root directory, %{buildroot} (normally /var/tmp/''something''), creating the directories inside %{buildroot} as necessary.
This section involves script commands to "install" the program, copying the relevant files from <code>%{_builddir}</code> to <code>%{buildroot}</code> (which usually means from <code>~/rpmbuild/BUILD</code> to <code>~/rpmbuild/BUILDROOT</code>) and creating directories inside <code>%{buildroot}</code> as necessary.


'''Watch out''': Some of the terminology is very misleading:
Some of the terminology can be misleading:
* The "build directory" (under which compilations occur during %build) and the "build root" (where files are copied into during the %install process) are '''different'''. The point of the %install process is to copy files, such as those under the build directory, to the right place in the build root. Perhaps "buildroot" should be called "installroot", but it's too late now, the terminology is entrenched.
* The "build directory", also known as <code>%{_builddir}</code> is not the same as the "build root", also known as <code>%{buildroot}</code>. Compilation occurs in the former directory, while files to be packaged are copied from the former to the latter.
* The build directory is normally ~/rpmbuild/BUILD.  The %prep stage will normally create a subdirectory underneath the build directory as part of %setup.  During during %build, the current directory will actually start at %{buildsubdir}, that newly-created  subdirectory under the build directory.  Typically %{buildsubdir} is something like ~/rpmbuild/BUILD/%{name}-%{version}.
* During the %build section, the current directory will start at <code>%{buildsubdir}</code>, which is the subdirectory within <code>%{_builddir}</code> that was created during %prep stage. This is usually something like <code>~/rpmbuild/BUILD/%{name}-%{version}</code>.
* The "%install" script is ''not'' used when the binary rpm package is installed by the end-user!! The term "%install" is misleading, in fact, the script must ''not'' install the programs in the REAL final locations (e.g., in /usr/bin), but under the buildroot %{buildroot}.
* 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.


As noted in the guidelines,  "when adding file copying commands in the spec file, consider using a command that preserves the files' timestamps, eg. cp -p or install -p".  So, if the makefile lets you override the install command (typically named INSTALL), you might want something like INSTALL="install -p" as a make parameter.
Normally, some variation of "<code>make install</code>" is performed here:
 
Normally, the install script would first erase the %{buildroot} directory, and then do some variation of "make install" (ideally using DESTDIR=%{buildroot}, if the program supports it). Here's an example of an %install section:
  %install
  %install
  rm -rf %{buildroot}
  %make_install
make DESTDIR=%{buildroot} INSTALL="install -p" install


Many older RPM documents suggest using "%makeinstall", which ''might'' work if "make install" doesn't support DESTDIR. However, as noted in the Fedora guidelines, "Fedora's RPM includes a %makeinstall macro but it must NOT be used when make install DESTDIR=%{buildroot} works. %makeinstall is a kludge that can work with Makefiles that don't make use of the DESTDIR variable..." - but sometimes it has subtle failures.  See the Fedora guidelines if you want the details.
Ideally you should use %make_install which is equivalent to [http://www.gnu.org/prep/standards/html_node/DESTDIR.html <code>DESTDIR=%{buildroot}</code>] 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.


So, if there's no "make install", or "make install" doesn't support DESTDIR, you may have to do things by hand. So if there is no "make install", it would do some sort of sequence that would create directories that weren't already created by the "BuildRequires" packages (typically using install -d), followed by copying of files from the current directory (inside the build directory) into the buildroot directory. For example:
If the program does not support <code>DESTDIR</code> (and only if), you can workaround it in one of several (inferior) ways:
* Patch the makefile so that is supports <code>DESTDIR</code>. Create directories inside <code>DESTDIR</code> where necessary and submit the patch upstream.
* Use the "<code>%makeinstall</code>" macro. This method might work, but can lead to subtle failures. It expands to something like "<code>make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install</code>", which can result in some programs failing to work properly. Create directories inside <code>%{buildroot}</code> where necessary.
* Consider using the <code>auto-destdir</code> package. This requires "<code>BuildRequires: auto-destdir</code>", and changing "<code>make install</code>" to "<code>make-redir DESTDIR=%{buildroot} install</code>". This only works well if the installation uses only certain common commands to install files, like <code>cp</code> and <code>install</code>.
* Perform the installation by hand. This would involve creating the necessary directories under <code>%{buildroot}</code> and copying files from <code>%{_builddir}</code> to <code>%{buildroot}</code>. Be especially careful with updates, which often contain new or changed filenames. An example of this procedure:
  %install
  %install
  rm -rf %{buildroot}
  mkdir -p %{buildroot}%{_bindir}/
  cp -p mycommand %{buildroot}%{_bindir}/
  cp -p mycommand %{buildroot}%{_bindir}/
=== %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 %install section, since files in %buildroot may be tested) instead of within the %build section itself, so that they can be easily skipped when necessary.
Often, this section contains:
make test
Sometimes it can be:
make check
Please explore the Makefile and choose the appropriate way.


=== %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 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. Usually this is %defattr(-,root,root,-).
The <code>%defattr</code> sets 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/bin/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 files you copied into %{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 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 lines in the <code>%files</code> section; seperate them with a space. See [http://ftp.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html Max RPM section on %files directives].
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 an appropriate directory under <code>/usr/share/doc</code>, whose ownership does not need to be declared.
'''Note:''' If specifying a <code>%doc</code> entry, rpmbuild < 4.9.1 removes the doc directory it installs files into before installing them. This means that files already in it, for example installed in the <code>%install</code> section, are removed and do not end up in the package. If you want to install some files in the <code>%install</code> section, install them into a temporary staging directory inside the build dir (not build root), for example <code>_docs_staging</code>, and include them in the in the <code>%files</code> list like <code>%doc _docs_staging/*</code>.
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
"<code>%attr(mode, user, group)</code>" can be used for finer control over permissions, where a "<code>-</code>" means use the default:
%attr(0600, root, root) FOO.BAR
If a file is in particular natural language, use <code>%lang</code> to note that:
%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*


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 modem, user, or group.  You don't need to claim ownership of the /usr/share/doc/%{name} directory, that's automatic.  Any %doc entry must must not affect the runtime of the application (if it is in %doc, the program must run properly if it is not present).
Programs using Locale files should follow the [[Packaging:Guidelines#Handling_Locale_Files|recommended method of handling i18n files]]:
* find the filenames in the <code>%install</code> step: <code> %find_lang ${name}</code>
* add the required build dependencies: <code>BuildRequires: gettext</code>
* use the found filenames: <code>%files -f ${name}.lang</code>


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).
The <code>%readme</code> prefix is '''not''' valid in Fedora.


==== %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.  Executables that should not normally be executed directly by users or administrators should (but are executed by other parts of your package) 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>.  ([[Packaging:Guidelines#Limited_usage_of_.2Fopt.2C_.2Fetc.2Fopt.2C_and_.2Fvar.2Fopt|reference]])
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, Perl and Systemd), 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 413: Line 631:
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
  %doc README LICENSE
  %license LICENSE COPYING
  %{_bindir}/*
  %{_bindir}/*
  %{_sbindir}/*
  %{_sbindir}/*
  %{_datadir}/%{name}/
  %{_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 ===
=== 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:
When an end-user installs the RPM, you may want some commands to be run. This can be achieved through scriptlets. See [[Packaging:Scriptlets]].
 
Scriptlets can be run:
* before ('''<code>%pre</code>''') or after ('''<code>%post</code>''') a package is installed
* before ('''<code>%preun</code>''') or after ('''<code>%postun</code>''') a package is uninstalled
* at the start ('''<code>%pretrans</code>''') or end ('''<code>%posttrans</code>''') of a transaction
 
For example, every binary RPM package that stores shared library files in any of the dynamic linker's default paths, must call <code>ldconfig</code> in <code>%post</code> and <code>%postun</code>. If the package has multiple subpackages with libraries, each subpackage should also perform the same actions.
  %post -p /sbin/ldconfig
  %post -p /sbin/ldconfig
  %postun -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 only running a single command, then the "<code>-p</code>" option runs the adjacent command without invoking the shell. However, for several commands, omit this option and include the shell commands beneath.
If there are no following lines, then using /sbin/ldconfig as the "command processor" is minor efficiency improvement
(because 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.
If you run any programs within the scriptlets, then you must specify any requirements in the form "<code>Requires(CONTEXT)</code>" (e.g. <code>Requires(post)</code>).
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)".


For example, after adding an info manual to the system the dir file
<code>%pre</code>, <code>%post</code>, <code>%preun</code>, and <code>%postun</code> provide the argument <code>$1</code>, 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 <code>2</code>, but instead check if they are greater than or equal to <code>2</code>. For <code>%pretrans</code> and <code>%posttrans</code>, <code>$1</code> is always <code>0</code>.
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:


For example, if the package installs an info manual, then the info manual index must be updated with <code>install-info</code> from the <code>info</code> package. Firstly, there is no guarantee that the <code>info</code> package will be available unless we explicitly declare it as required, and secondly, we don't want to fail completely if <code>install-info</code> fails:
  Requires(post): info
  Requires(post): info
  Requires(preun): info
  Requires(preun): info
Line 449: Line 676:
  fi
  fi


Another scriptlet-like abilility are ''triggers''.  You can define triggers for when ''other'' packages
There is one other glitch related to installing info manuals. The <code>install-info</code> command will update the info directory, so we should delete the useless empty directory from the %{buildroot} during the <code>%install</code> section:
are installed or uninstalled. See ''Maximum RPM'' for more.
rm -f %{buildroot}%{_infodir}/dir
 
Another scriptlet-like ability are "triggers", which can be run for your package when other packages are installed or uninstalled. See [http://ftp.rpm.org/api/4.4.2.2/triggers.html RPM Triggers].


=== Macros ===
=== Macros ===


Spec files may contain "macro" references (text beginning with "%"), which are replaced with other values.
Macros are text in the format <code>%{string}</code>. Typical macros:
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| 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
! Macro !! Typical Expansion !! Meaning
|-
| <code>%{_bindir}</code> || <code>/usr/bin</code> || Binary directory: where executables are usually stored.
|-
| <code>%{_builddir}</code> || <code>~/rpmbuild/BUILD</code> || Build directory: files are compiled within a subdirectory of the build directory. See <code>%buildsubdir</code>.
|-
|-
| %{_bindir} || /usr/bin
| <code>%{buildroot}</code> || <code>~/rpmbuild/BUILDROOT/%{name}...</code> || Build root: where files are "installed" during the <code>%install</code> stage, which copies files from a subdirectory of <code>%{_builddir}</code> to a subdirectory of <code>%{buildroot}</code>. (Historically, <code>%{buildroot}</code> was in "/var/tmp/".)
|-
|-
| %{_builddir} || ~/rpmbuild/BUILD (build directory; see %buildsubdir)
| <code>%{buildsubdir}</code> || <code>%{_builddir}/%{name}</code> || Build subdirectory: a subdirectory within <code>%{_builddir}</code> where files are compiled during the <code>%build</code> stage. It is set after <code>%autosetup</code>.
|-
|-
| %{buildroot} || /var/tmp/... - buildroot, where files are "installed" during %install
| <code>%{_datadir}</code> || <code>/usr/share</code> || Share directory.
|-
|-
| %{buildsubdir} || %{_builddir}/%{name} - where files are compiled during %build. It's under %{_builddir}, set after %setup.
| <code>%{_defaultdocdir}</code> || <code>/usr/share/doc</code> || Default documentation directory.
|-
|-
| %{_datadir} || /usr/share
| <code>%{dist}</code> || <code>.fc''NUMBER''</code> || Distribution+version short name (e.g. "<code>.fc{{FedoraVersion}}</code>")
|-
|-
| %{_includedir} || /usr/include
| <code>%{fedora}</code> || <code>''NUMBER''</code> || Number of fedora release (e.g. "<code>{{FedoraVersion}}</code>")
|-
|-
| %{_infodir} || /usr/share/info
| <code>%{_includedir}</code> || <code>/usr/include</code>
|-
|-
| %{_initrddir} || /etc/rc.d/init.d
| <code>%{_infodir}</code> || <code>/usr/share/info</code>
|-
|-
| %{_libdir} || /usr/lib
| <code>%{_initrddir}</code> || <code>/etc/rc.d/init.d</code>
|-
|-
| %{_libexecdir} || /usr/libexec
| <code>%{_libdir}</code> || <code>/usr/lib</code>
|-
|-
| %{_localstatedir} || /var
| <code>%{_libexecdir}</code> || <code>/usr/libexec</code>
|-
|-
| %{_mandir} || /usr/share/man
| <code>%{_localstatedir}</code> || <code>/var</code>
|-
|-
| %{name} || Name of package, set by Name: tag
| <code>%{_mandir}</code> || <code>/usr/share/man</code>
|-
|-
| %{_sbindir} || /usr/sbin
| <code>%{name}</code> || || Name of package, set by Name: tag
|-
|-
| %{_sharedstatedir} || /usr/com
| <code>%{_sbindir}</code> || <code>/usr/sbin</code>
|-
|-
| %{_sysconfdir} || /etc
| <code>%{_sharedstatedir}</code> || <code>/var/lib</code>
|-
|-
| %{version} || Version of package, set by Version: tag
| <code>%{_sysconfdir}</code> || <code>/etc</code>
|-
| <code>%{version}</code> || || Version of package, set by Version: tag
|}
|}


To see more about macros you
Learn more about macros by looking in <code>/etc/rpm/*</code> and <code>/usr/lib/rpm</code>, especially <code>/usr/lib/rpm/macros</code>. Also use <code>rpm --showrc</code> to show values that RPM will use for macros (altered by <code>rpmrc</code> and macro configuration files).
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 %define; be sure to define them before you use them. Macro definitions
You can set your own macro values using %global, but be sure to define them before you use them. (Macro definitions can also refer to other macros.) For example:
can refer to other macros.  For example:
  %global date 2012-02-08
  %define 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:
Use the "<code>-E</code>" option of <code>rpmbuild</code> to find the value of a macro in a SPEC file:
  rpmbuild -E '%{_bindir}' myfile.spec
  rpmbuild -E '%{_bindir}' myfile.spec


[[Packaging/RPMMacros]] has more information on macros, as does
Also see [[Packaging/RPMMacros]] and [https://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s07.html RPM Guide chapter 9].
[http://docs.fedoraproject.org/drafts/rpm-guide-en/ch09s07.html RPM Guide chapter 9].


=== Other tags ===
=== Other tags ===


We noted the "Requires" and "BuildRequires" tags earlier.
In addition to Requires and BuildRequires tags, you can also use these for controlling dependencies:
There are a few other tags for controlling dependencies:
* '''Provides''': list virtual package names that this package provides. For example, there might be a package "<code>foo</code>" that demands a particular functionality "bar" from another program. If there are several packages that can satisfy that demand, those packages can specify "<code>Provides: bar</code>" and the "<code>foo</code>" package can specify "<code>Requires: bar</code>". You could also use the [http://dailypackage.fedorabook.com/index.php?/archives/6-Wednesday-Why-The-Alternatives-System.html "alternatives" system], but avoid if multiple users on the same system might want different default, as these settings are system-wide. Use "<code>rpm -q --provides PACKAGENAME</code>" to see what a given package provides. Some examples of virtual packages in Fedora:
Provides, Obsoletes, Conflicts, and BuildConflicts.
** MTA: Used for mail transport agents, such as sendmail.
* "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. 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:
** tex(latex): Used for latex
** ''MTA'' : Used for mail transport agents, such as sendmail.
* '''Obsoletes''': remove another named package(s) when this package is installed. Use when the package name changes or when it totally replaces a different package.
** ''tex(latex)'' : Used for latex
* '''Conflicts''': state what other packages cannot be installed simultaneously to this one. Avoid this if you can. See [[Packaging/Conflicts]].
* "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.
* '''BuildConflicts''': state what packages cannot be installed when building this package. Avoid this if you can.
* "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.
To manage different architectures, there are two tags:
* '''ExcludeArch''': to exclude an architecture on which the package doesn't build. For example:
ExcludeArch: ppc
* '''ExclusiveArch''': to include only the specified architecture. Avoid this unless absolutely correct.
Valid architectures are listed at [[Architectures]].
 
=== Subpackages ===
 
A SPEC file can define several binary package. In other words, one SRPM with one SPEC file can result in several RPMS. Note that there is still only one creation (%prep, %build, %install etc.) process. <code>name-doc</code> and <code>name-devel</code> subpackages are common for documentation and development files respectively.
 
Use the <code>%package</code> directive to start defining a subpackage:
%package subpackage_name
 
After each <code>%package</code> directive, list the tags for the subpackage. This should at least include the Summary and Group tags, as well as the <code>%description subpackage_name</code> and <code>%files subpackage_name</code> directives:
 
Anything not specified by the subpackage will be inherited from its parent.
 
By default, if the package name is "<code>foo</code>" and the subpackage name is "<code>bar</code>", then the resulting subpackage will be "<code>foo-bar</code>". You can override it with the "<code>-n</code>" option (but you'll need to use it in all other directives too if you specify it here):
%package -n new_subpackage_name
 
[http://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch10s04.html See the RPM Guide section on subpackages] for more information.
 
=== Conditionals ===
 
You can insert conditional statements, for example to test if you are creating a binary for a certain architecture:
%ifarch ARCHITECTURE_NAME
the negated version with:
%ifnarch ARCHITECTURE_NAME
or the more general conditional:
%if TRUE_OR_FALSE
 
There is an optional "<code>%else</code>" section; all of these are closed with "<code>%endif</code>".
 
=== 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
[[Packaging/Guidelines#Application_Specific_Guidelines|Application Specific Guidelines of Packaging/Guidelines]].  Examples of application-specific guidelines are those for:
* [[Packaging:Cmake|Cmake]]
* [[Packaging:Emacs|Emacs]]
 
Failing that, some other ways of finding application-specific help are:
* The 'SEARCH' command on Fedoraproject.org.
* [[PackagingDrafts]]
* A [[SIGs|Special Interest Group (SIG)]]
* [[Special:PrefixIndex/Packaging|Wiki pages prefixed with 'Packaging']]


=== Miscellaneous hints ===
=== Miscellaneous hints ===
[[Packaging/FrequentlyMadeMistakes]] has information on frequently-made mistakes. There are also some recommendations and controversial tricks on
[[PackageMaintainers/Packaging Tricks]].
Try to write your SPEC files so that it is likely to work when a new release is made upstream, without any changes aside from bumping the version number and refreshing the source files. 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:
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
   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.
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.
You might not want to start services, because in a big install that could slow things down. If you install an init or systemd script, consider using <code>chkconfig</code> or <code>systemctl</code> to arrange for the service to be started/stopped on the next reboot.  Before uninstalling, you should normally try to stop its services if they are running.


Uninstall should reverse most changes made during installation, but don't remove any user-created files.
Uninstalling 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:
Normally, if there are binary executables, then debugging symbols are stripped from the normal binary packages and placed into a <code>name-debug</code> subpackage. If this shouldn't happen, you can disable the stripping and creation of this subpackage by putting this at the top of your SPEC:
  %define _enable_debug_package 0
  %global _enable_debug_package 0
  %define debug_package %{nil}
  %global debug_package %{nil}
  %define __os_install_post /usr/lib/rpm/brp-compress %{nil}
  %global __os_install_post /usr/lib/rpm/brp-compress %{nil}


There are also some recommendations and controversial tricks on
To prevent stripping you may also need to do this in the <code>%install</code> section:
[[PackageMaintainers/PackagingTricks]].
export DONT_STRIP=1


Some older documents about RPM have the most information, but some older documents make claims that are no longer true:
A way to check for the version of Fedora in a SPEC file for conditional builds is:
* 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.
%if 0%{?fedora} <= <version>
* the %install process does not install files in their final location.  Instead, it "installs" files to the buildroot.
The <code>?</code> causes the macro to evaluate to evaluate to blank if <code>%fedora</code> is not defined. This causes the end result to be the <code>0</code> (which is a number and thus fine), while not interfering with the result if there is actually a value for <code>%fedora</code>. (Note that this trick does not work in Koji "scratch" builds, where <code>%fedora</code> is set during the creation of a SRPM.)
* The "rpm" command no longer creates packages (e.g., "rpm -ba" was once legal). Use the separate "rpmbuild" program instead.


== Quick test with rpmlint ==
GUI programs must have a desktop entry so that people can invoke it from the graphical desktop menu. For <code>.desktop</code> files, see [[Packaging/Guidelines#Desktop_files|Fedora packaging guidelines for desktop files]] and [http://standards.freedesktop.org/desktop-entry-spec/latest/ desktop entry spec]. For icons within <code>/usr/share/icons</code>, see [http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html icon theme spec].


Before trying to build anything from it, you might want to run ''rpmlint'' on the spec file:
== Building the binary package ==
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
=== Test with rpmlint ===
rpmlint is excessively noisy.
The
[http://fedoraproject.org/wiki/Packaging/Guidelines#Use_rpmlint Fedora packaging guidelines]
explain which ones to ignore, e.g., ignore "no-packager-tag" and "no-signature" errors.


== Creating RPMs from the spec file ==
To catch many common errors early, run <code>rpmlint</code> on your SPEC file before trying to build anything from it:
$ rpmlint program.spec
If the reported error doesn't make sense, run it again with the "<code>-i</code>" option for longer messages.


Once you've create a spec file, say "program.spec", you can create
Aim to have no errors, but sometimes <code>rpmlint</code> reports false positives. The [[Packaging/Guidelines#Use_rpmlint|Fedora packaging guidelines]]
source and binary RPMs by simply running this:
explains which ones to ignore.
  $ rpmbuild --clean -ba program.spec


This will attempt to perform the following stages:
=== Create binary RPMS from the SPEC file ===
* %prep (preparation) stage, which uncompresses and installs the sources and patches into %_builddir (a subdirectory of ~/rpmbuild/BUILD)
* %build stage, which builds (e.g., compiles) the files to be installed in %_builddir. Usually this is some equivalent of "make".
* %install stage, which copies the files from the build directory %_builddir (which would be under ~/rpmbuild/BUILD) into the buildroot directory, %{buildroot}.  The buildroot directory is set by the earlier "BuildRoot:"; if you leave it to its normal value beginning %{_tmppath}/%{name}..., then the buildroot will be inside /var/tmp.
* Create the binary and source RPM packages (.rpm and .src.rpm files).  The binary RPM files are created using the information from the %files list.


Watch out: the "build directory" (where compilations occur during %build) and the "build root" (where files are installed during the %install) are ''different''.
Once you've created your SPEC file, build the SRPM and binary RPMS by running this:
$ rpmbuild -ba program.spec


When things go wrong, you can "cd" into the appropriate directory and see what's left over.
If successful, RPMS will be created within <code>~/rpmbuild/RPMS</code> and SRPMS will be created within <code>~/rpmbuild/SRPMS</code>.
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 it is successful, you'll find your binary RPM(s) in the "~/rpmbuild/RPMS/"
If it fails, go to the appropriate directory and see what is left over. To help debug, you can skip earlier stages that succeeded with the "<code>--short-circuit</code>" option. For example, to restart at the <code>%install</code> stage (skipping earlier stages), do this:
subdirectory, and the source RPM in "~/rpmbuild/SRPMS".
$ rpmbuild -bi --short-circuit program.spec


If you just want to create a source RPM (.src.rpm), do this in the SPECS directory:
If you just want to create an SRPM (which does not run the <code>%prep</code> or <code>%build</code> or other stages), run this:
  rpmbuild -bs program.spec
  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 ==
=== Testing binary RPMS with rpmlint ===


If you "cd" to the "~/rpmbuild/RPMS" directory, and then cd to the architecture subdirectory,
<code>rpmlint</code> can be run on SPEC files, RPMS and SRPMS to check for errors. You need to eliminate or justify warnings before posting a package. [[Common_Rpmlint_issues|This page]] offers explanations for some of the common issues that come up. If you are in the SPECS directory, do this:
you'll find some binary rpms. You can quickly see their files and their permissions by using rpmls
$ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm
(check to see that they are what you expect):
 
Enter the <code>~/rpmbuild/RPMS</code> directory and into the architecture subdirectory. You will find some binary RPMS. Quickly see their files and permissions (to check whether they are correct) by doing:
  $ rpmls *.rpm
  $ rpmls *.rpm


Run rpmlint on the ''binary'' RPM (rpmlint works on both .spec and RPM files, and finds different things):
If they look fine, install them as root:
  $ rpmlint *.rpm
  # rpm -ivp package1.rpm package2.rpm package3.rpm ...
 
Test the programs in a few different ways to see if everything works correctly. If it is a GUI tool, make sure it shows up in the desktop menu, otherwise the <code>.desktop</code> entry is wrong.


If those look okay, you can become root and try to install them:
Uninstall packages later by doing:
  # rpm -ivp XYZ1.rpm XYZ2.rpm XYZ3.rpm ...
  # rpm -e package1 package2 package3


Then, you can test them out.  If it's a command-line tool, can you invoke it
== Mock and Koji ==
without prepending /usr/bin?  If it's a GUI tool, does it show up in the menu
(if it doesn't, something is wrong with your .desktop entry).


You can uninstall them later using:
[[Projects/Mock|Mock]] is a powerful tool that uses the SRPM you have created to build binary packages within a nearly empty environment. This can reveal if you have accurate build dependencies. If it fails, then you forgot to list something in BuildRequires. See [[Using Mock to test package builds]]. Once your account is a member of the "<code>mock</code>" group, you can run commands like this to do local testing:
  # rpm -e XYZ1 XYZ2 XYZ3
  $ mock -r fedora-23-i386 rebuild path_to_source_RPM


If that all works, you can use Mock to do a rigorous test that you have
You can use Koji (which uses <code>mock</code>) 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 SRPM on a variety of platforms by running commands like:
accurate build requirements. See [[PackageMaintainers/MockTricks]]
  $ koji build --scratch f23 path_to_source_RPM
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


Once Mock works on your system, you can use Koji (which uses Mock) to do builds on
Replace <code>f23</code> with any later release of Fedora, or <code>rawhide</code>.
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


== Helpful tools from rpmdevtools ==
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. If you need to build against a package that is not yet a stable released update, submit a Koji buildroot override request via Bodhi. If it's not your own package you depend on, contact its maintainer(s). [Before Bodhi could handle Koji buildroot override requests, the old method has been to file a ticket with rel-eng at: https://fedorahosted.org/rel-eng/newticket and request that that package be added as a buildroot override.]


The "rpmdevtools" package has a number of helpful tools; "rpm -qil rpmdevtools" will show you what it installs.
== Helpful tools ==


One particularly useful tool is rpmdev-bumpspec, which has this form:
The <code>rpmdevtools</code> package has a number of helpful tools; "<code>rpm -qil rpmdevtools</code>" will show you what it installs.
* <code>rpmdev-bumpspec</code> : bump the release tag in the spec file and add a changelog comment with the right date and version format:
  rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
  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 "- ".
 
DNF download plugin (from core DNF plugins) is also useful:
* <code>dnf download</code> : download the SRPM of the package by running:
dnf download --source PACKAGENAME
 
The <code>auto-buildrequires</code> package has a pair of nice tools for helping to figure out the proper BuildRequires entries.  After installing this package, replace "<code>rpmbuild</code>" with "<code>auto-br-rpmbuild</code>" and you'll see an automatically generated BuildRequires list.
 
You might find [http://rust.sourceforge.net/ RUST] useful (GPL), though it does not create SPEC files of suitable quality for Fedora packages. [http://kitenet.net/~joey/code/alien/ Alien] converts between package formats. It won't produce clean SRPMS, but converting an existing package might provide helpful information.
 
If you are thinking about packing your rpm for Fedora, be sure you run your packages through [https://fedorahosted.org/FedoraReview/ Fedora Review], which helps ensure that you comply to the [[Packaging:Guidelines|Packaging Guidelines]].
 
Finally, [https://github.com/alanfranz/docker-rpm-builder docker-rpm-builder] (APL 2.0) uses [http://www.docker.com Docker] to build RPM packages; while using rpmbuild requires building on the same host distro as the target, and mock works fine on Fedora/Centos/RHEL distributions for any target, '''this last tool works fine whenever Docker can run'''.
 
If you want to build your package for diferent distribution and architectures and to have publicly accesible dnf repository, you can submit your src.rpm to [https://copr.fedoraproject.org Copr].
 
If you need to sign your new package, use <code>rpmsign</code> tool from
<code>rpm-sign</code> package.


== Guidelines and rules ==
== Guidelines and rules ==


When you create your packages, you'll need to follow the following rules and guidelines:
When you create your packages, you'll need to follow the following rules and guidelines:
* [[PackageMaintainers/Join| How to join the Fedora Package Collection Maintainers]] - describes the process for becoming a Fedora package maintainer
* [[Join the package collection maintainers|How to join the Fedora Package Collection Maintainers]]
* [[Packaging/Guidelines|Packaging Guidelines]]
* [[Packaging:Guidelines|Packaging Guidelines]]
* [[Packaging/NamingGuidelines| Package Naming Guidelines]]  
* [[Packaging:NamingGuidelines|Package Naming Guidelines]]
* [[Packaging/DistTag| Dist Tag Guidelines]]  
* [[Packaging:LicensingGuidelines|Package Licensing Guidelines]]
* [[Packaging/ReviewGuidelines| Package Review Guidelines]]
* [[Packaging:DistTag|Dist Tag Guidelines]]  
* [[Packaging:ReviewGuidelines|Package Review Guidelines]]
 
There are many official guidelines that will help you with specific circumstances (e.g. Java programs, OCaml programs, GNOME programs). You can also learn more from the [[SIGs]] and [[:Category:Package Maintainers|Package Maintainers]] sections.
 
[[Special:Prefixindex/Packaging|You can also see the list of all Wiki pages about Packaging]] to see if any apply.


There are many official guidelines that will help you with specific circumstances
Failing that, you might find some useful recommendations in the unofficial [[:Category:Packaging_guidelines_drafts|draft guidelines category]] and [[PackagingDrafts|Packaging Drafts To Do]].
(Java programs, OCaml programs, GNOME programs, etc.); the
<!-- This used to link to a search, but that is now broken and I don't know how to do it without an external link [[Special:Search?ns0=1&search=PackagingDrafts%2F&searchx=Search|Packaging Drafts]] -->
[[Packaging/Guidelines|Packaging Guidelines]] include cross-references to those guidelines.
You can also learn more from the [[SIGs]] and  
[[PackageMaintainers|Package Maintainers]] sections.
[https://fedoraproject.org/wiki/Special:Prefixindex/Packaging 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
[https://fedoraproject.org/wiki/Special:Search?ns0=1&search=PackagingDrafts%2F&searchx=Search Packaging Drafts] and [https://fedoraproject.org/wiki/PackagingDrafts Packaging Drafts To Do].
These are unofficial, obviously.
You might find ideas from [http://en.opensuse.org/Packaging SuSE],
You might find ideas from [http://en.opensuse.org/Packaging SuSE],
[http://www.debian.org/doc/debian-policy/ Debian], but
[http://www.debian.org/doc/debian-policy/ Debian], but
[http://www.mail-archive.com/distributions@lists.freedesktop.org/msg00156.html distributions differ in their rules], so do not presume they can be used directly.
[http://www.mail-archive.com/distributions@lists.freedesktop.org/msg00156.html 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 [[Legal:Fedora_Project_Contributor_Agreement|FPCA]].'''
== Maintaining the package ==
Once your package has been accepted, you and your co-maintainers will need to maintain it. See [[Package update HOWTO]] and [[Package update guidelines]]. 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:
* [http://www.dwheeler.com/essays/releasing-floss-software.html Releasing Free/Libre/Open Source Software (FLOSS) for Source Installation] (a quick summary)
* [http://www.gnu.org/prep/standards/html_node/Managing-Releases.html GNU Coding Standards release process]
* [http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/ Software Release Practice HOWTO]
* [http://www.pathname.com/fhs/ Filesystem Hierarchy Standard (FHS)]
* [http://offog.org/articles/packaging/ Packaging Unix software]


== For more information ==
== For more information ==


The [[PackageMaintainers|Package Maintainers]] page links to many other useful pages, and the
The [[:Category:Package Maintainers|Package Maintainers]] page links to many other useful pages, and the
[[PackageMaintainers/UpdatingPackageHowTo|Updating Package HOWTO]] describes how to update
[[Package update HOWTO]] describes how to update an existing package you already maintain in Fedora.
an existing package you already maintain in Fedora.


For more information, outside of the Fedora Wiki, see:
For more information, outside of the Fedora Wiki, see:
* [https://developer.fedoraproject.org/deployment/rpm/about.html A brief RPM Packaging overview] on the Fedora Developer Portal
* [http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/ How to build RPM packages on Fedora] - very brief run-through
* [http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/ How to build RPM packages on Fedora] - very brief run-through
* Packaging software with RPM (developerWorks) [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3]
* Packaging software with RPM (developerWorks) [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3]
* [http://koti.welho.com/vskytta/packagers-handbook/packagers-handbook.html Fedora Packager's Handbook]
* Fedora Classroom had an IRC session on packaging and you can refer to the logs at https://fedoraproject.org/wiki/Building_RPM_packages_%2820090405%29
* [http://www.redhatmagazine.com/2008/02/28/when-sally-met-eddie-the-fedora-package-story/ When Sally met Eddie] - a simple tale, but little detail
<!-- Server not found: * [http://koti.welho.com/vskytta/packagers-handbook/packagers-handbook.html Fedora Packager's Handbook]  
* [http://rpm.org/max-rpm-snapshot/ Maximum RPM Book] - most complete information, but in some cases old/obsolete
I read the above via https://web.archive.org/web/20120427181445/http://koti.welho.com/vskytta/packagers-handbook/packagers-handbook.html - but its just as of date and incomplete. Seems pointless to restore the link. --Argonel 11 September 2017
* [http://docs.fedoraproject.org/drafts/rpm-guide-en/ch-creating-rpms.html RPM Guide, section on creating RPMs] - this has lots of good information and focuses on Fedora, but is a draft
-->
* [http://docs.fedoraproject.org/developers-guide/ch-rpm-building.html Developer's guide, section on building RPMs]
 
* [http://www.gurulabs.com/GURULABS-RPM-LAB/GURULABS-RPM-GUIDE-v1.0.PDF Creating RPMS slides] from Guru Labs
<!-- Redirect to opensource.com: * [http://www.redhatmagazine.com/2008/02/28/when-sally-met-eddie-the-fedora-package-story/ When Sally met Eddie] - a simple tale, but little detail -->
* [http://freshrpms.net/docs/fight/ The fight, my first attempt to make a readable rpm package building introduction.]
* [http://ftp.rpm.org/max-rpm/ Maximum RPM Book] - most complete information, but in some cases old/obsolete
* [http://genetikayos.com/code/repos/rpm-tutorial/trunk/rpm-tutorial.html RPM Tutorial (Fullhart)]
* [http://docs-old.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html RPM Guide, section on creating RPMs] - this has lots of good information, and is slightly more up-to-date, but is a draft
* [http://web.archive.org/web/20100109050207/http://docs.fedoraproject.org/developers-guide/ch-rpm-building.html Developer's guide, section on building RPMs] - via archive.org, disappeared in 2010
<!-- URL not found: * [http://www.gurulabs.com/GURULABS-RPM-LAB/GURULABS-RPM-GUIDE-v1.0.PDF Creating RPMS slides] from Guru Labs -->
* [http://freshrpms.net/docs/fight/ "The fight", Mattias Saou's first attempt to make a readable rpm package building introduction. ca. 2003]
<!-- Page not found: * [http://www-uxsup.csx.cam.ac.uk/talks/rpmbuild/rpmbuild.pdf Cambridge RPM tutorial] is a presentation on creating basic RPMs -->
* [http://en.tldp.org/HOWTO/RPM-HOWTO/index.html RPM HOWTO: RPM at Idle by Donnie Barnes]
* [http://en.tldp.org/HOWTO/RPM-HOWTO/index.html RPM HOWTO: RPM at Idle by Donnie Barnes]
* [http://home.fnal.gov/~dawson/rpms/howto/index.html RPM HowTo] by Dawson
<!-- Page not found: * [http://home.fnal.gov/~dawson/rpms/howto/index.html RPM HowTo by Dawson] -->
* [http://en.opensuse.org/SUSE_Build_Tutorial SuSE build tutorial] - but about SuSE, not Fedora. [http://en.opensuse.org/Build_Service/cross_distribution_package_how_to Cross-distribution package HOWTO] has hints if you're building one RPM for many distributions.
* [http://en.opensuse.org/Build_Service/cross_distribution_package_how_to Cross-distribution package HOWTO] has hints if you're building one RPM for many distributions.
* [http://wiki.mandriva.com/en/Development/Howto/RPM Mandriva Rpm HowTo (en)] ([http://www.mandrivaclub.com/xwiki/bin/view/KB/MandrivaRpmHowTo alt]) is an RPM tutorial, though for Mandriva (nee Mandrake).  Note: In Fedora, do ''not'' recompress original tarballs, as Mandriva suggests, because that would change their cryptographic hashes.
<!-- Server not found: * [http://wiki.mandriva.com/en/Development/Howto/RPM Mandriva Rpm HowTo (en)] is an RPM tutorial, though for Mandriva (nee Mandrake).  Note: In Fedora, do ''not'' recompress original tarballs, as Mandriva suggests, because that would change their cryptographic hashes. -->
* [http://linuxshellaccount.blogspot.com/2008/03/creating-your-own-linux-rpms-initial.html Creating Your Own Linux RPM's - The Initial Software Build] is another brief intro, but it makes the point that "The process of building RPM's is much simpler than creating packages for Solaris... Fewer steps, and the ability to add all of your software information into one specification file, makes for a much tighter (and easier to modify or reproduce) software packaging system."
* [http://linuxshellaccount.blogspot.com/2008/03/creating-your-own-linux-rpms-initial.html Creating Your Own Linux RPM's - The Initial Software Build] is another brief intro, but it makes the point that "The process of building RPM's is much simpler than creating packages for Solaris... Fewer steps, and the ability to add all of your software information into one specification file, makes for a much tighter (and easier to modify or reproduce) software packaging system."
* [http://fedoranews.org/alex/tutorial/rpm/ All you need to know about RPM] (more about installing packages than creating them)
* [http://fedoranews.org/alex/tutorial/rpm/ All you need to know about RPM] (more about installing packages than creating them)
Line 688: Line 969:
Note: The [http://rpm5.org/ 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 [http://www.rpm.org rpm.org].
Note: The [http://rpm5.org/ 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 [http://www.rpm.org rpm.org].
[http://lwn.net/Articles/236029/ lwn.net has a brief article] about this.
[http://lwn.net/Articles/236029/ lwn.net has a brief article] about this.
[[Category:Package Maintainers]]
[[Category:How to]]

Revision as of 01:35, 12 September 2017


Note.png
This document is under construction to better conform to the packaging guidelines and to use Package-x-generic-16.pngfedpkg instead of rpmbuild throughout. We apologize for any conflicting or confusing information while these changes are underway.

Introduction

This page describes in detail how to create an RPM package, and in particular how to create a specfile. Unlike other RPM guides, this page explains the specifics for Fedora with links to Fedora-specific guidelines and usage of Fedora-specific utilities. Despite the focus on Fedora, much of this document does apply to other RPM-based distributions.

Fedora Documentation had released a draft guide for packagers, see Packagers Guide. It is archived.

Please note that this document is merely a gentle introduction and will leave out many of the details which you may need in order to package more complicated software. It also assumes that you have familiarity with the shell and are familiar with the process of building and installing (outside of RPM) the software you wish to package. Finally, this document is NOT an official Fedora packaging guideline. This page is open for editing by the general Fedora packaging community, while the actual packaging guidelines are managed by the Packaging Committee. For reference, here are some of the most referenced guideline pages:

Packaging:Guidelines and Packaging:Naming contain the main guidelines. Having said that, this page should be compatible with them, though the guidelines do change over time and this page may diverge from them on occasion.

If you plan to submit a package to the official Fedora repository, you will also want to follow the procedure depicted in Join the package collection maintainers.

Some terminology

RPM
The package manager used by Fedora, Red Hat Enterprise Linux, Mageia, OpenSUSE and others. Originally RPM stood for "Red Hat Package Manager" but now it's just the recursive acronym "RPM Package Manager".
specfile
A plain text file containing information about a package and instructions used by RPM for actually compiling the included software. It is named by appending .spec to the name of the package.
tag
A string, generally capitalized and followed by a colon, which appears at the top of the specfile to provide some important data about the RPM, such as Name:, Version: or Summary:.
section
A segment of the specfile which tells RPM how to perform some portion of the package construction process. Many, but not all, sections contain code that is simply passed to the shell, though RPM has significant flexibility around this which will not be covered at all in this document.
section header
A short string, starting with % at the beginning of a line, which introduces a section. Examples include %description, %prep and %files.
macro
A short string, always prefixed by % and generally surrounded by curly brackets ({}) which RPM will convert to a different and usually longer string. Some macros can take arguments and some can be quite complex. Some macros are provided by RPM, some are part of Package-x-generic-16.pngredhat-rpm-config and Package-x-generic-16.pngfedora-rpm-macros, but many other packages also provide them. If you're curious, running rpm --showrc will show you all of the macros currently available on your system, but note that you really don't want to use most of the ones you see there. Note that some macros have named prefixed by underscores; the reasons for this are mostly lost to time.
The packaging guidelines have various suggestions and restrictions regarding the use of various sets of macros. This document will use what the guidelines recommend, but won't necessarily explain the reasons in detail.
You may, in looking at other packages, see macros used without curly brackets. There are situations where this isn't strictly necessary, but these guidelines will use them wherever possible to make it more obvious when macros are being used and to avoid going into the rules about when the brackets are needed and when they aren't.
mock
A system for building RPMs within their own separate small Fedora installation. This avoids the need to have a full set of build dependencies installed into your regular operating system installation, allows you to build packages for different Fedora releases, and in general is a good thing.
koji
The main Fedora build system: [1].

Editors for editing RPM spec files

Many editors (like text editors and IDEs) that are in the official repositories of Fedora have out-of-the-box syntax-highlighting support for RPM spec files, these include:

  • CodeEditor. It does not syntax-highlight the shell script code found in RPM spec files.
  • gedit. It does not syntax-highlight the shell script code found in RPM spec files.
  • GNU nano. It does not syntax-highlight the shell script code found in RPM spec files.
  • Joe. It does not syntax-highlight the shell script code found in RPM spec files.
  • Kate. It does not syntax-highlight the shell script code found in RPM spec files.
  • KWrite. It does not syntax-highlight the shell script code found in RPM spec files.
  • Pluma. It does not syntax-highlight the shell script code found in RPM spec files.
  • Vim (and, of course, its graphical counterpart, gVim). It also syntax-highlights the shell script code found in RPM spec files.

while the following are present in the official Fedora repositories but do not come with out-of-the-box syntax-highlighting for RPM Spec files, but do gain said support when optional packages/plugins are installed:

  • Eclipse can develop RPM spec file editing support when the RPM Spec file editor package is also installed. This package also provides code linting (checking for RPM packaging errors) and make it easier to navigate the spec file.
  • GNU Emacs has editing support for RPM spec files when the RPM spec mode package is installed.

Editors that are not in the official repositories of Fedora but are available for Fedora and, with the appropriate plugins, can syntax-highlight RPM spec files include:

Preparing your system

Before you create RPM packages on Fedora, you need to install some packaging tools and set up the account(s) you will use. Run this as root:

dnf install fedora-packager fedora-review

This will install the Package-x-generic-16.pngfedora-packager utilities needed to work with and build packages in the same manner used to maintain official Fedora packages, including the Package-x-generic-16.pngfedora-review tool used by package reviewers to check package quality.

Stop (medium size).png
You should never create your packages as the root user. Indeed, you should never perform anything other than specific administration tasks as root. Building RPMs as root is dangerous because it is possible for situations to exist (due to mistakes or typos in the spec file) for some package building operations to attempt to write files to system locations. You must always build as a normal user to avoid corrupting parts of your system. This document will generally use the Package-x-generic-16.pngmock system to build more complicated packages in a very safe manner.

As root, add yourself to the mock group:

usermod -a -G mock yourusername

This should be the last time you need root unless you wish to install packages you have developed.

You may afterwards need to run newgrp or log out and back in for this change to take effect. Run the id command to see if the "mock" group appears in your group list.

If you have already obtained a Fedora account and accepted the contributor agreement, you can also set up your fedora certificates and such. Just run (as your user, not as root):

fedora-packager-setup

If you wish, you can also create a separate user and use it for doing RPM development. You should make sure that user is part of the "mock" group and has run fedora-packager-setup.

First steps

To create an RPM package, you will need to create a directory to hold the package and, within that directory, the specfile. This file provides information about the software being packaged, instructions for unpacking it, building it and installing it, as well as a list of files which will be included in the package. You then run the fedpkg command with appropriate options, which will go through a series of steps to produce your package.

The construction of the specfile is often done iteratively (one relevant piece at a time), and that's what we'll do here. But first we'll need someplace to make our package as well as something to package. Run the following to create a directory to hold packaging work (called packaging-work), within it a place to hold our package (called "howdy), and within that a simple program to package (also called "howdy). You can use any location you like but the directory name for the package should match the name of the package.

mkdir -p ~/packaging-work/howdy
cd ~/packaging-work/howdy
cat << EOF > howdy
#!/bin/bash
echo "Howdy, partner!"
EOF
chmod 644 howdy

You should be able to run bash howdy and receive the expected output. Now we have something we can package, so let's start making a specfile. We'll start with a very minimal template (which will have to be expanded for anything more complicated than this example). Just start your editor on a new file called howdy.spec" and paste this in. Please use spaces and not tabs. It's not necessary to have everything like up but it does make it look nice.

Name:    howdy
Version: 1
Release: 1%{?dist}
Summary: Say hello, Texas style

License: Public Domain
Source0: howdy

%description
A simple program to greet the user, Texas style.

%install

%files

%changelog

So we've described the package, indicated a version and listed the one source file we have. We have an %install and a %files section, both of which are empty. Save your edits and run

fedpkg --release f39 local

This is called a "local build". Assuming no typos or other issues, you should get some output and two RPM files. One should be the source package, which contains everything necessary for someone else (or the Fedora build system) to build their own copy of your package. The other is a binary package. It doesn't actually have anything in it at this point, though, because we didn't tell RPM to actually include any files. (It would not even have been created if we hadn't included the empty %files section.)

If you like, you can look at either package using rpm -qip, or just less.

A useful package

So now we have a minimally functional specfile which builds and produces a rather useless binary package.

In order to actually make a package which does something, we must tell RPM how to install the program. Edit the specfile and add this to the %install section (immediately after the line containing %install):

mkdir -p %{buildroot}/%{_bindir}
install -p -m 755 %{SOURCE0} %{buildroot}/%{_bindir}

The contents of the %install section is just a shell script! Note that we've used three macros:

  • %{buildroot} is set to a temporary directory called "the buildroot" that's set up by RPM to hold the complete tree of files we'll install.
  • %{_bindir} is just /usr/bin.
  • %{SOURCE0} refers to the file listed earlier in the spec with the Source0: tag.

This saves us from having to care about exactly where those files and directories are located on the filesystem while the package is built; instead we only care about where those files are ending up. And without %{buildroot} we'd end up installing those files directly onto our development machine, which would be bad, especially if running as root.

Now do a local build. It failed! But why? Well, because of this:

error: Installed (but unpackaged) file(s) found:
   /usr/bin/howdy

We installed a file but didn't tell RPM about it. RPM maybe could just include everything we install, but there are plenty of good reasons why it doesn't just do that. So tell RPM about that file, by adding this to the %files section:

%{_bindir}/howdy

Note that %files is generally about files we've actually installed into the buildroot. You do not use the %{buildroot} macro when listing files there.

Now do another local build. If all goes well, you should have two updated RPMs, and the binary one should contain a file. But there's one more thing we should add to the spec to make this a complete package. Since all we're packaging is a shell script, there is no reason at all for this to be built separately on each architecture Fedora supports. So edit the spec once more and add the following immediately after the Source0: line:

BuildArch: noarch

This tells RPM that there's nothing architecture-specific about a particular package. You can reindent the spec if you like to make things line up, but please use spaces and not tabs. Delete the existing .rpm files in this directory and do another local build. Now you should have a pair of rpms: one with the updated source, and one ending in .noarch.rpm indicating an architecture-independent package. You should now have your first complete package that you built yourself! If you like, install it and try it out. You'll probably want to remove it once you're done, unless you just like Texas-style greetings.

Further things to do with our package

Have a glance at our current spec if you like.

 
Name:      howdy
Version:   1
Release:   1%{?dist}
Summary:   Say hello, Texas style

License:   Public Domain
Source0:   howdy
BuildArch: noarch

%description
A simple program to greet the user, Texas style.

%install
mkdir -p %{buildroot}/%{_bindir}
install -p -m 755 %{SOURCE0} %{buildroot}/%{_bindir}

%files
%{_bindir}/howdy

%changelog

You may recall that RPM handles dependencies, but we didn't indicate anything about that in the specfile. Let's look.

 rpm -qp --requires howdy-1-1.fc39.noarch.rpm

You'll see that RPM added some internal rpmlib dependencies, plus one on /bin/bash which matches up with the first line of the howdy program. Often RPM will handle dependencies for your binary packages automatically. Often times it won't, and we'll look into that later.

You can also replace --requires by --provides to see the other side of the dependency equation. There's not much of interest there, but if something did depend on howdy then this package would provide it.

Next thing to do is run some checks on our package:

 fedpkg --release f39 lint

This will spit out a few complaints. Four total about the lack of %prep and %build sections, one about the lack of a URL: tag, and one about the lack of a proper changelog. You may also see other complaints, perhaps about permissions. The full set of complaints may change over time as the checking program, Package-x-generic-16.pngrpmlint itself changes. You may even have noticed these complaints earlier if your editor was configured to automatically check specfiles as you edit them.

We will ignore the complaints about the lack of the two sections and a URL. We could make the complaints go away by adding empty sections and a dummy URL, but that's not productive and our next experiment will have them.

It would indeed be nice to have a changelog section, though. Your editor may have the capability to add one automatically; in Package-x-generic-16.pngvim it's \c (unless you've changed the leader key) and in Package-x-generic-16.pngemacs it's Ctrl+c Ctrl+e. If you want to do it manually, have a look at the relevant guidelines. I'll add mine here:

* Mon Sep 19 2016 Jason L Tibbitts III <tibbs@math.uh.edu> - 1-1
- Initial packaging.

Building in mock

The next interesting thing to do would be to see if our package will build in the way that the Fedora build system would do it. To do this, just run:

fedpkg --release f39 mockbuild

This will build your package in Package-x-generic-16.pngmock. Running mock will set up a complete minimal Fedora installation inside a directory and then build the package within that.

Note.png
Please note that this can take a while. It has to download a number of packages and can take quite some time if you do not have a fast link. It will also take a nontrivial amount of disk space. Fortunately the data it downloads will be cached so subsequent runs will be quicker, but if the disk usage (by default in /var), the time or the bandwidth usage are an issue for you, you can skip this step. However, from this point on in the document, we will do mock builds rather than local builds, and later steps will require that mock builds be carried out. You can continue to perform local builds where possible if you prefer, but eventually you will run into dependency issues that mockbuilds do not have.

The end result should be a significant amount of output, a results_howdy directory, and a couple of levels deep a three log files and two packages. Feel free to look at those.

You can also build for other releases in this manner, by changing what you pass to the --release option. This can be useful for testing, but it takes another big download so we'll skip that now.

Building in koji

If you had your Fedora account set up at the time you started following this document, you can build your package in the central Fedora build system, though the syntax can be a bit odd:

fedpkg --release f39 scratch-build --target f39 --srpm

This will create a source package, upload it to the build servers, and give you some output including a URL you can visit to watch the process and download the built packages afterwards. This can be useful to test that your package builds on the various different architectures that Fedora supports, although your current test package doesn't need such testing.

Running fedora-review

Package reviewers use Package-x-generic-16.pngfedora-review as part of the process of accepting new packages into the distribution. You can run this tool yourself as a useful set of informative checks. First, clean up your package directory:

rm -rf *rpm results*

Then create a source package and run the utility:

fedpkg --release f39 srpm
fedora-review -n howdy

This will use mock to build your package and run a number of checks on it. It will be silent while mock runs, so it may appear as if it has hung when in reality it is doing a large amount of downloading. You can add -v to make it somewhat more verbose.

When done, you should have a review-howdy directory with various files and directories. rpmlint.txt should have some additional rpmlint output for you. review.txt is the template that a reviewer would fill in (in addition to checking the functionality of the software in your package, etc.) Most of that is probably not of interest to you, but it doesn't hurt to have a look.

On to a more complex program

Now that we've covered the absolute basics, we can move on to packaging something more complicated, which comes from a real upstream and has to be unpacked and built. A good package to use as an example is GNU Hello. Have a look there, note the current version of Hello (2.10 as this document is being written) and the download URL, licensing information and such. It's helpful to keep that page open for referenceLet's create a directory and work in it:

 mkdir -p ~/packaging-work/hello
 cd ~/packaging-work/hello

And create the following specfile named hello.spec:

Name:    hello
Version: 2.10
Release: 1%{?dist}
Summary: GNU Hello
URL:     https://www.gnu.org/software/hello/
License: GPLv3+

Source0: https://ftp.gnu.org/gnu/hello/hello-%{version}.tar.gz

%description
The GNU hello program produces a familiar, friendly greeting. It allows
nonprogrammers to use a classic computer science tool which would otherwise be
unavailable to them. Because it is protected by the GNU General Public License,
users are free (in perpetuity) to share and change it.

%prep

%build

%install

%files

%changelog

We've filled in a few things here. There's now a URL: tag, pointing to the Hello homepage. The %description was cribbed from the homepage. The License: tag has changed, since the bottom of the homepage says that the license is "under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.". Licensing is a difficult subject, and we'll cover it in more depth later, but for now it's sufficient to note that Fedora indicates this type of license with "GPLv3+".

Perhaps the most interesting change is to the Source0: tag. It now has a URL instead of a filename: using a URL tells everyone, including the relevant Fedora utilities, where to actually get the source. And there's a macro in there: %{version} is automatically set to whatever you used for the Version: tag. Combining the two lets things automatically get an updated copy of the source whenever the version changes. But how do we actually get that source, since now we can't cut and paste that URL? Try spectool:

spectool -g *spec

This quickly grabs all of the sources mentioned in the spec, and will leave us with hello-2.10.tar.gz in our package directory. Have a look with that file:

less *tar.gz

and we see that everything in there unpacks unto a single directory named hello-2.10. We'll need to tell RPM how to unpack that archive and how to find the files within. Add this to the %prep section:

%autosetup

This is a rather complicated macro which RPM will replace with plain old shell code to unpack the archive, change into a directory and fix up some permissions. It by default expects the directory to be named %{name}-%{version} (where %{name} is, you guessed it, what you gave for the Name: tag). This can be changed by passing the -n option, but in our case the default is just what we need. You can see exactly what it does by executing the %prep section with:

fedpkg --release f39 prep

This will call just the %prep section of your specfile, and should leave you with a directory named hello-2.10 in your package directory. Have a look around in there. You'll see this is a standard GNU package with a configure file, and that tells us most of what we need to know in order to build it. Add this to the %build section:

%configure
%make_build

This just calls the configure file with all of the arguments necessary to build in Fedora, and then calls make with the necessary options. And while we're at it, let's add this to %install:

%make_install

This calls the usual make install with Fedora's special macros to get everything into the buildroot. If you do a mockbuild at this point, you'll see that the build fails, just like with the previous package, there are installed but unpackaged files. The list of files below the error heading in the output, tells us what we need to do next, but because there's an info page, a manpage and some locale files, we have a few different rules to follow.

Old document below

Note.png
Beyond this point are remnants of the old document. These will all be incorporated or removed as the reorganization and cleanup continues. The information below is almost certainly out of date with regards to the current packaging guidelines. Please keep that in mind if you read further.

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. With a few exceptions, all binaries and libraries included in Fedora packages must be built from the source code that is included in the source package.

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.

SPEC templates and examples

Templates

You may use the rpmdev-newspec command to create a SPEC file for you. rpmdev-newspec <package-name> 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, and 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
vim python-antigravity.spec

According to the packaging guidelines, new spec files should be created this way. Vim and emacs can automatically create simple templates, but these are different than those made with rpmdev-newspec. This is especially true for templates with names beginning with python- or -perl.

Here is an example auto-generated .spec template:

Name:           testprogram
Version:        
Release:        1%{?dist}
Summary:        

License:        
URL:            
Source0:        

BuildRequires:  
Requires:       

%description


%prep
%setup -q


%build
%configure
%make_build


%install
%make_install


%files
%doc



%changelog
* Sun Apr  3 2016 makerpm
-

Examples

eject

Here's a simple example showing a Fedora specfile for the eject program:

Summary:            A program that ejects removable media using software control
Name:               eject
Version:            2.1.5
Release:            21%{?dist}
License:            GPLv2+
Source:             %{name}-%{version}.tar.gz
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
URL:                http://www.pobox.com/~tranter
ExcludeArch:        s390 s390x
BuildRequires:      gettext
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
%autosetup -n %{name}

%build
%configure
%make_build

%install
%make_install

install -m 755 -d %{buildroot}/%{_sbindir}
ln -s ../bin/eject %{buildroot}/%{_sbindir}

%find_lang %{name}

%files -f %{name}.lang
%license COPYING
%doc README TODO ChangeLog
%{_bindir}/*
%{_sbindir}/*
%{_mandir}/man1/*

%changelog
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.5-21
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild

* Fri Jul 02 2010 Kamil Dudka <kdudka@redhat.com> 2.1.5-20
- handle multi-partition devices with spaces in mount points properly (#608502)

SPEC file overview

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, and beware of macros (beginning with %) that are potentially multi-line, as they are expanded first. When commenting out a line, double the percent signs (%%) of the macros appearing after the "#". Also avoid inline comments on the same line as script commands.

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 generally 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. The optional Dist tag might be useful.
  • Summary: A brief, one-line summary of the package. Use American English. 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. Note: This tag is deprecated since Fedora 17. See Spec File Reference Preamble
  • 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 now redundant in Fedora and is only needed for EPEL5. By default, the build root is placed 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. It is possible to ensure you have specified all necessary build requires by performing a "mock build" of your package. 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 Package-x-generic-16.pngauto-buildrequires package 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 "%autosetup"; a common variation is "%autosetup -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.
  • %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.
  • %check: Script commands to "test" the program. This is run after the %install procedure, 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.
  • %clean: Instructions to clean out the build root. Note that this section is now redundant in Fedora and is only necessary for EPEL. 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. Do NOT put software's changelog at here.This changelog is for RPM itself.
  • 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.

Stop (medium size).png
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.

SPEC file sections explained

%prep section

The %prep section describes how to unpack the compressed packages so that they can be built. Typically, this includes the "%autosetup" command. Alternatively, you can use "%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 and %autosetup is not what you want, then you can do:

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: %autosetup command

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

  • -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 "%autosetup -n FOO".
  • -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.

If you use "%setup" command instead, then -q' is commonly used to suppress unecessary output.

There are more %setup 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

If you have used "%autosetup" command, the following manual patch management is not necessary. If you have complex requirements or need compatibility with EPEL, you may still need this. 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 -ur ../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_build

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

 %make_build 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.

%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
%make_install

Ideally you should use %make_install which is equivalent to 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
mkdir -p %{buildroot}%{_bindir}/
cp -p mycommand %{buildroot}%{_bindir}/

%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 %install section, since files in %buildroot may be tested) instead of within the %build section itself, so that they can be easily skipped when necessary.

Often, this section contains:

make test

Sometimes it can be:

make check

Please explore the Makefile and choose the appropriate way.

%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 sets 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 an appropriate directory under /usr/share/doc, whose ownership does not need to be declared.

Note: If specifying a %doc entry, rpmbuild < 4.9.1 removes the doc directory it installs files into before installing them. This means that files already in it, for example installed in the %install section, are removed and do not end up in the package. If you want to install some files in the %install section, install them into a temporary staging directory inside the build dir (not build root), for example _docs_staging, and include them in the in the %files list like %doc _docs_staging/*.

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(0600, 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

The %readme prefix is not valid in Fedora.

%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. Executables that should not normally be executed directly by users or administrators should (but are executed by other parts of your package) go in a subdirectory of /usr/libexec, which is referred to as %{_libexecdir}/%{name}.

Do not install files into /opt or /usr/local. (reference)

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, Perl and Systemd), 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 LICENSE COPYING
%{_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

When an end-user installs the RPM, you may want some commands to be run. This can be achieved through scriptlets. See Packaging:Scriptlets.

Scriptlets can be run:

  • before (%pre) or after (%post) a package is installed
  • before (%preun) or after (%postun) a package is uninstalled
  • at the start (%pretrans) or end (%posttrans) of a transaction

For example, every binary RPM package that stores shared library files in any of the dynamic linker's default paths, must call ldconfig in %post and %postun. If the package has multiple subpackages with libraries, each subpackage should also perform the same actions.

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

If only running a single command, then the "-p" option runs the adjacent command without invoking the shell. However, for several commands, omit this option and include the shell commands beneath.

If you run any programs within the scriptlets, then you must specify any requirements in the form "Requires(CONTEXT)" (e.g. Requires(post)).

%pre, %post, %preun, and %postun provide the argument $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, but instead check if they are greater than or equal to 2. For %pretrans and %posttrans, $1 is always 0.

For example, if the package installs an info manual, then the info manual index must be updated with install-info from the info package. Firstly, there is no guarantee that the info package will be available unless we explicitly declare it as required, and secondly, we don't want to fail completely if install-info fails:

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 one other glitch related to installing info manuals. The install-info command will update the info directory, so we should delete the useless empty directory from the %{buildroot} during the %install section:

rm -f %{buildroot}%{_infodir}/dir

Another scriptlet-like ability are "triggers", which can be run for your package when other packages are installed or uninstalled. See RPM Triggers.

Macros

Macros are text in the format %{string}. Typical macros:

Macro Typical Expansion Meaning
%{_bindir} /usr/bin Binary directory: where executables are usually stored.
%{_builddir} ~/rpmbuild/BUILD Build directory: files are compiled within a subdirectory of the build directory. See %buildsubdir.
%{buildroot} ~/rpmbuild/BUILDROOT/%{name}... Build root: where files are "installed" during the %install stage, which copies files from a subdirectory of %{_builddir} to a subdirectory of %{buildroot}. (Historically, %{buildroot} was in "/var/tmp/".)
%{buildsubdir} %{_builddir}/%{name} Build subdirectory: a subdirectory within %{_builddir} where files are compiled during the %build stage. It is set after %autosetup.
%{_datadir} /usr/share Share directory.
%{_defaultdocdir} /usr/share/doc Default documentation directory.
%{dist} .fcNUMBER Distribution+version short name (e.g. ".fc39")
%{fedora} NUMBER Number of fedora release (e.g. "39")
%{_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

Learn more about macros by looking in /etc/rpm/* and /usr/lib/rpm, especially /usr/lib/rpm/macros. Also use rpm --showrc to show values that RPM will use for macros (altered by rpmrc and macro configuration files).

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

%global date 2012-02-08

Use the "-E" option of rpmbuild to find the value of a macro in a SPEC file:

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

Also see Packaging/RPMMacros and RPM Guide chapter 9.

Other tags

In addition to Requires and BuildRequires tags, you can also use these for controlling dependencies:

  • Provides: list virtual package names that this package provides. For example, there might be a package "foo" that demands a particular functionality "bar" from another program. If there are several packages that can satisfy that demand, those packages can specify "Provides: bar" and the "foo" package can specify "Requires: bar". You could also use the "alternatives" system, but avoid if multiple users on the same system might want different default, as these settings are system-wide. Use "rpm -q --provides PACKAGENAME" to see what a given package provides. Some examples of virtual packages in Fedora:
    • MTA: Used for mail transport agents, such as sendmail.
    • tex(latex): Used for latex
  • Obsoletes: remove another named package(s) when this package is installed. Use when the package name changes or when it totally replaces a different package.
  • Conflicts: state what other packages cannot be installed simultaneously to this one. Avoid this if you can. See Packaging/Conflicts.
  • BuildConflicts: state what packages cannot be installed when building this package. Avoid this if you can.

To manage different architectures, there are two tags:

  • ExcludeArch: to exclude an architecture on which the package doesn't build. For example:
ExcludeArch: ppc
  • ExclusiveArch: to include only the specified architecture. Avoid this unless absolutely correct.

Valid architectures are listed at Architectures.

Subpackages

A SPEC file can define several binary package. In other words, one SRPM with one SPEC file can result in several RPMS. Note that there is still only one creation (%prep, %build, %install etc.) process. name-doc and name-devel subpackages are common for documentation and development files respectively.

Use the %package directive to start defining a subpackage:

%package subpackage_name

After each %package directive, list the tags for the subpackage. This should at least include the Summary and Group tags, as well as the %description subpackage_name and %files subpackage_name directives:

Anything not specified by the subpackage will be inherited from its parent.

By default, if the package name is "foo" and the subpackage name is "bar", then the resulting subpackage will be "foo-bar". You can override it with the "-n" option (but you'll need to use it in all other directives too if you specify it here):

%package -n new_subpackage_name

See the RPM Guide section on subpackages for more information.

Conditionals

You can insert conditional statements, for example to test if you are creating a binary for a certain architecture:

%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

Packaging/FrequentlyMadeMistakes has information on frequently-made mistakes. There are also some recommendations and controversial tricks on PackageMaintainers/Packaging Tricks.

Try to write your SPEC files so that it is likely to work when a new release is made upstream, without any changes aside from bumping the version number and refreshing the source files. 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

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 or systemd script, consider using chkconfig or systemctl to arrange for the service to be started/stopped on the next reboot. Before uninstalling, you should normally try to stop its services if they are running.

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

Normally, if there are binary executables, then debugging symbols are stripped from the normal binary packages and placed into a name-debug subpackage. If this shouldn't happen, you can disable the stripping and creation of this subpackage by putting this at the top of your SPEC:

%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 evaluate to blank if %fedora is not defined. This causes the end result to be the 0 (which is a number and thus fine), while not interfering with the result if there is actually a value for %fedora. (Note that this trick does not work in Koji "scratch" builds, where %fedora is set during the creation of a SRPM.)

GUI programs must have a desktop entry so that people can invoke it from the graphical desktop menu. For .desktop files, see Fedora packaging guidelines for desktop files and desktop entry spec. For icons within /usr/share/icons, see icon theme spec.

Building the binary package

Test with rpmlint

To catch many common errors early, run rpmlint on your SPEC file before trying to build anything from it:

$ rpmlint program.spec

If the reported error doesn't make sense, run it again with the "-i" option for longer messages.

Aim to have no errors, but sometimes rpmlint reports false positives. The Fedora packaging guidelines explains which ones to ignore.

Create binary RPMS from the SPEC file

Once you've created your SPEC file, build the SRPM and binary RPMS by running this:

$ rpmbuild -ba program.spec

If successful, RPMS will be created within ~/rpmbuild/RPMS and SRPMS will be created within ~/rpmbuild/SRPMS.

If it fails, go to the appropriate directory and see what is left over. To help debug, you can skip earlier stages that succeeded with the "--short-circuit" option. 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 an SRPM (which does not run the %prep or %build or other stages), run this:

rpmbuild -bs program.spec

Testing binary RPMS with rpmlint

rpmlint can be run on SPEC files, RPMS and SRPMS to check for errors. You need to eliminate or justify warnings before posting a package. This page offers explanations for some of the common issues that come up. If you are in the SPECS directory, do this:

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

Enter the ~/rpmbuild/RPMS directory and into the architecture subdirectory. You will find some binary RPMS. Quickly see their files and permissions (to check whether they are correct) by doing:

$ rpmls *.rpm

If they look fine, install them as root:

# rpm -ivp package1.rpm package2.rpm package3.rpm ...

Test the programs in a few different ways to see if everything works correctly. If it is a GUI tool, make sure it shows up in the desktop menu, otherwise the .desktop entry is wrong.

Uninstall packages later by doing:

# rpm -e package1 package2 package3

Mock and Koji

Mock is a powerful tool that uses the SRPM you have created to build binary packages within a nearly empty environment. This can reveal if you have accurate build dependencies. If it fails, then you forgot to list something in BuildRequires. See Using Mock to test package builds. Once your account is a member of the "mock" group, you can run commands like this to do local testing:

$ mock -r fedora-23-i386 rebuild path_to_source_RPM

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 SRPM on a variety of platforms by running commands like:

$ koji build --scratch f23 path_to_source_RPM

Replace f23 with any later release of Fedora, or rawhide.

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. If you need to build against a package that is not yet a stable released update, submit a Koji buildroot override request via Bodhi. If it's not your own package you depend on, contact its maintainer(s). [Before Bodhi could handle Koji buildroot override requests, the old method has been to 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.

  • rpmdev-bumpspec : bump the release tag in the spec file and add a changelog comment with the right date and version format:
rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES

DNF download plugin (from core DNF plugins) is also useful:

  • dnf download : download the SRPM of the package by running:
dnf download --source PACKAGENAME

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), though it does not create SPEC files of suitable quality for Fedora packages. Alien converts between package formats. It won't produce clean SRPMS, but converting an existing package might provide helpful information.

If you are thinking about packing your rpm for Fedora, be sure you run your packages through Fedora Review, which helps ensure that you comply to the Packaging Guidelines.

Finally, docker-rpm-builder (APL 2.0) uses Docker to build RPM packages; while using rpmbuild requires building on the same host distro as the target, and mock works fine on Fedora/Centos/RHEL distributions for any target, this last tool works fine whenever Docker can run.

If you want to build your package for diferent distribution and architectures and to have publicly accesible dnf repository, you can submit your src.rpm to Copr.

If you need to sign your new package, use rpmsign tool from rpm-sign package.

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 (e.g. Java programs, OCaml programs, GNOME programs). 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 draft guidelines category and Packaging Drafts To Do.

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 FPCA.

Maintaining the package

Once your package has been accepted, you and your co-maintainers will need to maintain it. See Package update HOWTO and Package update guidelines. 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.