From Fedora Project Wiki

Line 59: Line 59:
you're going to be automating this by editing a ".spec" file, so you have
you're going to be automating this by editing a ".spec" file, so you have
to understand what you're supposed to do first.
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.
Try to reuse what you can.

Revision as of 13:47, 20 June 2008

Creating Package HOWTO

This page describes the basic mechanics of how to create an RPM package for Fedora (such as 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 do.

Nearly all Linux distributions can install and uninstall programs as "packages". Fedora, and many other Linux distributions, use the "RPM" format for packages. There are tools that make it easy to create RPM packages; the key is to write a ".spec" file that explains to RPM how to build and install the program.

If you plan to create an RPM package for the Fedora repository, follow the process for How to join the Fedora Package Collection Maintainers, including following the various Fedora guidance.

Setting up

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

 # yum groupinstall "Development Tools"
 # yum install rpmdevtools

It's strongly recommended that you create a new "dummy user" specifically for creating rpm packages. That 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 normally not create your packages as user root. You can create a new user named "makerpm" quickly by doing:

 # /usr/sbin/useradd makerpm

Then log in as that special dummy user (makerpm).

Once you're logged in as the user who is creating packages, create the directory structure in your home directory by executing:

 $ rpmdev-setuptree

The "rpmdev-setuptree" program will create an "rpmbuild" directory in your $HOME 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.

One you've set up your system and user account, you won't normally need to do these again.

Setting up to package a particular program

If there are special programs that are required to build or run it, install them and write down what they were (you'll need that information).

To package a program, you must package pristine (original) sources, along with the patches and build instructions. 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 your "makerpm" account).

Read through the manual installation instructions for your program; you're going to be automating this by editing a ".spec" file, so you have 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. Obviously, make sure you aren't packaging something that is already packaged; you can find a list of existing packages in Fedora Package Collection in the Fedora Package Database. Also check the In Progress Review Requests (for packages that are currently being reviewed) and the Retired Packages list. Failing that, see if someone has already started to package it for Fedora. Google for "PROGRAMNAME Fedora rpm" or similar... 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 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

Sometimes it's easiest to start with an existing package, and then clean it up for Fedora. RPM Find may help you find rpm's for non-Fedora systems. (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 Ubuntu or Debian (source package files are standard tarballs with a "debian/" subdirectory, possibly associated with patch files). If the FreeBSD ports collection has it, you could download the FreeBSD ports tarball and see if their packaging information helps as a starting point. However, this is sometimes not helpful at all. Different distributions have different rules, and what they do may be quite inappropriate for Fedora.

Creating a spec file

You now need to create a ".spec" file in the "~/rpmbuild/SPECS" directory. Generally, you'll name it after the program, e.g., "program.spec".

Creating a blank spec file

When you're creating a spec file for the first time, create its initial version using emacs or vim; 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:

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

BuildRequires:	
Requires:	

%description

%prep
%setup -q

%build
%configure
make %{?_smp_mflags}

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

%clean
rm -rf %{buildroot}

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

%changelog


You may have $RPM_BUILD_ROOT instead of %{buildroot}; just be consistent.

An example: eject

Here's a simple example, a Fedora 9 package for the "eject" program:

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

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

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

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

%build
%configure

make

%install
rm -rf %{buildroot}

make DESTDIR=%{buildroot} install

# pam stuff
install -m 755 -d %{buildroot}/%{_sysconfdir}/pam.d
install -m 644 %{SOURCE1} %{buildroot}/%{_sysconfdir}/pam.d/%{name}

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

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

%find_lang %{name}

%clean
rm -rf %{buildroot}

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

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

This is an old spec file, so its "BuildRoot:" value is old; you should normally use the "BuildRoot:" entry from the template instead.


Spec file pieces explained

The RPM Guide, section on creating RPMs, describes the details of how to fill in a spec file. The developWorks series "Packaging software with RPM" Part 1, Part 2, and Part 3 is also handy.

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

You can insert comments with a leading "#" character, but 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:

  • Name: The (base) name of the package. It must follow the Package Naming Guidelines.
  • Version: The upstream version number. See Naming guidelines - package version.
  • Release: This starts as "1%{?dist}"; 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 Name Guidelines - package release for more. Packaging/DistTag describes the "dist" tag, which isn't required but can be useful.
  • Summary: A brief, one-line summary of the package. Use American English, and do not end in a period.
  • Group: This needs to be a pre-existing group, like "Applications/Engineering"; run "less /usr/share/doc/rpm-*/GROUPS" to see the complete list. If you create a sub-package "...-doc" with documentation, use the group "Documentation".
  • 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., "GPLv2+" (GPL version 2 or greater) instead of just "GPL". See the Licensing Guidelines for more information. Call this tag "License"; don't use the older, inaccurately named tag "Copyright".
  • 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!).
  • Source0: The URL or filename for the compressed archive containing the source code. If it refers to a URL, that should be the pristine file as upstream released it. "Source" is synonymous with "Source0". If you give a full URL, 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. (Note: This is different than "URL", which provides the URL to more information such as the project website.)
  • 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 special newly-created directory under /var/tmp.
  • BuildRequires: A comma-separated list of packages required for building (beyond what it requires to run). No need to list gcc or other common packages, as noted in the guidelines. You can also specify minimum versions, if necessary.
  • Requires: A comma-separate list of packages that are required to execute. This is automatically determined by rpm, so normally you don't need to put anything here.
  • %description - A longer, multi-line description of the program. Use American English. All lines must be 80 characters or less.
  • %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". Don't use in-line comments, and don't put macros (words beginning with "%") in a comment (macros can cause failures if they are in a comment). See the Maximum RPM section on %setup and %patch for more details.
  • %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. 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:
 %configure
 make %{?_smp_mflags}
  • %install - Script commands to "install" the program. These 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). Normally, you would erase the %{buildroot} directory, and then do some variation of "make install" (using DESTDIR, if the program supports it). Try to copy the files in a way that retains the creation and modification date of the build directory. Here's an example:
