如何创建一个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 包编译的样本。
开发环境
为了创建 RPM 包,我们需要一套开发工具。这仅需要配置一次即可,包括使用系统管理员(root
) 账户运行的那些命令:
# yum install @development-tools # yum install fedora-packager
如果您想在一个干净的 chroot 中测试编译过程,您必须将您的非特权账户配置为'mock'用户组的成员:
# usermod -a -G mock <your username>
以上是仅有的需要 root
权限的命令。 所有剩下的工作应该使用您正常的、非特权账户完成,或甚至使用一个仅为开发工作而创建的隔离账户。现代基于 RPM 的系统中,包括 Fedora,都纯粹在一个非特权账户中搭建以编译和测试 RPM 包。 命令
$ rpmdev-setuptree
会在你的 ~/rpmbuild
目录下创建一个 RPM 编译区。 这个目录包含若干子目录,用于保存项目源码、RPM 配置文件以及最终的源码和二进制包。
创建 "Hello World" RPM 包
我们打包所需要的项目源码通常称为'upstream'源。我们将从项目网站上将它下载到
~/rpmbuild/SOURCE
目录中。 我们获得的是一个压缩的 tarball 文件, 这正是大多数 FOSS 项目首选发布形式。
$ cd ~/rpmbuild/SOURCES $ wget http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz
RPM 包是通过 .spec
文件配置的。这里我们将在合适的目录下创建一个模板文件 hello.spec
:
$ cd ~/rpmbuild/SPECS $ rpmdev-newspec hello
Emacs
和 vi
的最新版本有.spec 文件编辑模式,它也会在创建新文件的时候打开一个类似的模板。所以你可以仅使用以下示例中的命令来自动使用模板。
vi hello.spec
深入 .spec
文件
在我们 .spec
文件中的域需要稍微编辑一下。 详情请参考 Fedora rules。在本例的情况下,文件可以是如下所示:
Name: hello Version: 2.8 Release: 1 Summary: The "Hello World" program from GNU License: GPLv3+ URL: http://ftp.gnu.org/gnu/hello Source0: http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz %description The "Hello World" program, done with all bells and whistles of a proper FOSS project, including configuration, build, internationalization, help files, etc. %changelog * Thu Jul 07 2011 The Coon of Ty <Ty@coon.org> - 2.8-1 - Initial version of the package
Version
域应该和'upstream'源的版本号一致,而 Release
则是我们在 Fedora 中使用的编号。
Summary
域中的第一个字母应该大写,以避免 rpmlint 工具的抱怨。
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.
检查软件的 License
状态是你的职责,这可以通过检查源码文件和/或他们的 LICENSE 文件,和/或通过和其作者沟通。
Group
标签历史上是用于 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.
创建 RPM 软件包
我们现在可以尝试第一次执行创建命令,以创建源码、二进制和包含调试信息的软件包:
$ rpmbuild -ba hello.spec
这次的运行中系统将会抱怨并列出未打包的文件。例如那些需要安装在系统中,但又没有声明其属于这个包的文件。 我们必须在 %files
中声明它们。但不要使用形如 /usr/bin/
的硬编码, 而应该使用类似 %{_bindir}/hello
这样的宏来替代。
手册页应该在 %doc
中声明 : %doc %{_mandir}/man1/hello.1.gz
.
这是一个反复的过程:编辑 .spec
文件后,重新运行 rpmbuild
。
由于我们的程序使用了翻译和国际化,我们会看到很多未未声明的 i18 文件。 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
如果程序使用 GNU info 文件, 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
andRequires(preun): info
- add those steps:
%post /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || : %preun if [ $1 = 0 ] ; then /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || : fi
一个完整的 hello.spec
文件
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: http://ftp.gnu.org/gnu/%{name} Source0: http://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.gz BuildRequires: gettext Requires(post): info Requires(preun): info %description The "Hello World" program, done with all bells and whistles of a proper FOSS project, including configuration, build, internationalization, help files, etc. %prep %setup -q %build %configure make %{?_smp_mflags} %install %make_install %find_lang %{name} rm -f %{buildroot}/%{_infodir}/dir %post /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || : %preun if [ $1 = 0 ] ; then /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || : fi %files -f %{name}.lang %doc AUTHORS ChangeLog COPYING NEWS README THANKS TODO %{_mandir}/man1/hello.1.gz %{_infodir}/%{name}.info.gz %{_bindir}/hello %changelog * Tue Sep 06 2011 The Coon of Ty <Ty@coon.org> 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 :生成的源代码包
参考文献
- https://fedoraproject.org/wiki/How_to_create_an_RPM_package
- https://fedoraproject.org/wiki/Building_RPM_packages_%2820090405%29
- https://fedoraproject.org/wiki/Using_Mock_to_test_package_builds
- https://fedoraproject.org/wiki/Using_the_Koji_build_system
修改历史
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.