翻譯中...
這是製作 RPM 檔案的簡短快速上手教程,內容包括如何快速設置以製作出簡單的源碼軟體包或二進位軟體包。本文假設您對於預製好的 RPM 軟體包使用、以及對於軟體建置流程有一定的熟悉。
如果想澈底瞭解如何建立出 RPM 檔案的相關資訊,像是詳細的秘訣等,請參考 How to create an RPM package。若您計畫為 Fedora 軟體庫建立 RPM 軟體包,請遵守 How to join the Fedora Package Collection Maintainers 所規範的流程,以及遵守各種 Fedora 規約。
本教程旨在展示 GNU "Hello World" 專案的打包過程。你可能會想說何不打包個簡單 C 語言 Hello World 呢?相比於可將「Hello World」印出至標準輸出上的平凡 C 語言程式,GNU 版本的 Hello World 則包含典型 FOSS 軟體專案所需的常用週邊元件,像是組態/建置/安裝 (configuration/build/install) 環境、文件、國際化... 等。而這個傳統的 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
檔案內部
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+ 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
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.
建置軟體包
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
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
檔
以下是 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, use rpmlint -i
or rpmlint -I <error_code>
to see a more verbose description of the rpmlint
diagnostics.
mock
組建
若要檢查軟體包組建在 Fedora 受限的建置環境中是否成功,可以用 mock 來檢查。預設的 mock 組態會以 Rawhide - Fedora 開發分支為對象建置軟體包。
$ mock --verbose ../SRPMS/hello-2.7-1.fc19.src.rpm
參考資料
- How to create an RPM package
- Building RPM packages (20090405)
- Using Mock to test package builds
- 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.