rm -rf %{buildroot}
make install DESTDIR=%{buildroot} 
  • %clean - instructions to clean out the build root. Typically:
rm -rf %{buildroot}
  • %files - the list of files that will be installed. You can use wildcards, but it's an error if no file matches the wildcard. %{_bindir} is /usr/bin, and %{_sbindir} is /usr/sbin. If you use a "make install", you need not list each filename - just use wildcards.
%defattr(-,root,root,-)
%doc README
%{_bindir}/*
%{_sbindir}/*
  • %changelog - Changes in the package. Use the format example above.
  • 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.
  • Every binary RPM package which stores shared library files (not just symlinks) in any of the dynamic linker's default paths, must call ldconfig in %post and %postun (post-install and post-uninstall). If the package has multiple subpackages with libraries, each subpackage should also have a %post/%postun section that calls /sbin/ldconfig. For example:
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig

RPM supports subpackages, that is, a single spec file can generate many binary packages. For example, if the documentation is very large, you might generate a separate "doc" subpackage.

Macros

Spec files may contain macro references (text beginning with "%"), which are replaced with other values.

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

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

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

Here are some typical macros:

Macro Typical Expansion
%{_bindir} /usr/bin
%{_builddir} ~/rpmbuild/BUILD/... (build directory, where files are built)
%{buildroot} /var/tmp... (buildroot, where files are installed)
%{_datadir} /usr/share
%{_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} /usr/com
%{_sysconfdir} /etc
%{version} Version of package, set by Version: tag

To see more about macros you can look in /etc/rpm/* and the "macros" files under "/usr/lib/rpm/". You can also invoke rpm, using "rpm --showrc" (to show all the configuration values) or "rpm --eval '%{macro}'" (to see the default value of a particular macro).

You can set your own macro values using %define; be sure to define them before you use them. E.G.,:

%define myvalue 50

Packaging/RPMMacros has more information on macros.

Miscellaneous hints

Beware: Comments (beginning with #) do not work as you might expect. Do not include macros (words beginning with "%") in a comment, because they are expanded even inside comments; if the macro is multi-line it cause weird errors. Also, do not use in-line comments (a # not at the beginning of a line); in-line comments often don't work properly in a spec file. Instead, use a comment-only line (without macros).

Scriptlet Snippets has some useful examples of scriptlets.

Packaging/FrequentlyMadeMistakes has information on frequently-made mistakes.

Some older documents about RPM have the most information, but older documents tend to assume that all rpm work happens in a shared /usr/src/redhat directory. This is an obsolete way of using rpm and not recommended. They may also claim that "rpm" creates packages; it once did, but now that capability is in the separate "rpmbuild" program.


Quick test with rpmlint

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

rpmlint program.spec

This will catch many errors early.

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

Creating RPMs from the spec file

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

 $ rpmbuild --clean -ba program.spec

This will attempt to perform the following stages:

  • %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 maybe source) packages; this uses the information from the %files list to determine what files in the RPM BuildRoot to use.

Watch out: the "build directory" (where compilations occur during %build) and the "build root" (where files are installed during the %install) are different.

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

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

If it is successful, you'll find your binary RPM(s) in the "~/rpmbuild/RPMS/" subdirectory, and the source RPM in "~/rpmbuild/SRPMS". If you "cd" to the "~/rpmbuild/RPMS" directory, to the architecture subdirectory, and then find some rpms, you can quickly see what's in each rpm by using rpmls:

$ rpmls *.rpm

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

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

Then, you can test them out.

You can uninstall them later using:

# rpm -e XYZ1 XYZ2 XYZ3

Guidelines and rules

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

There are many guidelines for specific circumstances (Java programs, OCaml programs, GNOME programs, etc.); go to Package Maintainers or SIGs] and see if any apply to you. You can see the list of all Wiki pages about Packaging to see if any apply.

For more information

The Package Maintainers page links to many other useful pages, and the Updating Package 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.