From Fedora Project Wiki

(update the spec for current guidelines)
(Replace with notica about the new location at docs.fp.o)
Tag: Replaced
(43 intermediate revisions by 24 users not shown)
Line 1: Line 1:
Author:  Przemek Klosowski
This is a short hands-on tutorial on writing RPM files, showing how to quickly step up to create simple source and binary software packages. I assume familiarity with using pre-made RPM packages, and with the FOSS software building process.
{{admon/important|This page is deprecated|As part of documentation move to docs.fp.o, this page has moved to}}
For a comprehensive information on how to create RPM files, including more detailed tips, see [[How to create an RPM package]].
This tutorial demonstrates packaging of the GNU "Hello World" project. While the C program printing 'Hello World" to stdout is trivial, the GNU version contains most of the usual peripheral components associated with a typical FOSS software project, including the configuration/build/install environment, documentation, internationalization, etc.  The GNU version, however, traditionally consists of a tar file containing the source code and configure/make scripts, but it does not include the packaging information. Therefore, it's a reasonable vehicle to practice building RPMs on.
I wrote this tutorial when I worked through [[Building_RPM_packages_%2820090405%29|Christoph Wickert's IRC session on building RPMs]] using Rahul Sundaram suggestion of GNU "Hello World" as a test case. After I wrote up my experience, I found out about the excellent and extensive [[How to create an RPM package]] page on this wiki, as well as the [ Christian Lyder Jacobsen's website]. However, Christian told me he isn't planning to update his site, and I think a 5-minute 'fast food' alternative to the more extensive article might suit some people. More in-depth information on using and building RPM packages is available from [[RPM|other sources]].
== Development environment ==
To build RPMs we need a set of development tools. This is a one-time-only setup,
installed by running those commands from a system administration (<code>root</code>) account:
# yum install @development-tools
# yum install fedora-packager
If you want to test the build procedure in the context of Fedora anonymous package build
system, you need to configure your non-privileged account to be a member of the 'mock' group:
# usermod -a -G mock <your username>
Those are the only commands requiring <code>root</code> privileges. All the remaining
work should be done from your regular, non-privileged account, or even from a separate
account created just for development work. Modern RPM-based
systems, including Fedora, are set up to build and test RPM packages purely from
within a non-privileged account. The command
<pre>$ rpmdev-setuptree</pre>
sets up a RPM build
area in your <code>~/rpmbuild</code>. This directory will contain several subdirectories,
for the project source code, RPM configuration files and for the resulting source and binary
== Building a "Hello World" RPM==
We need the source code of the project we are packaging, often referred
to as the 'upstream' source. We will download it from the project's website  into the <code>~/rpmbuild/SOURCE</code>
directory. We are getting the compressed tarball archive, which happens to be a preferred distribution form for
most FOSS projects.
$ cd ~/rpmbuild/SOURCES
$ wget
The RPM package is configured by <code>.spec</code> files. We will create a template
file <code> hello.spec</code> in the appropriate directory:
$ cd ~/rpmbuild/SPECS
$ rpmdev-newspec hello
Recent versions of <code>Emacs</code> and <code>vi</code> have .spec file editing modes which will also bring up a similar template upon creating a new file. So you can just use the following command for example to use the template automatically.
vi hello.spec
=== Inside a <code>.spec</code> file ===
The fields in our <code>.spec</code> file need slight editing. Please follow the [[How_to_create_an_RPM_package#Spec_file_pieces_explained|Fedora rules]] for these fields. In our case, the file might start as follows:
Name: hello
Version: 2.7
Release: 1
Summary: The "Hello World" program from GNU
License: GPLv3+
The "Hello World" program, done with all bells and whistles of a proper FOSS
project, including configuration, build, internationalization, help files, etc.
* Thu Jul 07 2011 The Coon of Ty <> 2.7-1
- Initial version of the package
The <code>Version</code> should mirror upstream while <code> Release</code> numbers our work
within Fedora.
The first letter of the <code> Summary</code> should be uppercase to avoid
rpmlint complaints.
It is your responsibility to check the <code>License</code> status of the software, by
inspecting the source files and/or their LICENSE files, and/or by talking to the authors.
The <code> Group </code> tag was historically used to classify the package in accordance to the list in <code>/usr/share/doc/rpm-<version>/GROUPS</code>. It is being phased out so you will not see it added by default. However, it doesn't hurt to add it anyway.
The <code> %changelog</code> should document the work on preparing the RPM, especially if there are security and bug patches included on top of the base upstream source.  Changelog data can be displayed by <code>rpm --changelog -q <packagename></code>, which is very useful for instance to find out if specific bug and security patches were included in the installed software, thanks to diligent Fedora packagers who include this info with the relevant [[|CVE]] numbers.
The changelog entry should include the version string to avoid rpmlint complaints.
Multi-line sections like <code> %changelog</code> or <code> %description</code> start on a line under the directive, and end with an empty line.
Lines which aren't needed (e.g. <code>BuildRequires</code> and <code>Requires</code>) can be commented out with a hash ('#') for now.
Many lines in the template don't need to be changed at all in many cases, at least for the initial attempt.
=== Building the package ===
We are ready for the first  run to build source,  binary and debugging packages:
$ rpmbuild -ba hello.spec
It will complain and list the unpackaged files, i.e. the files that would be  installed in the system that weren't  declared as belonging to the package. We need to declare them in the <code>%files</code> section. Do not hardcode names like <code>/usr/bin/</code>, but use macros, like <code>%{_bindir}/hello</code> instead. The manual pages should be declared in the <code>%doc</code> subsection: <code>%doc %{_mandir}/man1/hello.1.gz</code>.
This is an iterative process: after editing the <code>.spec</code> file, rerun <code>rpmbuild</code>.
Since our program uses translations and internationalization, we are seeing a lot of undeclared i18 files. The [[Packaging:Guidelines#Handling_Locale_Files|recommended method]] to declare them is:
* 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 the program uses GNU info files, you need to make sure the installation and unistallation
of the package does not interfere with other software on the system, by using this boilerplate:
* delete the 'dir' file in %install:  <code>rm -f $RPM_BUILD_ROOT/%{_infodir}/dir</code>
* <code>Requires(post): info</code> and <code>Requires(preun): info</code>
* add those steps:
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
=== A complete <code>hello.spec</code> file ===
Here's the initial version of <code>hello.spec</code>:
Name:          hello
Version:        2.7
Release:        1%{?dist}
Summary:        The "Hello World" program from GNU
License:        GPLv3+
BuildRequires: gettext
# Requires:     
Requires(post): info
Requires(preun): info
The "Hello World" program, done with all bells and whistles of a proper FOSS
project, including configuration, build, internationalization, help files, etc.
%setup -q
make %{?_smp_mflags}
make install DESTDIR=%{buildroot}
%find_lang %{name}
rm -f %{buildroot}/%{_infodir}/dir
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
%files -f %{name}.lang
%doc %{_mandir}/man1/hello.1.gz
%doc %{_infodir}/%{name}.info.gz
* Tue Sep 06 2011 The Coon of Ty <> 2.7-1
- Initial version of the package
With this spec file, you should be able to successfully complete the
build process, and create the source and binary RPM packages.
Next you should check them for conformance with RPM design
rules, by running <code>rpmlint</code> on the spec file and all RPMs:
$ rpmlint hello.spec ../SRPMS/hello* ../RPMS/*/hello*
If there are no warnings or errors, we've succeeded. Otherwise,
append the error messages to the <code>rpmlint -I</code>
command to see a more verbose description of the <code>rpmlint</code> diagnostics.
=== The <code>mock</code> builds ===
To check that the package build will succeed in the Fedora restricted
build environment, check it with mock.
$ mock -r fedora-15-i386 --rebuild ../SRPMS/hello-2.7-1.fc15.src.rpm
[[Category:Package Maintainers]][[Category:How to]]

Latest revision as of 20:50, 26 May 2021