From Fedora Project Wiki

如何创建一个GNU Hello RPM包: 这是一个简短的实际动手编写RPM文件的教程, 展示了如何快速创建一个简单的源代码包和二进制软件包。这里假设您已对使用预编译的 RPM 软件包以及 FOSS (Free and Open Source Software:自由及开源软件) 的编译过程有所了解。

关于如何创建 RPM 文件的完整信息(包括更详细的技巧),请参考How to create an RPM package。如果你打算为 Fedora 仓库创建一个 RPM 包,请按照How to join the Fedora Package Collection Maintainers中的流程,包括遵照各种 Fedora 的指南。

本教程演示了 GNU“Hello World” 项目的打包过程。虽然用 C 语言程序打印 “Hello World” 到标准输出是小菜一碟,但 GNU 版本包含了与一个典型的 FOSS 软件项目相关的最常用的外围组件,包括配置/编译/安装环境、文档、国际化等等。然而 GNU 版本包含了一个传统的由源代码和 configure/make 脚本组成的 tar 文件,但并不包括打包信息。因此,这是一个很好的实践 RPM 包编译的样本。


To build RPMs we need a set of development tools为了创建RPM,我们需要一套开发工具. This is a one-time-only setup, installed by running those commands from a 系统管理员(system administration) (root) 账户:

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

如果您想在一个干净的 chroot 中测试编译过程,您必须将您的非特权账户配置为'mock'用户组的成员:

# usermod -a -G mock <your username>

Those are the only commands requiring root 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

$ rpmdev-setuptree

sets up a RPM build area in your ~/rpmbuild. This directory will contain several subdirectories, for the project source code, RPM configuration files and for the resulting source and binary packages.

创建 "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 ~/rpmbuild/SOURCE 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 .spec files. We will create a template file hello.spec in the appropriate directory:

$ cd ~/rpmbuild/SPECS
$ rpmdev-newspec hello

Recent versions of Emacs and vi 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 .spec file

The fields域 in our .spec file need slight editing. Please follow the Fedora rules for these fields. In our case, the file might start as follows:

Name:     hello
Version:  2.8
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.8-1
- Initial version of the package

The Version should mirror upstream while Release numbers our work within Fedora.

The first letter of the Summary should be uppercase to avoid rpmlint complaints.

It is your responsibility to check the License status of the software, by inspecting the source files and/or their LICENSE files, and/or by talking to the authors.

The Group tag was historically used to classify the package in accordance to the list in /usr/share/doc/rpm-<version>/GROUPS. It is being phased out so you will not see it added by default. However, it doesn't hurt to add it anyway.

The %changelog 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 rpm --changelog -q <packagename>, 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 %changelog or %description start on a line under the directive, and end with an empty line.

Lines which aren't needed (e.g. BuildRequires and Requires) 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 %files section. Do not hardcode names like 不要使用硬编码如/usr/bin/, but use macros使用宏, 使用like %{_bindir}/hello 来替代instead. The manual pages should be declared in the %doc subsection: %doc %{_mandir}/man1/hello.1.gz.

This is an iterative process: after editing the .spec file, rerun rpmbuild.

Since our program uses translations and internationalization, we are seeing a lot of undeclared i18 files. The recommended method to declare them is:

  • 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

If the program uses GNU info files, you need to make sure the installation and uninstallation of the package does not interfere with other software on the system, by using this boilerplate:

  • delete the 'dir' file in %install: rm -f %{buildroot}/%{_infodir}/dir
  • Requires(post): info and Requires(preun): info
  • add those steps:
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :

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

完整的hello.spec文件 A complete hello.spec file

Here's the initial version of hello.spec:

Name:           hello
Version:        2.8
Release:        1%{?dist}
Summary:        The "Hello World" program from GNU

License:        GPLv3+
URL:  {name}

BuildRequires: gettext
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}

%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

* Tue Sep 06 2011 The Coon of Ty <> 2.8-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 rpmlint 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 rpmlint -i command to see a more verbose description of the rpmlint diagnostics.

模拟编译The mock builds

To check that the package build will succeed in the Fedora restricted build environment, check it with mock.

$ mock -r fedora-17-i386 --rebuild ../SRPMS/hello-2.8-1.fc17.src.rpm


  • fedora-17-i386:构建的环境
  • ../SRPMS/hello-2.8-1.fc17.src.rpm :生成的源代码包



Przemek Klosowski wrote this tutorial when he worked through Christoph Wickert's IRC session on building RPMs using Rahul Sundaram suggestion of GNU "Hello World" as a test case. After he wrote up his experience, he 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 isn't planning to update his site, and it seemed that 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 other sources.