From Fedora Project Wiki

この項目は、RPM ファイルの書き方についての a short hands-on なチュートリアルです。どうすれば手っ取りばやく、簡単なソースとバイナリのソフトウェアパッケージを作ってステップアップするかを示しています。前提として、既に、多少は、あらかじめRPM化されたパッケージを使ったことがある事を前提のひとつにしており、また、FOSS ビルドのプロセスにも多少は詳しい事を前提にしています。

一方、RPM ファイルの作り方についての総合的かつ包括的な情報、および詳細なヒントについては How to create an RPM package を参照してください。またもし、あなたが作成した RPM パッケージを Fedora リポジトリに反映させたいと計画中でしたら、次の手続き How to join the Fedora Package Collection Maintainers に従ってください。これは、Fedora の様々なガイダンスに従うことを含みます。

このチュートリアルが提示するのは、GNU "Hello World" project のパッケージングです。 While the C program printing 'Hello World" to standard output is trivial, the GNU version contains most of the usual peripheral components associated with a typical FOSS 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.

開発環境

RPMs をビルドするためには、development tools(開発ツール)の一式が必要です。このセットアップは1回で済みます。端末のアカウントをシステム管理者権限 (root) にして、次のコマンドを入力すればいいだけです:

# dnf install fedora-packager @development-tools

クリーンな chroot の中でのビルドのプロシージャーを可能にさせるために、あなたには、あなたの non-privileged account を 'mock' グループの一員として、configure する必要があります:

# usermod -a -G mock <your username>

これらは root 権限が必要なコマンドです。 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. そして、コマンド

$ rpmdev-setuptree

は、あなたの ~/rpmbuild ディレクトリの中に、1つの RPM build area を設置します。このディレクトリは、いくつかのサブディレクトリを含みます。 それは、ソースコードのプロジェクトのためと、 RPM configuration files のためと、 および the resulting source and binary packages です。

"Hello World" RPM のビルド

私達にはソースコードが必要です。そのソースコードとは、私達がパッケージングするというプロジェクトのソースコードであり、しばしば 'upstream' ソースとして言及されます。私達はプロジェクトのウェブサイトからそれをダウンロードして、 それを ~/rpmbuild/SOURCE ディレクトリの内部に入れます。 We are getting the compressed tarball archive, which happens to be the preferred distribution form for most FOSS projects.

$ cd ~/rpmbuild/SOURCES
$ wget http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz

RPM パッケージは .spec ファイルによって configure されます。 私達は適切なデディレクトリーの中に、file hello.spec テンプレートファイルを作成しようとしています:

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

最新バージョンの Emacs または vi ならば、 .spec ファイルを編集できるモードが付いていて、それは 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

.spec ファイルの内側

私達の .spec ファイルにあるフィールドに、まだ若干の編集が必要です。 このフィールドのために Fedora rules に従う必要がありまして、今回の私達の場合なら、 the file might start as follows:

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 while Release numbers our work within Fedora です。

Summary の最初の文字は大文字にするべきです。何故なら、 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 with 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 the 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 a blank 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.

パッケージをビルド

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

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:
%post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :

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

This snippet is copied directly from Packaging:ScriptletSnippets#Texinfo. That page contains solutions to many common packaging tasks. If possible, try to copy a solution from there instead of devising your own.

完全な 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
%autosetup

%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
%{_mandir}/man1/hello.1.*
%{_infodir}/hello.info.*
%{_bindir}/hello

%doc AUTHORS ChangeLog NEWS README THANKS TODO
%license COPYING

%changelog
* Tue Sep 06 2011 The Coon of Ty <Ty@coon.org> 2.8-1
- Initial version of the package

この .spec ファイルを使えば、きっとビルドが成功するはずで、きっとソースとバイナリの RPM パッケージが作成されるはずです。

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, use rpmlint -i or rpmlint -I <error_code> 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. The default mock configuration builds the package against Rawhide - the Fedora development branch.

$ mock --verbose ../SRPMS/hello-2.8-1.fc20.src.rpm

References

History

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.