(first commit) |
m (internal link cleaning) |
||
(81 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
{{autolang}} | |||
''翻譯:[[User:Kaio| Caius 'kaio' Chance]] 與 [[User:Zerng07|Cheng-Chia Tseng]]'' | |||
== 簡介 == | |||
本頁旨在詳細解說製作 RPM 軟體包的方法,特別是指製作 SPEC 檔的方法。不像其他的 RPM 教學指引,本頁有針對 Fedora 的規格作解說,並附上 Fedora 專用的規約 (guideline) 連結。由於本頁內容是以 Fedora Wiki 系統作維護,比起其他教學指引可能資訊還新一些。除了專注於 Fedora 的部份之外,文件中的大部份內容都能用於其他採用 RPM 作為軟體包管理系統的 Linux 散布版。如果你覺得按耐不住了,你可以改看較簡短的 [[How_to_create_an_RPM_package/zh-tw|如何製作 RPM 軟體包]]。 | |||
[ | |||
'''目前 Fedora 文件已發行一份給打包者遵守的草擬規約,請見 [http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide Packagers Guide]''' | |||
[ | |||
請注意本篇內文'''並非 '''Fedora 官方軟體包的'''規約''', [[Packaging:Committee| 打包委員會]] 才是處理 Fedora 中軟體打包守則與規約的組織。其中最重要的是: | |||
* [[Packaging:Guidelines| Packaging Guidelines]] | |||
* [[Packaging:LicensingGuidelines |Licensing Guidelines]] | |||
* [[Packaging:NamingGuidelines| Package Naming Guidelines]] | |||
* [[Packaging:DistTag| Dist Tag Guidelines]] | |||
* [[Packaging:ReviewGuidelines| Package Review Guidelines]] | |||
* [[Packaging:ScriptletSnippets| Recipes for RPM post scripts]] | |||
'''[[Packaging:Guidelines|Packaging Guidelines]] 及 [[Packaging:NamingGuidelines|Package Naming Guidelines]] 皆是 Fedora 打包的主要規約。本頁的內容應與規約相容。 | |||
若你打算為 Fedora 軟體庫製作個 RPM 軟體包,請遵循 [[Join the package collection maintainers]] 中的步驟來做。 | |||
== 準備系統 == | |||
在你為 Fedora 建立 RPM 軟體包之前,你需要安裝一些核心開發工具,並設置你會用到的帳號: | |||
# yum install @development-tools | |||
# yum install fedora-packager | |||
你可以特別為 RPM 軟體包的製作建立個傻瓜使用者 (dummy user),以避免建置程序出錯摧毀你的檔案,或將私人金鑰傳給全世界。 | |||
{{admon/caution|你「永遠」都不該以 <code>root</code> 使用者的身份製作 RPM 軟體包。用 root 帳號建置 RPM 非常危險,因為軟體在打包之前就會將二進位檔安裝在系統之中,所以你必須總是使用一般使用者來建置,以免意外污染你的系統。}} | |||
建立一位名為 <code>makerpm</code> 的傻瓜使用者,將使用者加入 'mock' 群組中,設定個密碼,並以該位使用者身份登入: | |||
# /usr/sbin/useradd makerpm | |||
# usermod -a -G mock makerpm | |||
# passwd makerpm | |||
一旦你以建置用假使用者登入後,在你的家屋目錄中執行以下指令來建立需要的目錄結構: | |||
$ rpmdev-setuptree | |||
<code>rpmdev-setuptree</code> 程式會建立 <code>~/rpmbuild</code> 目錄與一組子目錄 (例:<code>SPECS</code> 與 <code>BUILD</code>),你將利用它們製作軟體包。同時也會建立 <code>~/.rpmacros</code> 檔,可用來設定許多選項。 | |||
= | [[Packaging:Guidelines#Timestamps|打包規約建議保留檔案的時間戳記]];如果你使用 <code>wget</code> 或 <code>curl</code> 下載源碼檔案的話,你可以讓程式自動保留時間戳記。如你使用 <code>wget</code> 下載源碼檔案,將「<code>timestamping = on</code>」加入 <code>~/.wgetrc</code> 組態中。如你使用 <code>curl</code> 的話,則將「<code>-R</code>」加入 <code>~/.curlrc</code> 組態中。 | ||
一般來說往後就不再需要重複以上步驟。 | |||
== 建置 RPM 軟體包的基本要領 == | |||
製作 RPM 軟體包,你需要先有「<code>.spec</code>」文字檔,這份檔案提供打包軟體的相關資訊。接著針對 SPEC 檔執行 <code>rpmbuild</code> 指令,進行產生軟體包的一系列步驟。 | |||
{| | |||
! | 一般來說,你應該將原始 (原生) 來源,例如來自原開發者的 <code>.tar.gz</code> 檔,放進 <code>~/rpmbuild/SOURCES</code> 目錄中。將 <code>.spec</code> 檔放進 <code>~/rpmbuild/SPECS</code> 目錄中,並命名為「''NAME''.spec」,而 ''NAME'' 為軟體包的基礎名稱。最後同時製作二進位軟體包與源碼軟體包,先將目錄切換至 <code>~/rpmbuild/SPECS</code> 並執行: | ||
$ rpmbuild -ba ''NAME''.spec | |||
<code>rpmbuild</code> 會讀取 <code>.spec</code> 檔,並以下列所述階段走過檔案內容。以 <code>%</code> 開頭的字為預先定義的巨集 (請見下方的表格)。 | |||
{|border="1" cellspacing="0" | |||
! 階段 !! 讀取 !! 寫入 !! 動作 | |||
|- | |- | ||
|%prep||%_sourcedir||%_builddir|| | |<code>%prep</code> (準備) ||<code>%_sourcedir</code>||<code>%_builddir</code>||它會讀取源碼目錄 <code>%_sourcedir</code> 下的源碼及補丁。它解開源碼封存檔,將內容放到建置資料夾 <code>%_builddir</code> (大多是 ~/rpmbuild/BUILD/) 內部的子資料夾內部,並套用補丁。 | ||
|- | |- | ||
|%build||%_builddir||%_builddir|| | |<code>%build</code> (建置) ||<code>%_builddir</code>||<code>%_builddir</code>||它會在建置資料夾 <code>%_builddir</code> 內部編譯檔案。這通常是執行 "<code>./configure && make</code>" 之類的指令。 | ||
|- | |- | ||
|% | |<code>%install</code> (安裝) ||<code>%_builddir</code>||<code>%_buildrootdir</code>||它會讀取建置資料夾 <code>%_builddir</code> 內部的檔案,並寫入建置根基資料夾 <code>%_buildrootdir</code> 內部的一個目錄下。寫入的檔案即是使用者在安裝二進位軟體包時所要安裝的檔案。請留意這個怪異的術語:''建置根基 (build root) 資料夾'' 並 '''不是''' 前面所說的 ''建置資料夾''。 本步驟通常是執行 "<code>make install</code>"。 | ||
|- | |- | ||
|% | |<code>%check</code> (檢查) ||<code>%_builddir</code>||<code>%_builddir</code>||檢查軟體是否可以順利運作。這通常是執行 "<code>make test</code>" 之類的指令。許多軟體包不處理這個步驟。 | ||
|- | |- | ||
|bin||%_buildrootdir||%_rpmdir|| | |<code>bin</code> (二進位包) ||<code>%_buildrootdir</code>||<code>%_rpmdir</code>||它會讀取建置根基資料夾 <code>%_buildrootdir</code> 內部的檔案,以在 RPM 資料夾 <code>%_rpmdir</code> 內部製作二進位 RPM 軟體包。在 RPM 資料夾內有各個 CPU 架構的子資料夾,以及一個可給任何架構使用的 "<code>noarch</code>" 資料夾。這些 RPM 檔即是給使用者安裝用的軟體包。 | ||
|- | |- | ||
|src||%_sourcedir||%_srcrpmdir|| | |<code>src</code> (源碼包) ||<code>%_sourcedir</code>||<code>%_srcrpmdir</code>||它會在源碼 RPM 資料夾 <code>%_srcrpmdir</code> 下製作源碼 RPM 軟體包 (<code>.src.rpm</code>)。這些檔案用於軟體包的校閱與上傳。 | ||
|} | |} | ||
註:上述表格中的「下」與「內部」意思不同。例如有個檔案位於 /a/b/c,則 c 位於 a 的「內部」而非 a 之「下」。 | |||
如你所見,在 rpmbuild 中,特定的資料夾有特定的用途。這些是: | |||
{| | {| | ||
! | ! 巨集名稱 !! 名稱 !! 通常 !! 用途 | ||
|- | |- | ||
|%_specdir||Specification | |%_specdir||規格 (Specification) 資料夾||~/rpmbuild/SPECS||RPM 規格 (.spec) 檔 | ||
|- | |- | ||
|%_sourcedir||Source | |%_sourcedir||來源 (Source) 資料夾||~/rpmbuild/SOURCES||元初來源封存檔 (如:tarball) 與補丁 (patch) | ||
|- | |- | ||
|%_builddir||Build | |%_builddir||建置 (Build) 資料夾||~/rpmbuild/BUILD||解開源碼檔並在此資料夾內部的子資料夾下編譯。 | ||
|- | |- | ||
|%_buildrootdir||Build root | |%_buildrootdir||建置根基 (Build root) 資料夾||~/rpmbuild/BUILDROOT||在 %install 階段中,檔案安裝於此處。 | ||
|- | |- | ||
|%_rpmdir||Binary RPM | |%_rpmdir||二進位 (Binary) RPM 資料夾||~/rpmbuild/RPMS||二進位 RPM 檔於此製作、儲存。 | ||
|- | |- | ||
|%_srcrpmdir||Source RPM | |%_srcrpmdir||源碼 (Source) RPM 資料夾||~/rpmbuild/SRPMS||源碼 RPM 檔於此製作、儲存。 | ||
|} | |} | ||
如果在某個階段失敗了,你需要查看詳細輸出內容以瞭解 ''為何'' 失敗,並根據所需修改 .spec 檔 (或其他輸入來源)。 | |||
== | == 準備好打包某個程式 == | ||
如果需要有其他的特別程式才能建置或執行你想要打包的程式,先安裝那些程式然後記下來是哪些 (你會用到這些資訊)。 | |||
若要為 Fedora 軟體庫打包程式,你 ''必須'' 將元初 (原始) 來源連同修補檔與建置指示都一起包進去;採用預先編譯過的代碼「''並不''」妥當。請將原始來源 (通常是 <code>.tar.gz</code> 檔) 放在 <code>~/rpmbuild/SOURCES</code> 目錄 (建置 RPM 的使用者帳號下) 中,然後用它來安裝檔案。 | |||
請先閱讀這個程式的手動安裝指示;你接下來會需要編輯「.spec」檔來將流程自動化,所以你必須先瞭解應該要怎麼做。 | |||
在你試圖用 RPM 建置程式之前,最好你先親手「實際跑過 (dry run)」建置一次 (如果你對 RPM 還不是很熟的話,這真的很重要)。 | |||
除了一些例外,Fedora 軟體中包含的所有二進位檔與函式庫,都必須從源碼軟體包中所含的源碼建置。 | |||
( | |||
=== | === 拆分程式 === | ||
應用程式源碼經常與其他外部函式庫一起發行,也就是說整個「綁在一塊」。 | |||
然而,[[Packaging:No_Bundled_Libraries|請不要將外部函式庫和主程式綁在一塊,統統包成一個軟體包]]。 | |||
[[Packaging:No_Bundled_Libraries| | 相反的,請將他們拆分開來成為獨立的軟體包 。 | ||
=== | === 判斷授權 === | ||
請只打包法律上允許你打包的軟體。 | |||
請參見 [[Packaging:Guidelines#Legal]]、[[Licensing:Main]]、和 [[Packaging:LicensingGuidelines]]。 | |||
通常來說,只有以核可的開源軟體 OSS 授權 (例如 GPL、LGPL、BSD-new、MIT/X、或 Apache 2.0 等授權) 發行的軟體可以打包。 | |||
[[Licensing:Main]] | 請確認軟體真的以這種方式授權 (例如:查看源碼的標頭、README 檔等等)。 | ||
如果軟體有綁函式庫,請確認這些函式庫也是採用 OSS 授權。 | |||
( | |||
=== | === 重複使用既有的軟體包資訊 === | ||
盡可能重複使用。例如,請確認你想打包的不是早就有人打包過的東西。你可以從 Fedora Package Collection [https://admin.fedoraproject.org/pkgdb/ Fedora Package Database] 中找到既有軟體包的清單。 | |||
也請查看 [[PackageMaintainers/InProgressReviewRequests|In Progress Review Requests]] 與 [[PackageMaintainers/RetiredPackages|Retired Packages]] 清單。你可以直接使用 [http://pkgs.fedoraproject.org/cgit Fedora Packages Git Repositories] 來檢視 SPEC 檔 (與修補檔)。你可以使用 <cod> yum-utils</code> 軟體來下載 SRPMS: | |||
# yum -y install yum-utils | |||
http:// | |||
$ yumdownloader --source sourcepackage-name | $ yumdownloader --source sourcepackage-name | ||
另外,也可手動從 [http://mirrors.fedoraproject.org/publiclist Fedora mirror] http/ftp 網頁下的 <code>releases/{{FedoraVersion}}/Everything/source/SRPMS</code> 目錄取得源碼軟體包。請將「<code>{{FedoraVersion}}</code>」替換成你想要使用的 Fedora 發行版本,接著下載該軟體的 <code>.src.rpm</code> 軟體包。 | |||
一旦你下載好 SRPM,請將它安裝到 <code>~/rpmbuild</code>: | |||
$ rpm -ivh sourcepackage-name*.src.rpm | $ rpm -ivh sourcepackage-name*.src.rpm | ||
你也可以用 <code>rpm2cpio</code> 將 SRPM 包解開放到目錄中: | |||
$ mkdir PROGRAMNAME_src_rpm | $ mkdir PROGRAMNAME_src_rpm | ||
$ cd PROGRAMNAME_src_rpm | $ cd PROGRAMNAME_src_rpm | ||
$ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i | $ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i | ||
有時候利用既有的軟體包作為開始是最簡單的方式,只要稍微清理一下就能讓 Fedora 使用。[http://rpmfind.net/ RPM Find] 和 [http://pkgs.org PKGS.org] 可以幫你找到一些非 Fedora 系統的 RPM。你可以安裝其他系統的 SRPM,就像安裝 Fedora 的 SRPM 一樣。若找不到可以利用的軟體包,你或許可以參考看看給 [http://packages.ubuntu.com/ Ubuntu] 或 [http://www.debian.org/distrib/packages Debian] 用的源碼軟體包 (不是 <code>.deb</code> 檔。源碼軟體包的檔案是標準的 tarball,但是有個「<code>debian/</code>」子目錄)。如果 [http://www.freebsd.org/ports/installing.html FreeBSD ports collection] 中有你要的軟體,你可以[ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz 下載 the FreeBSD ports tarball],然後看看他們的打包資訊是否能幫助你作為起點。不過,也有可能這些都一點幫助也沒有。不同的散布版有不同的規則,所以他們的作法或許對 Fedora 而言反而不妥。 | |||
[http://rpmfind.net/ RPM Find] | |||
[http://www.debian.org/distrib/packages Debian] | |||
( | |||
[ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz | |||
== | == 製作 SPEC 檔 == | ||
現在你需要在 <code>~/rpmbuild/SPECS</code> 目錄中製作一份 SPEC 檔。你應該根據程式名稱來命名 (例:「<code>program.spec</code>」) 這份檔案。你可以使用封存檔的名稱,或如果軟體作者有倡議該用怎樣的名稱就用該名稱,但無論如何都應遵守 [[Packaging/NamingGuidelines|軟體包命名規約]] 中的規範。 | |||
[[Packaging/NamingGuidelines| | |||
=== | === SPEC 樣板與範例 === | ||
==== 樣板 ==== | |||
首次製作 SPEC 檔時,可以利用 vim 或 emacs 來自動建立樣板: | |||
$ cd ~/rpmbuild/SPECS | $ cd ~/rpmbuild/SPECS | ||
$ | $ vim program.spec | ||
以下是樣板看起來的模樣 ('''注意:'''供應的樣板不一定有遵守 Fedora 打包規約): | |||
Name: | Name: | ||
Version: | Version: | ||
Line 196: | Line 158: | ||
URL: | URL: | ||
Source0: | Source0: | ||
BuildRequires: | BuildRequires: | ||
Line 204: | Line 165: | ||
%prep | %prep | ||
% | %autosetup | ||
%build | %build | ||
Line 211: | Line 172: | ||
%install | %install | ||
%make_install | |||
%files | %files | ||
%doc | %doc | ||
%changelog | %changelog | ||
你可以用 <code>$RPM_BUILD_ROOT</code> 取代 <code>%{buildroot}</code>。這兩者都能用,只不過記得前後一致就好。 | |||
你也可以用 <code>rpmdev-newspec</code> 指令來製作 SPEC 檔。<code>rpmdev-newspec NAME-OF-NEW-PACKAGE</code> 可為新軟體包製作初始 SPEC 檔,適合各種類型的軟體包使用。它會根據你給的軟體包名稱來猜測可能的種類給予對應的樣板,你也可以直接指定特定的樣板。請見 <code>/etc/rpmdevetools/spectemplate-*.spec</code> 來查閱可用的樣板,也可見 <code>rpmdev-newspec --help</code> 瞭解更多資訊。舉例來說,若想為 python 模組製作個新 SPEC 檔: | |||
cd ~/rpmbuild/SPECS | cd ~/rpmbuild/SPECS | ||
Line 232: | Line 187: | ||
vi python-antigravity.spec | vi python-antigravity.spec | ||
=== | ==== 範本 ==== | ||
===== eject ===== | |||
以下是 Fedora 16 中 <code>eject</code> 程式的 SPEC 檔: | |||
<pre> | |||
Summary: A program that ejects removable media using software control | |||
Name: eject | |||
Version: 2.1.5 | |||
Release: 21%{?dist} | |||
License: GPLv2+ | |||
Group: System Environment/Base | |||
Source: %{name}-%{version}.tar.gz | |||
Patch1: eject-2.1.1-verbose.patch | |||
Patch2: eject-timeout.patch | |||
Patch3: eject-2.1.5-opendevice.patch | |||
Patch4: eject-2.1.5-spaces.patch | |||
Patch5: eject-2.1.5-lock.patch | |||
Patch6: eject-2.1.5-umount.patch | |||
URL: http://www.pobox.com/~tranter | |||
ExcludeArch: s390 s390x | |||
BuildRequires: gettext | |||
BuildRequires: libtool | |||
%description | |||
The eject program allows the user to eject removable media (typically | |||
CD-ROMs, floppy disks or Iomega Jaz or Zip disks) using software | |||
control. Eject can also control some multi-disk CD changers and even | |||
some devices' auto-eject features. | |||
Install eject if you'd like to eject removable media using software | |||
control. | |||
%prep | |||
%autosetup -n %{name} | |||
%build | |||
%configure | |||
make %{?_smp_mflags} | |||
%install | |||
%make_install | |||
install -m 755 -d %{buildroot}/%{_sbindir} | |||
ln -s ../bin/eject %{buildroot}/%{_sbindir} | |||
%find_lang %{name} | |||
%files -f %{name}.lang | |||
%doc README TODO COPYING ChangeLog | |||
%{_bindir}/* | |||
%{_sbindir}/* | |||
%{_mandir}/man1/* | |||
%changelog | |||
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.5-21 | |||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild | |||
* Fri Jul 02 2010 Kamil Dudka <kdudka@redhat.com> 2.1.5-20 | |||
- handle multi-partition devices with spaces in mount points properly (#608502) | |||
</pre> | |||
== SPEC 檔概覽 == | |||
其他有用的指引: | |||
* [http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html RPM Guide] 描寫如何寫作 SPEC 檔。 | |||
* IBM 系列文章 "Packaging software with RPM" [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3/ Part 3]。 | |||
* [http://rpm.org/max-rpm-snapshot/ Maximum RPM] 包含最詳盡的資訊,但內容有點陳舊過時。 | |||
[http://rpm.org/max-rpm-snapshot/ Maximum RPM] | |||
你需要遵守 Fedora 規約: [[Packaging/NamingGuidelines|Package Naming Guidelines]], [[Packaging/Guidelines|Packaging guidelines]],以及 [[Packaging/ReviewGuidelines|Package review guidelines]]。 | |||
[[Packaging/NamingGuidelines| Package Naming Guidelines]], | |||
[[Packaging/Guidelines| Packaging | |||
[[Packaging/ReviewGuidelines|Package review guidelines]] | |||
你可以用「<code>#</code>」字號作為註解的前導字元,但請避免用到可展開成許多列 (以 <code>%</code> 作開頭) 的巨集 (因為它們會先被替換展開)。如果要註解掉一列,百分比符號請改成兩個 (<code>%%</code>)。此外,也請避免使用列內註解 (「#」),例如在同一列中使用指令稿指令提示符。 | |||
( | |||
下方列的是主要標籤。請注意巨集 <code>%{name}</code>、<code>%{version}</code>、和 <code>%{release}</code> 可用來各自指稱 Name 名稱、Version 版本與 Release 發行版次標籤。只要更改標籤,巨集就會自動更新使用新值。 | |||
* Name | * '''Name''':軟體包的 (基礎) 名稱,應該與 SPEC 檔名相符。它必須遵守 [[Packaging/NamingGuidelines|Package Naming Guidelines]],一般只用小寫。 | ||
* Version | * '''Version''':上游版本號。請見打包規約的 [[Packaging/NamingGuidelines#Version_Tag|Version tag section]]。如果版本包含非數字標籤 (即版本標籤不是用數字表示),你可能需要在 Release 發行版次標籤中加入額外的非數字字元。如果上游版本標籤用的是完整日期來區隔版本,請考慮以 <code>yy.mm[dd]</code> (例如:<code>2008-05-01</code> 就變成 <code>8.05</code>) 格式來作為版本號。 | ||
* Release | * '''Release''':發行版次。初始值一般都應該是 <code>1%{?dist}</code>。每次新發行同版本軟體的軟體包就遞增一個數字。若上游發行新的版本,就對應修改 Version 標籤,然後把 Release 發行版次重設回 <code>1</code>。請見打包規約的 [[Packaging/NamingGuidelines#Release_Tag|Release tag section]]。選標的 [[Packaging/DistTag|Dist tag]] 可能會用得到。 | ||
* Summary | * '''Summary''':簡要的、只用一列的軟體包摘要。記得使用美式英文。 還有,'''「絕對不可以」加上半形句號 (.) 作為結尾。''' | ||
* Group | * '''Group''':這個標籤需要使用先前就已經存在過的群組,例如「Applications/Engineering」;請執行「<code>less /usr/share/doc/rpm-*/GROUPS</code>」來查閱完整列表。任何含有文件的子軟體包,請用「Documentation」作為群組 (例如:<code>kernel-doc</code>)。 '''''注意:這個標籤從 Fedora 17 之後就棄用了。請見 [[http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide/chap-Packagers_Guide-Spec_File_Reference-Preamble.html|Spec File Reference Preamble]] ''''' | ||
* License | * '''License''':授權條款,必須是開源軟體授權。請''不要''用舊的 Copyright 標籤。採用標準縮寫 (例如:「<code>GPLv2+</code>」),並且明確 (例如可採用 GPL 2 或後續版本,就寫「<code>GPLv2+</code>」,而不是只隨便寫個「<code>GPL</code>」或「<code>GPLv2</code>」就算了)。請見 [[Licensing]] 與 [[Packaging/LicensingGuidelines|Licensing Guidelines]]。你可以用「<code>and</code>」以及「<code>or</code>」來合併列出多種授權 (例如:「<code>GPLv2 and BSD</code>」)。 | ||
* URL: | * '''URL''': 有關該程式更多資訊的完整 URL (例如該程式的專案網站)。 '''''注意:這不是原本源碼的來源 URL,源碼封存檔的來源 URL 應該用下列的 Source0'''''。 | ||
* Source0 | * '''Source0''':包含 (原始) 元初源碼的壓縮後封存檔的完整 URL,即上游發行該源碼的位置。「<code>Source</code>」與「<code>Source0</code>」同義。如果你給的是完整的 URL (而且你也該這麼做),會用其基礎名稱去查找 <code>SOURCES</code> 目錄。如果可以的話,請用 <code>%{name}</code> 和 <code>%{version}</code> 替換嵌入 URL 中,這樣只要有所變動時都會自動對應。下載源碼檔案時記得[[Packaging:Guidelines#Timestamps|保留時間戳記]]。如果不只有一份源碼封存檔,請用 <code>Source1</code>、<code>Source2</code> 等等依序羅列。如果你要在元初來源外還要再加一些全新的檔案,請將它們列在元初來源''之後''。任何你製作出的 SRPM 都會包入這些來源的副本,除非你有另外直接指定那就例外。請見 [[Packaging/SourceURL|Source URL]] 瞭解更多特殊案例的資訊 (例如:revision control 修訂控制)。 | ||
* Patch0 | * '''Patch0''':第一個要套用到源碼上的修補檔 (patch) 名稱。如果你需要在檔案解壓縮之後對一些檔案作修補,你應該要先編輯檔案並將兩者間的差異儲存成「patch」檔,然後放在 <code>~/rpmbuild/SOURCES</code> 目錄下。一個 Patch 應該只做一種目的更動 (logical change),所以正常來講可能會有多個 patch 檔。 | ||
* BuildRoot | * '''BuildArch''':如果你要打包的檔案並不依賴任何架構 (例如:shell 指令稿、資料檔等),那麼請用「<code>BuildArch: noarch</code>」。二進位檔 RPM 的架構就會跟著變成「<code>noarch</code>」。 | ||
* BuildRequires | * '''BuildRoot''':這是 %install 程序 (在 %build 程序之後) 期間檔案要「安裝」到的地方。這一項目前在 Fedora 中是多餘的,只有 EPEL5 還需要它。預設情況下,建置根基目錄放在「<code>%{_topdir}/BUILDROOT/</code>」。 | ||
* | * '''BuildRequires''':建置 (編譯) 該程式所需要的軟體包列表,以半形逗號分隔各個項目。這個欄位可以 (而且通常) 多列重複。這些依賴項目 ''不會'' 自動判定,所以你需要納入建置該程式所需要的 ''所有'' 項目。[[Packaging/Guidelines#Exceptions_2|有些常見軟體包可以省略]],例如 <code>gcc</code>。如果有必要,你也可以指定最低要求版本 (例:"<code>ocaml >= 3.08</code>")。如果你需要 <code>/EGGS</code> 檔案,可以執行「<code>rpm -qf /EGGS</code>」來判斷它的所屬軟體包。請維持最低限度的依賴 (例如你不需要 perl 的功能,那就用 <code>sed</code> 而不需用到 <code>perl</code>),但請注意有些應用程式若沒有某功能相關的依賴項目時,會永久停用該功能;這些情況中你可能需要納入額外的軟體包。 {{package|auto-buildrequires}} 軟體包可能會有所用處。 | ||
* '''Requires'':當程式安裝之時所需要的軟體包清單,請以半形逗號隔開各個項目。請注意 BuildRequires 標籤應列出的是建置二進位檔 RPM 的項目清單,而 Requires 標籤列出的是安裝/執行該程式所需的項目清單;一個軟體包可以放在其中一個清單,或同時兩個清單中。在許多情況下,<code>rpmbuild</code> 會自動偵測依賴項目,所以不見得需要 Requires 標籤。然而,你可能會希望特別標明那些軟體包是需要的,或是哪些軟體包沒自動偵測到而你需要手動標明。 | |||
* %prep | * '''%description''':長篇的、跨多列的程式描述。請使用美式英文。每一列都必須小於等於 80 個字元。空白列表示新段落的開始。有些圖形使用者介面安裝程式會重新格式化段落;以空白起頭的列會被視為已預先格式化過的格式,會如其所述表現,顯示時一般採用等寬字型。請見 [http://docs.fedoraproject.org/drafts/rpm-guide-en/ch09s03.html RPM Guide]. | ||
* %build | * '''%prep''':「準備」程式的指令稿指令 (例如:將之解壓縮),這樣才能建置程式。一般這只是「<code>%autosetup</code>」。如果源碼檔案要解開放到 <code>NAME</code> 的話,常見的變化形式是「<code>%autosetup -n NAME</code>」。請見下方的 %prep 小節瞭解更多資訊。 | ||
* | * '''%build''':「建置」程式的指令稿指令 (例如:編譯它),準備完成以便後續安裝。程式應該有附上如何執行此步驟的指示。請見下方 %build 小節來瞭解更多資訊。 | ||
* '''%install''':「安裝」程式的指令稿指令。指令應該要將檔案從 <code>BUILD</code> 目錄 <code>%{_builddir}</code> 複製到建置根基目錄 <code>%{buildroot}</code> 中。請見下方的 %install 小節瞭解更多細節。 | |||
* %clean | * '''%check''':「測試」程式的指令稿指令。這是在 %install 程序後執行,所以如果你需要此區段的話,請將它放在該處。通常它僅包含「<code>make test</code>」或「<code>make check</code>」。這要和 %build 分開,這樣人們才能在需要的時候略過自我測試。 | ||
* '''%clean''': 清理建置根基目錄的指令。請注意這個區段目前在 Fedora 中是多餘的,並且只有 EPEL 需要。一般這只包含: | |||
rm -rf %{buildroot} | rm -rf %{buildroot} | ||
* %files | * '''%files''':會安裝的檔案清單。請見下方 %files 小節以瞭解更多細節。 | ||
* %changelog | * '''%changelog''':軟體包的變動。請使用上述格式。'''請「不要」把軟體的變更記錄放在這裡。這裡是 RPM 自身的變更記錄。''' | ||
* ExcludeArch | * '''ExcludeArch''':如果軟體包無法在某特定架構上成功編譯、建置或運作,請在此標籤下列出這些架構。* 你可以加入些代碼區段,這樣代碼會在軟體包於真實系統上安裝或移除時執行 (與之相反的是只執行 %install 指令稿,它只會作虛擬安裝 (pseudo-install),安裝到建置根基目錄中)。這些代碼稱之為「scriptlet」指令稿片段,他們通常以軟體包中的資訊更新執行中的系統。請見下方的「scriptlet」瞭解更多細節。 | ||
* | |||
RPM 也支援從單一 SPEC 檔製作出多個軟體包 (稱為 [[How_to_create_an_RPM_package#Subpackages|子軟體包]]) 的功能,例如 <code>name-libs</code> 和 <code>name-devel</code> 等軟體包。 | |||
{{admon/caution|請'''「不要」'''使用這些標籤| | |||
* Packager | |||
* Vendor | |||
* Copyright}} | |||
請'''不要'''製作「relocatable」可重新變換位置的軟體包;他們不會幫 Fedora 加值,反而把事情搞得更複雜。 | |||
== SPEC 檔區段詳解 == | |||
=== %prep 區段 === | |||
%prep 區段描述的是如何解開壓縮後軟體包的方法,這樣才能拿來建置。一般而言,這包含「<code>%autosetup</code>」指令。另外,你可以使用「<code>%setup</code>」和「<code>%patch</code>」指令搭配參照 Source0 (與 Source1 等) 條目。請見 [http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html Maximum RPM 一文中的 %setup and %patch 小節] 瞭解更多細節。 | |||
自 RPM 4.4.2 起可以使用 %{patches} 和 %{source} 巨集,若你有大量補丁或來源清單,以及 %autosetup 效果並非你所想要的話會很好用,例如你可以這樣做: | |||
for p in %{patches}; do | for p in %{patches}; do | ||
... | |||
done | done | ||
然而請記住,使用上述功能,會讓你的 SPEC 和 RHEL 以及其他 RPM 散布版中所使用的 RPMS 不相容。 | |||
==== %prep 區段:%autosetup 指令 ==== | |||
「<code>%autosetup</code>」指令會解開來源軟體包。可用選項包括: | |||
[http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html | * '''<code>-n</code> ''name'' ''' :如果 Source tarball 所要解開成的目錄名稱與 RPM 名稱不同,這個切換開關用來指定正確的目錄名稱。舉例來說,如果 tarball 要解開成 FOO 目錄,則使用「<code>%autosetup -n FOO</code>」。 | ||
* '''<code>-c</code> ''name'' ''' :如果 Source tarball 需要解開成多個目錄,而非單一個目錄時,這個切換開關可以用來建立名為 ''name'' 的目錄,然後將內容解開放在裡面。 | |||
如我你改用「<code>%setup</code>」指令,則通常使用 ''<code>-q</code>''' 來抑止不必要的輸出。 | |||
如果你打算解開多份檔案,[http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html 有更多 %spec 選項可以用],這在你製作子軟體包時會很有用 (請見下方)。比較重要的有: | |||
{| | {| | ||
|- | |- | ||
| -a number || | | <code>-a number</code> || 在切入目錄後,只解開指定數字的 Source 目錄 (例:「<code>–a 0</code>」代表 Source0)。 | ||
|- | |- | ||
| -b number || | | <code>-b number</code> || 在切入目錄前,只解開指定數字的 Source 目錄 (例:「<code>–b 0</code>」代表 Source0)。 | ||
|- | |- | ||
| -D || | | <code>-D</code> || 在解開之前不要刪除目錄。 | ||
|- | |- | ||
| -T || | | <code>-T</code> || 停用自動解開封存檔。 | ||
|} | |} | ||
==== %prep | ==== %prep 區段:%patch 指令 ==== | ||
如果你用的是「<code>%autosetup</code>」指令,就不需要下列的手動補丁管理程序。如果你的需求很複雜,或是需要和 EPEL 相容,還是可能需要用到。「<code>%patch0</code>」指令會套用 Patch0 (而 %patch1 會套用 Patch1,依此類推)。補丁是對來源程式碼做出必要修改使之符合打包規約的正常作法。常用的「<code>-pNUMBER</code>」選項會傳遞引數給 <code>patch</code> 程式來套用對應補丁。 | |||
補丁的檔名通常看起來像是「<code>telnet-0.17-env.patch</code>」這樣,命名格式依循「<code>%{name} - %{version} - REASON.patch</code>」(不過有時候會省略 version 版本)。補丁檔通常是「<code>diff -u</code>」的成果;如果你是從if you do this from the subdirectory of <code>~/rpmbuild/BUILD</code> 的子目錄執行這個指令的,那麼你之後便不必指定 <code>-p</code> 層級。 | |||
這是為單一檔案製作補丁的典型程序: | |||
cp | cp foo/bar foo/bar.orig | ||
vim | vim foo/bar | ||
diff -u | diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch | ||
如果需要修改許多檔案,有個簡單的方法,就是複製 <code>BUILD</code> 下的整個子目錄,然後執行子目錄的 diff。在你切入「<code>~rpmbuild/BUILD/NAME</code>」目錄後,執行以下指令: | |||
cp -pr ./ ../PACKAGENAME.orig/ | cp -pr ./ ../PACKAGENAME.orig/ | ||
... | ... 修改許多檔案 ... | ||
diff - | diff -ur ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/''NAME''.''REASON''.patch | ||
如果你想在一個補丁中編輯多重檔案,你也可以在編輯之前用同樣的檔名結尾「<code>.orig</code>」來複製原始檔案。然後,你可以用「<code>gendiff</code>」(在 <code>rpm-build</code> 軟體包中) 製作檔案差異的補丁檔。 | |||
試著確保你的路徑完全符合情境。預設的「fuzz」值是「<code>0</code>」,代表比對要求完全相同。你可以加入「<code>%global _default_patch_fuzz 2</code>」來轉換成舊版 Fedora RPM 版本所採用的值,但我們建議你應盡量避免這樣做。 | |||
如 [[Packaging/PatchUpstreamStatus]] 所詳述的,SPEC 檔中所有的補丁上方都要有個註解描述它的目前上游狀態為何。如果這是 Fedora 特別需要的補丁,你應該提及為何它如此特別。Fedora 專案致力不與上游分歧;請見 [[PackageMaintainers/WhyUpstream]] 瞭解此事的重要性。 | |||
=== % | ==== %prep 區段:未修改的檔案 ==== | ||
有時候,來源的一個或多個檔案並不需要解壓縮。你可以「prep」準備這些項目到建置目錄中,如 (這裡的 <code>SOURCE1</code> 代表對應的來源檔): | |||
cp -p %SOURCE1 . | |||
=== %build 區段 === | |||
「%build」區段偶爾會有點複雜;在這個區段中你設置組態,並編譯/建置用來安裝的檔案。 | |||
許多程式採用 GNU <code>configure</code> 的方法 (或據此變化)。預設情況下,檔案會安裝到前綴為「<code>/usr/local</code>」的路徑下,這對解開檔案的存放來說相當合理;但是,現在你是要打包程式,所以請將路徑前綴改成「<code>/usr</code>」。函式庫則應該視架構而定,安裝到 <code>/usr/lib</code> 或 <code>/usr/lib64</code> 中。 | |||
由於 GNU <code>configure</code> 非常常見,可以自動使用「<code>%configure</code>」巨集來喚起正確的選項 (例如,將前綴路徑改成 <code>/usr</code>)。有些變化也多能作用: | |||
%configure | %configure | ||
make %{?_smp_mflags} | make %{?_smp_mflags} | ||
若要凌駕 makefile 變數,請將它作為參數傳遞給 <code>make</code>: | |||
make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir} | make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir} | ||
至於其他深入資訊,請參見 [http://sourceware.org/autobook/ "GNU autoconf, automake, and libtool"] 以及 [http://www.suse.de/~sh/automake/automake.pdf "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer]。 | |||
也有些程式使用 <code>cmake</code>。請參見 [[Packaging/cmake]]。 | |||
=== %install 區段 === | |||
本區段內含「安裝」該程式用的指令稿指令,即從 <code>%{_builddir}</code> 資料夾複製相關檔案到 <code>%{buildroot}</code> 中 (通常代表從 <code>~/rpmbuild/BUILD</code> 複製到 <code>~/rpmbuild/BUILDROOT</code>),並且根據需要在 <code>%{buildroot}</code> 中新建資料夾。 | |||
有些術語的名稱可能讓人會錯意: | |||
* 「建置目錄 build directory」,也稱為 <code>%{_builddir}</code>,實際上和「建置根基 build root」,又稱為 <code>%{buildroot}</code>,是不一樣的資料夾。我們會在前者中編譯,而要打包的檔案則從前者複製到後者去。 | |||
* 在 %build 區段中,目前的目錄起始於 <code>%{buildsubdir}</code>,是 %prep 階段中在 <code>%{_builddir}</code> 下建立的子資料夾。這個資料夾名稱通常會是 <code>~/rpmbuild/BUILD/%{name}-%{version}</code> 這樣。 | |||
* %install 區段在終端使用者安裝二進位 RPM 軟體包時並 '''不會''' 執行 ;事實上 %install 區段只有在製作軟體包時才會執行。 | |||
一般來說,這裡執行的是「<code>make install</code>」之類的: | |||
%install | |||
rm -rf %{buildroot} # redundant except for RHEL 5 | |||
%make_install | |||
理想上您應該使用 %make_install,對於支援的程式來說,它等同於 [http://www.gnu.org/prep/standards/html_node/DESTDIR.html <code>DESTDIR=%{buildroot}</code>],因為它會重新導引檔案安裝到指定的目錄中,也就是我們在 %install 區段中預期發生的事。 | |||
如果程式不支援 <code>DESTDIR</code>(且僅在有此情況之下),您有許多 (下方所列) 方式可以避開問題: | |||
* 修補 makefile 來讓它支援 <code>DESTDIR</code>。在 <code>DESTDIR</code> 中視需要建立目錄,並提交該 patch 補丁給上游。 | |||
* 使用「<code>%makeinstall</code>」巨集。這個方法可能有效,但也可能導致些微失敗。該巨集會展開成「<code>make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install</code>」,而可能導致有些程式無法正常運作。請在 <code>%{buildroot}</code> 下視需要建立目錄。 | |||
* 考慮使用 <code>auto-destdir</code> 軟體包。它需要「<code>BuildRequires: auto-destdir</code>」、並將「<code>make install</code>」修改成「<code>make-redir DESTDIR=%{buildroot} install</code>」。這只在安裝僅使用到特定常用指令來安裝檔案時才能作用,例如 <code>cp</code> 和 <code>install</code>。 | |||
* 手動執行安裝。這可能牽涉到在 <code>%{buildroot}</code> 下建立必要的目錄,並從 <code>%{_builddir}</code> 複製檔案到 <code>%{buildroot}</code> 裡去。要特別注意更新,通常會有新檔名或修改過檔名。此程序的範例: | |||
%install | %install | ||
rm -rf %{buildroot} | rm -rf %{buildroot} | ||
mkdir -p %{buildroot}%{_bindir}/ | |||
cp -p mycommand %{buildroot}%{_bindir}/ | |||
=== %check 區段 === | |||
如果可以自我測試的話,將它們納入其中的話會是個好主意。他們應該放在 %check 區段中 (緊接在 %install 區段之後,因為應該測試 %buildroot 中的檔案) 而不是放在 %build 區段中,這樣才能在必要時刻輕易略過。 | |||
通常,此區段包含: | |||
make test | |||
有時候也可以用: | |||
make check | |||
請探索一下 Makefile 的用法,並選擇適當的方式。 | |||
=== %files 區段 === | |||
此區段宣告哪些檔案與目錄是由該軟體包擁有,還有哪些檔案與目錄會放到二進位檔 RPM 中。 | |||
==== %files | ==== %files 基礎 ==== | ||
<code>%defattr</code> 會設定預設的檔案權限,通常可以在 <code>%files</code> 區段的開頭看到使用。請注意到,如果不需要修改權限的話,那就不再需要用到它。它的使用格式為: | |||
%defattr(<file permissions>, <user>, <group>, <directory permissions>) | |||
第四個參數通常會省略。通常我們會這樣用 <code>%defattr(-,root,root,-)</code>,其中「<code>-</code>」代表預設權限。 | |||
您應該列出該軟體包擁有的所有檔案和目錄。請盡量用巨集來取代目錄名稱,您可以到 [[Packaging:RPMMacros]] (舉例:使用 <code>%{_bindir}/mycommand</code> 取代 <code>/usr/bin/mycommand</code>) 來查看巨集表。如果起頭樣式為「<code>/</code>」(或從巨集擴展而來),則從 <code>%{buildroot}</code> 目錄取用。否則,將假定檔案位在目前的目錄中 (例如:在 <code>%{_builddir}</code> 內部,例如您想要納入的文件檔)。若您的軟體包僅安裝單一檔案如 <code>/usr/sbin/mycommand</code>,則 <code>%files</code> 區段可以像這樣簡單: | |||
%files | %files | ||
%{_sbindir}/mycommand | %{_sbindir}/mycommand | ||
若要讓您的軟體包較不受上游改動而影響,請依這種樣式比對來宣告該軟體包擁有的目錄下所有檔案: | |||
%{_bindir}/* | %{_bindir}/* | ||
若要納入單一目錄: | |||
%{_datadir}/%{name}/ | %{_datadir}/%{name}/ | ||
請注意,<code>%{_bindir}/*</code> 並不會宣稱此軟體包擁有 <code>/usr/bin</code> 目錄,而只有包含其下的檔案。如果您列出一個目錄,則您正試圖宣稱該軟體包擁有這個目錄,以及該目錄內的所有檔案與子目錄。所以,請 '''不要''' 列出 <code>%{_bindir}</code>,而且要小心處理那些可能和其他軟體包共享的目錄。 | |||
如果有下列情形可能引發錯誤: | |||
* 試圖樣式比對,卻沒比對到任何檔案或目錄 | |||
* 重複列出或重複比對到某個檔案或目錄 | |||
* 沒有列出 <code>%{buildroot}</code> 下的某個檔案或目錄 | |||
您也可以使用 <code>%exclude</code> glob 來從前個比對中排除檔案。這對於想用不同的樣式比對來將幾乎全部檔案納入其中時會很有用,但是請注意如果沒有比對到任何東西也會造成失敗。 | |||
==== %files | ==== %files 前綴字 ==== | ||
您可能需要在 <code>%files</code> 區段的內容中加入一個或多個前綴字;請用空格隔開。請見 [http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html Max RPM section on %files directives]。 | |||
通常,「<code>%doc</code>」用來列出 <code>%{_builddir}</code> 內,但未複製到 <code>%{buildroot}</code> 中的文件檔。通常包括 <code>README</code> 和 <code>INSTALL</code> 檔。它們會放到 <code>/usr/share/doc</code> 下適當的目錄中,而 <code>/usr/share/doc</code> 的擁有權不必宣告。 | |||
'''注意:''' 如果有指定 <code>%doc</code> 條目,rpmbuild < 4.9.1 在安裝之前會將檔案安裝到其中的 doc 文件目錄移除。這代表已經放到裡面去的檔案,例如,在 <code>%install</code> 區段中安裝的檔案,會被移除,因此最終不會出現在軟體包中。如果您想要在 <code>%install</code> 區段中安裝一些檔案,請將它們安裝到建置目錄 (是 build dir,而不是建置根基 build root) 內的暫時鄰架目錄 (temporary staging directory) 中,例如 <code>_docs_staging</code>,接著將之納入 <code>%files</code> 列表中,如 <code>%doc _docs_staging/*</code> 這樣。 | |||
組態檔應該要放在 <code>/etc</code> 中,一般會這樣指定 (可以確保使用者所作的更動不會在更新時被覆蓋): | |||
%config(noreplace) %{_sysconfdir}/foo.conf | |||
如果更新程序用的是無法向前相容的組態格式 (non-backwards-compatible configuration format),則應這樣指定: | |||
%config %{_sysconfdir}/foo.conf | |||
「<code>%attr(mode, user, group)</code>」可以用來指派更精細的權限控制,而「<code>-</code>」代表是用預設值: | |||
%attr(0644, root, root) FOO.BAR | |||
如果檔案是以特定的自然語言撰寫,請使用 <code>%lang</code> 來標註: | |||
%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh* | %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh* | ||
使用到區域語言 (Locale) 檔案的程式應該遵循 [[Packaging:Guidelines#Handling_Locale_Files|處理 i18n 檔的建議方法 (英)]]: | |||
* 在 <code>%install</code> 步驟中找出檔名:<code> %find_lang ${name}</code> | |||
* 加入必要的建置依賴: <code>BuildRequires: gettext</code> | |||
* 使用找到的檔名: <code>%files -f ${name}.lang</code> | |||
以下前綴字在 Fedora 中 '''無效''':<code>%license</code> 和 <code>%readme</code>。 | |||
==== %files | ==== %files 與檔案系統階層標準 (Filesystem Hierarchy Standard, FHS) ==== | ||
您應該遵守 [http://www.pathname.com/fhs/ 檔案系統階層標準 (FHS)]。執行檔應放在 <code>/usr/bin</code>,全域組態檔放進 <code>/etc</code>,函式庫放到 <code>/usr/lib</code> (或 <code>/usr/lib64</code>) 等等。只有一項例外:一般不該給使用者或管理員執行的執行檔,應該放到 <code>/usr/libexec</code> 中的子資料夾中,資料夾名稱為 <code>%{_libexecdir}/%{name}</code>. | |||
請 '''不要''' 把檔案安裝到 <code>/opt</code> 或 <code>/usr/local</code> 中。 | |||
不幸地,許多程式預設情況下並不遵守 FHS。尤其是,系統架構獨立的函式庫被放到 <code>/usr/lib</code> 而非 <code>/usr/share</code> 之中。前者是給系統架構依賴的函式庫使用,後者才是給系統架構獨立的函式庫運用;這代表不同 CPU 架構的系統都能共享 <code>/usr/share</code> 資料夾。Fedora 中也是有一些例外 (例如 Python 和 Perl),然而 Fedora 比起其他散佈版來說更嚴格遵守標準規範,<code>rpmlint</code> 一般會在你將 ELF 以外的檔案放進 <code>/usr/lib</code> 內時提出抱怨。 | |||
==== %files | ==== %files 範例 ==== | ||
以下為 %files 區段的簡單範例: | |||
%files | %files | ||
%doc README LICENSE | %doc README LICENSE | ||
%{_bindir}/* | %{_bindir}/* | ||
%{_sbindir}/* | %{_sbindir}/* | ||
%{_datadir}/%{name}/ | %{_datadir}/%{name}/ | ||
%config(noreplace) %{_sysconfdir}/*.conf | |||
==== 找出重複檔案 ==== | |||
您可以列出任兩個二進位軟體包的重複檔案,做法爲: | |||
cd ~/rpmbuild/RPMS/ARCH # 請將 "ARCH" 替換為您的系統架構 | |||
rpm -qlp PACKAGE1.*.rpm | sort > ,1 | |||
rpm -qlp PACKAGE2.*.rpm | sort > ,2 | |||
comm -12 ,1 ,2 | |||
=== 小指令稿 (Scriptlet) === | |||
當終端使用者在安裝 RPM 時,您可能想要執行一些指令。這可以透過小指令稿完成。請見 [[Packaging/ScriptletSnippets]]。 | |||
小指令稿可以: | |||
* 在軟體包安裝之前 ('''<code>%pre</code>''') 或之後 ('''<code>%post</code>''') 執行 | |||
* 在軟體包移除之前 ('''<code>%preun</code>''') 或之後 ('''<code>%postun</code>''') 執行 | |||
* 在處理事項的開頭 ('''<code>%pretrans</code>''') 或結尾 ('''<code>%posttrans</code>''') 執行 | |||
舉例來說,每一會在任何 dinamic linker 預設路徑中儲存共享函式庫檔案的二進位檔 RPM 軟體包,都必須在 <code>%post</code> 和 <code>%postun</code> 中呼叫 <code>ldconfig</code>。如果該軟體包有多個附帶函式庫的子軟體包,則每個軟體包也都應該執行相同的動作。 | |||
%post -p /sbin/ldconfig | %post -p /sbin/ldconfig | ||
%postun -p /sbin/ldconfig | %postun -p /sbin/ldconfig | ||
如果僅執行單一指令,則「<code>-p</code>」選項會執行相接的指令但不會喚起 shell。然而,若有許多指令時,請省去這個選項,並在其下納入 shell 指令。 | |||
如果你在小指令稿中有執行任何程式,你就必須以「<code>Requires(CONTEXT)</code>」(例: <code>Requires(post)</code>) 的形式來列出所有的執行需求。 | |||
<code>%pre</code>、<code>%post</code>、<code>%preun</code>、和 <code>%postun</code> 提供了 <code>$1</code> 引數,表示動作完成之後系統上留下的此名稱之軟體包有幾個。請不要拿這個值來比較是否等於 <code>2</code>,而是比較是否大於或等於 <code>2</code>。至於 <code>%pretrans</code> 和 <code>%posttrans</code>,<code>$1</code> 的值則恆為 <code>0</code>。 | |||
舉例來說,如果軟體包安裝了一份 info manual (資訊手冊),那麼可以用 <code>info</code> 軟體包提供的 <code>install-info</code> 來更新資訊手冊索引。首先,我們不保證 <code>info</code> 軟體包總會存在,除非我們明確宣告它是必備的部分;再來,我們不想要在 <code>install-info</code> 失敗之時讓軟體包的執行動作完全失敗: | |||
Requires(post): info | Requires(post): info | ||
Requires(preun): info | Requires(preun): info | ||
Line 598: | Line 522: | ||
fi | fi | ||
還有一件安裝資訊手冊時相關的小瑕疵。<code>install-info</code> 指令會更新資訊目錄,所以我們應該要在 <code>%install</code> 區段中刪掉 %{buildroot} 中無用的空目錄: | |||
rm -f %{buildroot}%{_infodir}/dir | |||
另一個類似小指令稿的能力是「triggers」(觸發器),可以在其他軟體包已安裝或已移除之時,為你的軟體包執行一些動作。請見 [http://rpm.org/api/4.4.2.2/triggers.html RPM Triggers]。 | |||
=== 巨集 (Macro) === | |||
巨集是 <code>%{string}</code> 這類寫法的文字。典型的巨集有: | |||
{| | {| | ||
! | ! 巨集 !!典型擴展 !! 意義 | ||
|- | |- | ||
| %{_bindir} || /usr/bin || Binary directory | | <code>%{_bindir}</code> || <code>/usr/bin</code> || 二進位檔資料夾 (Binary directory):執行檔通常存放的位置。 | ||
|- | |- | ||
| %{_builddir} || ~/rpmbuild/BUILD || Build directory | | <code>%{_builddir}</code> || <code>~/rpmbuild/BUILD</code> || 建置資料夾 (Build directory):檔案放在建置目錄下的子目錄中編譯。請見 <code>%buildsubdir</code>。 | ||
|- | |- | ||
| %{buildroot} || | | <code>%{buildroot}</code> || <code>~/rpmbuild/BUILDROOT</code> || 建置根基 (Build root):在 <code>%install</code> 階段中的檔案「安裝」之處,會將 <code>%{_builddir}</code> 子目錄下的檔案複製到 <code>%{buildroot}</code> 的子目錄之下。(過去,<code>%{buildroot}</code> 所採用的位置是「/var/tmp/」。) | ||
|- | |- | ||
| %{buildsubdir} || %{_builddir}/%{name} || Build subdirectory | | <code>%{buildsubdir}</code> || <code>%{_builddir}/%{name}</code> || 建置子資料夾 (Build subdirectory):在 <code>%build</code> 階段中檔案會在 <code>%{_builddir}</code> 的子目錄中編譯。這個位置會在 <code>%autosetup</code> 後設置。 | ||
|- | |- | ||
| %{_datadir} || /usr/share || | | <code>%{_datadir}</code> || <code>/usr/share</code> || 共用資料夾。 | ||
|- | |- | ||
| %{_defaultdocdir} || /usr/share/doc || | | <code>%{_defaultdocdir}</code> || <code>/usr/share/doc</code> || 預設文件資料夾。 | ||
|- | |- | ||
| %{dist} || .fc''NUMBER'' || | | <code>%{dist}</code> || <code>.fc''NUMBER''</code> || 散佈版+版本短名 (例:「<code>.fc{{FedoraVersion}}</code>」) | ||
|- | |- | ||
| %{fedora} || ''NUMBER'' || | | <code>%{fedora}</code> || <code>''NUMBER''</code> || fedora 發行版號 (例:「<code>{{FedoraVersion}}</code>」) | ||
|- | |- | ||
| %{_includedir} || /usr/include | | <code>%{_includedir}</code> || <code>/usr/include</code> | ||
|- | |- | ||
| %{_infodir} || /usr/share/info | | <code>%{_infodir}</code> || <code>/usr/share/info</code> | ||
|- | |- | ||
| %{_initrddir} || /etc/rc.d/init.d | | <code>%{_initrddir}</code> || <code>/etc/rc.d/init.d</code> | ||
|- | |- | ||
| %{_libdir} || /usr/lib | | <code>%{_libdir}</code> || <code>/usr/lib</code> | ||
|- | |- | ||
| %{_libexecdir} || /usr/libexec | | <code>%{_libexecdir}</code> || <code>/usr/libexec</code> | ||
|- | |- | ||
| %{_localstatedir} || /var | | <code>%{_localstatedir}</code> || <code>/var</code> | ||
|- | |- | ||
| %{_mandir} || /usr/share/man | | <code>%{_mandir}</code> || <code>/usr/share/man</code> | ||
|- | |- | ||
| %{name} || || | | <code>%{name}</code> || || 軟體包的名稱,由 Name: tag 決定 | ||
|- | |- | ||
| %{_sbindir} || /usr/sbin | | <code>%{_sbindir}</code> || <code>/usr/sbin</code> | ||
|- | |- | ||
| %{_sharedstatedir} || / | | <code>%{_sharedstatedir}</code> || <code>/var/lib</code> | ||
|- | |- | ||
| %{_sysconfdir} || /etc | | <code>%{_sysconfdir}</code> || <code>/etc</code> | ||
|- | |- | ||
| %{version} || || | | <code>%{version}</code> || || 軟體包版本,由 Version: tag 決定 | ||
|} | |} | ||
您可以查看 <code>/etc/rpm/*</code> 和 <code>/usr/lib/rpm</code>、甚至是 <code>/usr/lib/rpm/macros</code> 以進一步瞭解巨集。或是用 <code>rpm --showrc</code> 來顯示 RPM 運用這些巨集時所採用的值 (會根據 <code>rpmrc</code> 與巨集組態檔而有所變動)。 | |||
您可以利用 %global 來定義自己的巨集值,但是請確定在使用巨集之前先已定義過。(巨集在定義之時也可以指涉 (refer to) 其他巨集。) | |||
範例: | |||
%global | %global date 2012-02-08 | ||
請用 <code>rpmbuild</code> 的「<code>-E</code>」選項來尋找巨集在 SPEC 檔中代表的值: | |||
rpmbuild -E '%{_bindir}' myfile.spec | rpmbuild -E '%{_bindir}' myfile.spec | ||
[[Packaging/RPMMacros]] | 也請參見 [[Packaging/RPMMacros]] 和 [https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s07.html RPM Guide chapter 9]。 | ||
[ | |||
=== | === 其他標籤 (tag) === | ||
除了 Requires 和 BuildRequires 標籤之外,你還可以使用以下這些控制依賴關係: | |||
* '''Provides''':列出此軟體包提供的虛擬軟體包名稱。例如,可能有個 <code>foo</code> 軟體包需要來自其他程式的「bar」功能;若有許多軟體包可以滿足該需求,則這些軟體包可以指定「<code>Provides: bar</code>」,而「<code>foo</code>」軟體包則可以指定「<code>Requires: bar</code>」。你也可以使用 [http://dailypackage.fedorabook.com/index.php?/archives/6-Wednesday-Why-The-Alternatives-System.html "alternatives" 系統],但是若同個系統中有多位使用者,不同人可能希望使用不同的預設值,此時請避免使用它,畢竟這些設定屬於系統全域設定。請用「<code>rpm -q --provides PACKAGENAME</code>」來查看指定的軟體包提供那些東西。一些 Fedora 中虛擬軟體包的範例: | |||
** MTA:用作郵件傳輸代理 (mail transport agent, MTA),例如 sendmail。 | |||
* | ** tex(latex): 用作 latex | ||
** | * '''Obsoletes''':當這個軟體包安裝時移除另一個指名的軟體包。當軟體包名稱更換之時,或是用該軟體包完全取代另一個不同的軟體包之時可以使用。 | ||
** | * '''Conflicts''':表示無法與此軟體包同時安裝的其他軟體包。如果可以請避免使用這個標籤。請見 [[Packaging/Conflicts]]。 | ||
* | * '''BuildConflicts''':表示在建置此軟體包之時無法安裝的軟體包。如果可以請避免使用這個標籤。 | ||
* | |||
* | |||
若要處理不同的系統架構,有兩種標籤可以使用: | |||
* '''ExcludeArch''':排除此軟體包無法建置的系統架構。例如: | |||
ExcludeArch: ppc | ExcludeArch: ppc | ||
* '''ExclusiveArch''':僅納入指定的系統架構。除非絕對正確,否則請避免使用。 | |||
可用的系統架構列在 [[Architectures]] 中。 | |||
=== | === 子軟體包 (或稱細分包,Subpackage) === | ||
一份 SPEC 檔可以定義多份二進位檔軟體包。換句話說,一個內含一份 SPEC 檔的 SRPM 檔可能製作出許多 RPM 檔來。請注意到這依然只會有一道製作 (%prep、%build、%install 等) 程序。 <code>name-doc</code> 和 <code>name-devel</code> 為常見的文件檔和開發檔子軟體包。 | |||
請使用 <code>%package</code> 巨集指令來定義子軟體包: | |||
%package subpackage_name | |||
%package | |||
在每個 <code>%package</code> 指令之後,請列出該子軟體包的數個標籤 (tag)。這應該至少包括 Summary 和 Group 標籤、以及 <code>%description subpackage_name</code> 和 <code>%files subpackage_name</code> 指令: | |||
任何子軟體包中未特別指定到的東西,都會從其親代沿襲下來。 | |||
預設情況下,如果該軟體包的名稱為「<code>foo</code>」而子軟體包名稱為「<code>bar</code>」,則子軟體包成果則會是「<code>foo-bar</code>」。你可以利用「<code>-n</code>」選項 (但如果你在這裡特別指定的話,你也需要在所有其他的指令中用到這道指令) 來凌駕原先的規則: | |||
%package -n new_subpackage_name | |||
[http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch10s04.html 請見 RPM Guide 針對子軟體包所寫的小節]瞭解更多資訊。 | |||
=== 條件判斷 (Conditional) === | |||
你可以插入條件判斷陳述,例如測試你是否會為特定系統架構製作二進位檔: | |||
%ifarch ARCHITECTURE_NAME | %ifarch ARCHITECTURE_NAME | ||
反面 (negated) 的論述版本為: | |||
%ifnarch ARCHITECTURE_NAME | %ifnarch ARCHITECTURE_NAME | ||
或更一般的條件判斷式: | |||
%if TRUE_OR_FALSE | %if TRUE_OR_FALSE | ||
也有個可選擇性使用的「<code>%else</code>」區段;以上這些全都必須以「<code>%endif</code>」作結尾。 | |||
=== | === 應用程式專門規約 === | ||
有許多應用程式專門規約可以協助你 (例:專門的程式語言、應用程式、函式庫、建置系統等)。大多都列在 | |||
[[Packaging/Guidelines#Application_Specific_Guidelines| | [[Packaging/Guidelines#Application_Specific_Guidelines|應用程式專用打包規約/規約 (英)]] 之中。一些應用程式專門規約的例子有: | ||
* [[Packaging:Cmake|Cmake]] | * [[Packaging:Cmake|Cmake]] | ||
* [[Packaging:Emacs|Emacs]] | * [[Packaging:Emacs|Emacs]] | ||
如果上述的資訊都沒有涵括到,還有一些可以幫助你找到應用程式專用協助的方法: | |||
* | * Fedoraproject.rog 上的「SEARCH」指令。 | ||
* [[PackagingDrafts]] | * [[PackagingDrafts]] | ||
* | * [[SIGs|Special Interest Group (SIG)]] | ||
* [ | * [[Special:PrefixIndex/Packaging|名稱以「Packaging」起頭的 Wiki 頁面]] | ||
=== Miscellaneous hints === | === 其他注意事項 (Miscellaneous hints) === | ||
[[Packaging/FrequentlyMadeMistakes]] 有列出常見錯誤的相關資訊。[[PackageMaintainers/Packaging Tricks]] 則有列出一些建議、以及具爭議性的技巧。 | |||
請試著撰寫你的 SPEC 檔,盡可能讓上游發行新版本時一切都能水到渠成,使你除了要改版本號並刷新來源檔案外,都不必做任何其他修改。舉例來說,如果要替 *.txt 檔設執行位元,請不要用 | |||
chmod a-x Filename1.txt Filename2.txt Filename3.txt | chmod a-x Filename1.txt Filename2.txt Filename3.txt | ||
而是考慮用以下這種方式來處理,可以直接處理使用相同命名規則的新檔名: | |||
chmod a-x *.txt | chmod a-x *.txt | ||
如果你想要查看大量的小指令稿範例,你可以利用下列指令來顯示所有已安裝程式的小指令稿: | |||
rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less | rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less | ||
請不要嘗試和使用者互動;RPM 是以支援批量安裝為設計核心。如果有個程式需要顯示 EULA 終端使用者授權協議,則該動作應是初次執行時才做,而非安裝之時做。 | |||
建議你不要試圖啟動服務,因為在大量安裝的過程中可能會讓一切變得緩慢。若你有安裝 init 或 systemd 指令稿,請考慮用 <code>chkconfig</code> 或 <code>systemctl</code> 來安排服務在下次重新開機之時啟動/停止該項服務。在解除安裝之前,如果這些服務還在跑,一般而言你應該先嘗試停止這些服務。 | |||
解除安裝應該要盡可能還原安裝階段中所做過的改變,但是不要移除任何使用自行建立的檔案。 | |||
一般而言,如果有二進位執行檔,則一般二進位軟體包應該剝離除錯用符號 (debugging symbols),並放到 <code>name-debug</code> 子軟體包中。如果不應發生這樣的事,你可以在你的 SPEC 檔頂端放入停用剝離動作: | |||
%global _enable_debug_package 0 | %global _enable_debug_package 0 | ||
%global debug_package %{nil} | %global debug_package %{nil} | ||
%global __os_install_post /usr/lib/rpm/brp-compress %{nil} | %global __os_install_post /usr/lib/rpm/brp-compress %{nil} | ||
若想避免剝離動作,你也需要在 <code>%install</code> 區段中做以下動作: | |||
export DONT_STRIP=1 | |||
在 SPEC 檔中檢查 Fedora 版本作條件判斷式建置的方法:A way to check for the version of Fedora in a SPEC file for conditional builds is: | |||
%if 0%{?fedora} <= <version> | %if 0%{?fedora} <= <version> | ||
<code>?</code> 會讓巨集在 <code>%fedora</code> 未定義之時評斷為空白。這樣會讓結果成為 <code>0</code> (數字零,所以很好),而 <code>%fedora</code> 若真的有個數值時也不會有所干擾。(請注意這種做法在 Koji 的「scratch」建置中沒有作用,<code>%fedora</code> 的值會在 SRPM 製作之時就設定好。) | |||
GUI 程式必須有桌面條目 (desktop entry),這樣用戶才能從圖形化桌面選單中喚起這些程式。對於 <code>.desktop</code> 檔案,請見 [[Packaging/Guidelines#Desktop_files|Fedora packaging guidelines for desktop files]] 和 [http://standards.freedesktop.org/desktop-entry-spec/latest/ desktop entry spec];至於 <code>/usr/share/icons</code>,請見 [http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html icon theme spec]。 | |||
== 建置二進位軟體包 == | |||
=== 利用 rpmlint 作測試 === | |||
若要在早期捕捉個種常見錯誤,請在嘗試用 SPEC 檔建置任何軟體包之前先對它執行 <code>rpmlint</code>: | |||
$ rpmlint program.spec | |||
如果回報的錯誤看起來不怎麼合理,請重新以「<code>-i</code>」選項執行以取得更詳細的訊息。 | |||
請以無報錯為目標,不過有時 <code>rpmlint</code> 會有誤報的情況發生。[[Packaging/Guidelines#Use_rpmlint|Fedora 打包規約]] 中有解釋到那些錯誤可以忽略。 | |||
=== 以 SPEC 檔製作二進位 RPM 包 === | |||
一旦你做好 SPEC 檔之後,請執行以下指令來建置 SRPM 與二進位 RPM: | |||
$ rpmbuild -ba program.spec | |||
如果製作成功,RPM 會放到 <code>~/rpmbuild/RPMS</code> 裡面,而 SRPM 會放到 <code>~/rpmbuild/SRPMS</code> 之內。 | |||
如果製作失敗,請前往對應的資料夾來看看留下了什麼。若想取得除錯協助,你可以用「<code>--short-circuit</code>」選項來略過早期的成功階段。例如:若想要 (略過更早期階段) 重新從 <code>%install</code> 階段開始,請執行: | |||
$ rpmbuild -bi --short-circuit program.spec | |||
若你只想要製作 SRPM 檔 (不會執行 <code>%prep</code> 或 <code>%build</code> 或其他階段),請執行: | |||
rpmbuild -bs program.spec | rpmbuild -bs program.spec | ||
== | === 利用 rpmlint 來測試二進位 RPM 檔 === | ||
<code>rpmlint</code> 可以對 SPEC 檔、RPM 檔、SRPM 檔執行來檢查是否存在錯誤。你需要在發佈軟體包之前解除或糾正發出的警告。[[Common_Rpmlint_issues|這個網頁]]提供一些常見問題的解釋。如果你位於 SPEC 目錄中,請執行: | |||
$ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm | $ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm | ||
請進入 <code>~/rpmbuild/RPMS</code> 目錄,再進入系統架構子目錄中。你會看到一些二進位檔 RPM。請用以下指令快速查看這些檔案和權限 (來檢查看看是否正確): | |||
$ rpmls *.rpm | |||
如果一切看起都很好,請以 root 身份安裝: | |||
# rpm -ivp package1.rpm package2.rpm package3.rpm ... | |||
請以不同的方式來測試程式看是否全部都正常運作。如果它是 GUI 工具,請確認有出現在桌面選單中,否則代表 <code>.desktop</code> 條目可能有錯。 | |||
稍後可以利用以下指令來解除安裝軟體包: | |||
# rpm -e package1 package2 package3 | |||
== Mock 和 Koji == | |||
[[Projects/Mock|Mock]] 是在近乎空白的環境下,運用你剛製作的 SRPM 來建置二進位軟體包的強大工具。這可以揭露你實際的建置依賴關係。如果建置失敗,則代表你忘記在 BuildRequires 中列出其中一些東西。請參見 [[Using Mock to test package builds]]。一旦你的帳號屬於「<code>mock</code>」群組的成員之一,你可以執行這樣的指令來做本地端測試: | |||
$ mock -r fedora-9-i386 rebuild path_to_source_RPM | $ mock -r fedora-9-i386 rebuild path_to_source_RPM | ||
你可以利用 Koji (會運用 <code>mock</code>) 在各種不同的系統上執行建置,包括那些你沒有的系統架構。[[PackageMaintainers/Join]] 和 [[PackageMaintainers/UsingKoji]] 上面有更多有關 Koji 的資訊。一旦設定完成,你就可以在各種平臺上使用以下指令來測試你的 SRPM: | |||
[[PackageMaintainers/Join]] | |||
$ koji build --scratch dist-f9 path_to_source_RPM | $ koji build --scratch dist-f9 path_to_source_RPM | ||
請將 <code>dist-f9</code> 以任意近期 Fedora 發行版本替換,但別使用 <code>dist-rawhide</code>。請記住,<code>%fedora</code>、<code>%fc9</code>、等這類的值都不會在 scratch build 中得到修正,所以如果你的 SPEC 檔會依據上述值來做不同的事,則無法作用。 | |||
你的 Koji 建置僅能依賴 TARGET 散佈版軟體庫中實際存在的軟體包。所以,如果你的軟體包依賴 Bodhi 尚未發行的其他軟體包,就無法用 Koji 來為已發行的散佈版作建置。如果你需要對尚未成為穩定版的發行更新建置軟體包,請透過 Bodhi 提交 Koji 建置根基凌駕請求 (Koji buildroot override requet)。如果它並非你的軟體包依賴,請聯絡其維護者。[在 Bodhi 可以處理 Koji 建置根基凌駕請求之前,以前的舊方法是在此處對 rel-eng 提交請票 (ticket):https://fedorahosted.org/rel-eng/newticket ,並請求將該軟體包加入成為建置根基凌駕之一。] | |||
== | == 有用的工具 == | ||
<code>rpmdevtools</code> 軟體包有各種好用工具;「<code>rpm -qil rpmdevtools</code>」會展示給你看它會安裝哪些東西。 | |||
* <code>rpmdev-bumpspec</code>:增進 SPEC 檔中的發行版本標籤,並以當下時間與版本格式加入 changelog 評註: | |||
rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES | rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES | ||
<code>yum-utils</code> 軟體包也提供一些好用工具: | |||
* <code>yumdownloader</code>:請執行以下指令下載該軟體包的 SRPM: | |||
yumdownloader --source PACKAGENAME | |||
<code>auto-buildrequires</code> 軟體包有一對優質工具可以幫助我們找出適當的 BuildRequires 條目。在安裝這個軟體包之後,請用「<code>auto-br-rpmbuild</code>」替換 「<code>rpmbuild</code>」,你就會看見自動產生的 BuildRequires 清單。 | |||
你可能發現到 [http://rust.sourceforge.net/ RUST] 滿好用的 (GPL),但是它無法製作出符合 Fedora 軟體包品質的 SPEC 檔。[http://kitenet.net/~joey/code/alien/ Alien] 則可以在軟體包格式之間轉換;它無法製作出乾淨的 SRPM,但是從既有的軟體包轉換程式或許能提供一些有用的資訊。 | |||
[ | 最後,[https://github.com/alanfranz/docker-rpm-builder docker-rpm-builder] (APL 2.0) 使用 [http://www.docker.com Docker] 來建置 RPM 軟體包;想用 rpmbuild 建置的目標架構需要與主控散佈版相同,至於 mock 則對於任何目標架構的 Fedora/Centos/RHEL 散佈版都能良好處理,'''這是無論 Docker 是否能跑都能運用的最後工作'''。 | ||
若你想要為你的軟體包建置出不同的散佈版與系統架構,並且公開存取 yum 軟體庫,你可以提交你的 src.rpm 到 [https://copr.fedoraproject.org Copr]。 | |||
== 規約與規則 == | |||
* [[Join the package collection maintainers| | |||
* [[Packaging:Guidelines | Packaging | 當你製作軟體包之時,你需要遵守下列規則與規約: | ||
* [[Packaging: | * [[Join the package collection maintainers|如何成為 Fedora 軟體包集合的維護者]] | ||
* [[Packaging:DistTag| | * [[Packaging:Guidelines|打包規約]] | ||
* [[Packaging:ReviewGuidelines| Package | * [[Packaging:NamingGuidelines|軟體包名稱規約]] | ||
* [[Packaging:LicensingGuidelines|軟體包授權規約]] | |||
* [[Packaging:DistTag|散佈版標籤規約]] | |||
* [[Packaging:ReviewGuidelines|軟體包校閱規約]] | |||
有許多官方規約可以引導你處理一些特定情況 (例:Java 程式、OCaml 程式、GNOME 程式等)。你也可以從 [[SIGs|SIG]] 瞭解更多資訊,與 [[:Category:Package Maintainers|軟體包維護者]] 小節。 | |||
[[Special:Prefixindex/Packaging|你也可以查看所有關於打包的 Wiki 頁面]]來看是否有適用的。 | |||
如果找不到,你可能想要找一些非官方的好用建議,例如 [[Special:Search?ns0=1&search=PackagingDrafts%2F&searchx=Search|Packaging Drafts]] 和 [[PackagingDrafts|Packaging Drafts To Do]]。 | |||
[[ | |||
[[ | |||
你也可以從 [http://en.opensuse.org/Packaging SuSE]、 | |||
[http://www.debian.org/doc/debian-policy/ Debian] 的資料中找到一些想法,但是 | |||
[http://www.mail-archive.com/distributions@lists.freedesktop.org/msg00156.html 各個散佈版所用的規則會不同],所以不要直接想說他們的東西可以直接拿來用。 | |||
[http://www.debian.org/doc/debian-policy/ Debian] | |||
[http://www.mail-archive.com/distributions@lists.freedesktop.org/msg00156.html | |||
'''你製作的 .spec 檔必須是開源軟體,如 [[Legal:Fedora_Project_Contributor_Agreement|FPCA]] 中所提及。''' | |||
[ | |||
== | == 維護軟體包 == | ||
一旦你的軟體包被接受,你和你的共同維護者會需要維護這份軟體包。請見 [[Package update HOWTO]] 和 [[Package update guidelines]]。如果你在多個 Fedora 發行版中更新了它的版本,請即時往前做 (例:為 Fedora N 發行新版,一旦被接受,就做 Fedora N-1)。系統會假定新的 Fedora 版本會有相同版本或更後續版本的程式。 | |||
請鼓勵上游開發者使用標準源碼發行慣例。請使用標準慣例以便讓打包流程更輕鬆。若想要瞭解更多資訊,請見: | |||
* [http://www.dwheeler.com/essays/releasing-floss-software.html Releasing Free/Libre/Open Source Software (FLOSS) for Source Installation] ( | * [http://www.dwheeler.com/essays/releasing-floss-software.html Releasing Free/Libre/Open Source Software (FLOSS) for Source Installation] (簡明摘要) | ||
* [http://www.gnu.org/prep/standards/html_node/Managing-Releases.html GNU Coding Standards release process] | * [http://www.gnu.org/prep/standards/html_node/Managing-Releases.html GNU Coding Standards release process] | ||
* [http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/ Software Release Practice HOWTO] | * [http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/ Software Release Practice HOWTO] | ||
Line 919: | Line 777: | ||
* [http://offog.org/articles/packaging/ Packaging Unix software] | * [http://offog.org/articles/packaging/ Packaging Unix software] | ||
== | == 更多資訊 == | ||
[[:Category:Package Maintainers|Package Maintainers]] 頁面連結到許多其他有用的網頁去,而 | |||
[[Package update HOWTO]] | [[Package update HOWTO]] 則描述了如何更新你已經在 Fedora 中維護的既有軟體包。 | ||
若想瞭解更多資訊,在 Fedora Wiki 以外的地方,可以看看下面這些: | |||
* [http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/ How to build RPM packages on Fedora] - very brief run-through | * [http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/ How to build RPM packages on Fedora] - very brief run-through | ||
* Packaging software with RPM (developerWorks) [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3] | * Packaging software with RPM (developerWorks) [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3] | ||
Line 931: | Line 789: | ||
* [http://www.redhatmagazine.com/2008/02/28/when-sally-met-eddie-the-fedora-package-story/ When Sally met Eddie] - a simple tale, but little detail | * [http://www.redhatmagazine.com/2008/02/28/when-sally-met-eddie-the-fedora-package-story/ When Sally met Eddie] - a simple tale, but little detail | ||
* [http://rpm.org/max-rpm-snapshot/ Maximum RPM Book] - most complete information, but in some cases old/obsolete | * [http://rpm.org/max-rpm-snapshot/ Maximum RPM Book] - most complete information, but in some cases old/obsolete | ||
* [http://docs.fedoraproject.org/ | * [http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html RPM Guide, section on creating RPMs] - this has lots of good information, and is slightly more up-to-date, but is a draft | ||
* [http://docs.fedoraproject.org/developers-guide/ch-rpm-building.html Developer's guide, section on building RPMs] | * [http://docs.fedoraproject.org/developers-guide/ch-rpm-building.html Developer's guide, section on building RPMs] | ||
* [http://www.gurulabs.com/GURULABS-RPM-LAB/GURULABS-RPM-GUIDE-v1.0.PDF Creating RPMS slides] from Guru Labs | * [http://www.gurulabs.com/GURULABS-RPM-LAB/GURULABS-RPM-GUIDE-v1.0.PDF Creating RPMS slides] from Guru Labs | ||
* [http://freshrpms.net/docs/fight/ The fight, my first attempt to make a readable rpm package building introduction.] | * [http://freshrpms.net/docs/fight/ The fight, my first attempt to make a readable rpm package building introduction.] | ||
* [http://www-uxsup.csx.cam.ac.uk/talks/rpmbuild/rpmbuild.pdf Cambridge RPM tutorial] is a presentation on creating basic RPMs | * [http://www-uxsup.csx.cam.ac.uk/talks/rpmbuild/rpmbuild.pdf Cambridge RPM tutorial] is a presentation on creating basic RPMs | ||
* [http://en.tldp.org/HOWTO/RPM-HOWTO/index.html RPM HOWTO: RPM at Idle by Donnie Barnes] | * [http://en.tldp.org/HOWTO/RPM-HOWTO/index.html RPM HOWTO: RPM at Idle by Donnie Barnes] | ||
* [http://home.fnal.gov/~dawson/rpms/howto/index.html RPM HowTo | * [http://home.fnal.gov/~dawson/rpms/howto/index.html RPM HowTo by Dawson] | ||
* | * [http://en.opensuse.org/Build_Service/cross_distribution_package_how_to Cross-distribution package HOWTO] has hints if you're building one RPM for many distributions. | ||
* [http://wiki.mandriva.com/en/Development/Howto/RPM Mandriva Rpm HowTo (en)] | * [http://wiki.mandriva.com/en/Development/Howto/RPM Mandriva Rpm HowTo (en)] is an RPM tutorial, though for Mandriva (nee Mandrake). Note: In Fedora, do ''not'' recompress original tarballs, as Mandriva suggests, because that would change their cryptographic hashes. | ||
* [http://linuxshellaccount.blogspot.com/2008/03/creating-your-own-linux-rpms-initial.html Creating Your Own Linux RPM's - The Initial Software Build] is another brief intro, but it makes the point that "The process of building RPM's is much simpler than creating packages for Solaris... Fewer steps, and the ability to add all of your software information into one specification file, makes for a much tighter (and easier to modify or reproduce) software packaging system." | * [http://linuxshellaccount.blogspot.com/2008/03/creating-your-own-linux-rpms-initial.html Creating Your Own Linux RPM's - The Initial Software Build] is another brief intro, but it makes the point that "The process of building RPM's is much simpler than creating packages for Solaris... Fewer steps, and the ability to add all of your software information into one specification file, makes for a much tighter (and easier to modify or reproduce) software packaging system." | ||
* [http://fedoranews.org/alex/tutorial/rpm/ All you need to know about RPM] (more about installing packages than creating them) | * [http://fedoranews.org/alex/tutorial/rpm/ All you need to know about RPM] (more about installing packages than creating them) | ||
* The [http://wiki.rpm.org/ rpm.org Wiki] has some useful information, such as the [http://wiki.rpm.org/Problems list of known RPM problems] | * The [http://wiki.rpm.org/ rpm.org Wiki] has some useful information, such as the [http://wiki.rpm.org/Problems list of known RPM problems] | ||
註:[http://rpm5.org/ rpm5.org] 網站也有提供一些文件,但是請不要依靠裡面的內容;那是 Jeff Johnson 維護的 RPM「分支」,也就是 ''fork''。Fedora (和 Novell/SuSE) 所用的 RPM 則是基於 [http://www.rpm.org rpm.org]。 | |||
[http://lwn.net/Articles/236029/ lwn.net | [http://lwn.net/Articles/236029/ lwn.net 有個簡要的文章]報導這件事。 | ||
[[Category:Package Maintainers]][[Category:How to]] | [[Category:Package Maintainers]] | ||
[[Category:How to]] | |||
[[Category:Zh]] | |||
[[Category:Zh/Translation]] |
Latest revision as of 21:00, 19 September 2016
翻譯: Caius 'kaio' Chance 與 Cheng-Chia Tseng
簡介
本頁旨在詳細解說製作 RPM 軟體包的方法,特別是指製作 SPEC 檔的方法。不像其他的 RPM 教學指引,本頁有針對 Fedora 的規格作解說,並附上 Fedora 專用的規約 (guideline) 連結。由於本頁內容是以 Fedora Wiki 系統作維護,比起其他教學指引可能資訊還新一些。除了專注於 Fedora 的部份之外,文件中的大部份內容都能用於其他採用 RPM 作為軟體包管理系統的 Linux 散布版。如果你覺得按耐不住了,你可以改看較簡短的 如何製作 RPM 軟體包。
目前 Fedora 文件已發行一份給打包者遵守的草擬規約,請見 Packagers Guide
請注意本篇內文並非 Fedora 官方軟體包的規約, 打包委員會 才是處理 Fedora 中軟體打包守則與規約的組織。其中最重要的是:
- Packaging Guidelines
- Licensing Guidelines
- Package Naming Guidelines
- Dist Tag Guidelines
- Package Review Guidelines
- Recipes for RPM post scripts
Packaging Guidelines 及 Package Naming Guidelines 皆是 Fedora 打包的主要規約。本頁的內容應與規約相容。
若你打算為 Fedora 軟體庫製作個 RPM 軟體包,請遵循 Join the package collection maintainers 中的步驟來做。
準備系統
在你為 Fedora 建立 RPM 軟體包之前,你需要安裝一些核心開發工具,並設置你會用到的帳號:
# yum install @development-tools # yum install fedora-packager
你可以特別為 RPM 軟體包的製作建立個傻瓜使用者 (dummy user),以避免建置程序出錯摧毀你的檔案,或將私人金鑰傳給全世界。
建立一位名為 makerpm
的傻瓜使用者,將使用者加入 'mock' 群組中,設定個密碼,並以該位使用者身份登入:
# /usr/sbin/useradd makerpm # usermod -a -G mock makerpm # passwd makerpm
一旦你以建置用假使用者登入後,在你的家屋目錄中執行以下指令來建立需要的目錄結構:
$ rpmdev-setuptree
rpmdev-setuptree
程式會建立 ~/rpmbuild
目錄與一組子目錄 (例:SPECS
與 BUILD
),你將利用它們製作軟體包。同時也會建立 ~/.rpmacros
檔,可用來設定許多選項。
打包規約建議保留檔案的時間戳記;如果你使用 wget
或 curl
下載源碼檔案的話,你可以讓程式自動保留時間戳記。如你使用 wget
下載源碼檔案,將「timestamping = on
」加入 ~/.wgetrc
組態中。如你使用 curl
的話,則將「-R
」加入 ~/.curlrc
組態中。
一般來說往後就不再需要重複以上步驟。
建置 RPM 軟體包的基本要領
製作 RPM 軟體包,你需要先有「.spec
」文字檔,這份檔案提供打包軟體的相關資訊。接著針對 SPEC 檔執行 rpmbuild
指令,進行產生軟體包的一系列步驟。
一般來說,你應該將原始 (原生) 來源,例如來自原開發者的 .tar.gz
檔,放進 ~/rpmbuild/SOURCES
目錄中。將 .spec
檔放進 ~/rpmbuild/SPECS
目錄中,並命名為「NAME.spec」,而 NAME 為軟體包的基礎名稱。最後同時製作二進位軟體包與源碼軟體包,先將目錄切換至 ~/rpmbuild/SPECS
並執行:
$ rpmbuild -ba NAME.spec
rpmbuild
會讀取 .spec
檔,並以下列所述階段走過檔案內容。以 %
開頭的字為預先定義的巨集 (請見下方的表格)。
階段 | 讀取 | 寫入 | 動作 |
---|---|---|---|
%prep (準備) |
%_sourcedir |
%_builddir |
它會讀取源碼目錄 %_sourcedir 下的源碼及補丁。它解開源碼封存檔,將內容放到建置資料夾 %_builddir (大多是 ~/rpmbuild/BUILD/) 內部的子資料夾內部,並套用補丁。
|
%build (建置) |
%_builddir |
%_builddir |
它會在建置資料夾 %_builddir 內部編譯檔案。這通常是執行 "./configure && make " 之類的指令。
|
%install (安裝) |
%_builddir |
%_buildrootdir |
它會讀取建置資料夾 %_builddir 內部的檔案,並寫入建置根基資料夾 %_buildrootdir 內部的一個目錄下。寫入的檔案即是使用者在安裝二進位軟體包時所要安裝的檔案。請留意這個怪異的術語:建置根基 (build root) 資料夾 並 不是 前面所說的 建置資料夾。 本步驟通常是執行 "make install "。
|
%check (檢查) |
%_builddir |
%_builddir |
檢查軟體是否可以順利運作。這通常是執行 "make test " 之類的指令。許多軟體包不處理這個步驟。
|
bin (二進位包) |
%_buildrootdir |
%_rpmdir |
它會讀取建置根基資料夾 %_buildrootdir 內部的檔案,以在 RPM 資料夾 %_rpmdir 內部製作二進位 RPM 軟體包。在 RPM 資料夾內有各個 CPU 架構的子資料夾,以及一個可給任何架構使用的 "noarch " 資料夾。這些 RPM 檔即是給使用者安裝用的軟體包。
|
src (源碼包) |
%_sourcedir |
%_srcrpmdir |
它會在源碼 RPM 資料夾 %_srcrpmdir 下製作源碼 RPM 軟體包 (.src.rpm )。這些檔案用於軟體包的校閱與上傳。
|
註:上述表格中的「下」與「內部」意思不同。例如有個檔案位於 /a/b/c,則 c 位於 a 的「內部」而非 a 之「下」。
如你所見,在 rpmbuild 中,特定的資料夾有特定的用途。這些是:
巨集名稱 | 名稱 | 通常 | 用途 |
---|---|---|---|
%_specdir | 規格 (Specification) 資料夾 | ~/rpmbuild/SPECS | RPM 規格 (.spec) 檔 |
%_sourcedir | 來源 (Source) 資料夾 | ~/rpmbuild/SOURCES | 元初來源封存檔 (如:tarball) 與補丁 (patch) |
%_builddir | 建置 (Build) 資料夾 | ~/rpmbuild/BUILD | 解開源碼檔並在此資料夾內部的子資料夾下編譯。 |
%_buildrootdir | 建置根基 (Build root) 資料夾 | ~/rpmbuild/BUILDROOT | 在 %install 階段中,檔案安裝於此處。 |
%_rpmdir | 二進位 (Binary) RPM 資料夾 | ~/rpmbuild/RPMS | 二進位 RPM 檔於此製作、儲存。 |
%_srcrpmdir | 源碼 (Source) RPM 資料夾 | ~/rpmbuild/SRPMS | 源碼 RPM 檔於此製作、儲存。 |
如果在某個階段失敗了,你需要查看詳細輸出內容以瞭解 為何 失敗,並根據所需修改 .spec 檔 (或其他輸入來源)。
準備好打包某個程式
如果需要有其他的特別程式才能建置或執行你想要打包的程式,先安裝那些程式然後記下來是哪些 (你會用到這些資訊)。
若要為 Fedora 軟體庫打包程式,你 必須 將元初 (原始) 來源連同修補檔與建置指示都一起包進去;採用預先編譯過的代碼「並不」妥當。請將原始來源 (通常是 .tar.gz
檔) 放在 ~/rpmbuild/SOURCES
目錄 (建置 RPM 的使用者帳號下) 中,然後用它來安裝檔案。
請先閱讀這個程式的手動安裝指示;你接下來會需要編輯「.spec」檔來將流程自動化,所以你必須先瞭解應該要怎麼做。 在你試圖用 RPM 建置程式之前,最好你先親手「實際跑過 (dry run)」建置一次 (如果你對 RPM 還不是很熟的話,這真的很重要)。 除了一些例外,Fedora 軟體中包含的所有二進位檔與函式庫,都必須從源碼軟體包中所含的源碼建置。
拆分程式
應用程式源碼經常與其他外部函式庫一起發行,也就是說整個「綁在一塊」。 然而,請不要將外部函式庫和主程式綁在一塊,統統包成一個軟體包。 相反的,請將他們拆分開來成為獨立的軟體包 。
判斷授權
請只打包法律上允許你打包的軟體。
請參見 Packaging:Guidelines#Legal、Licensing:Main、和 Packaging:LicensingGuidelines。 通常來說,只有以核可的開源軟體 OSS 授權 (例如 GPL、LGPL、BSD-new、MIT/X、或 Apache 2.0 等授權) 發行的軟體可以打包。 請確認軟體真的以這種方式授權 (例如:查看源碼的標頭、README 檔等等)。 如果軟體有綁函式庫,請確認這些函式庫也是採用 OSS 授權。
重複使用既有的軟體包資訊
盡可能重複使用。例如,請確認你想打包的不是早就有人打包過的東西。你可以從 Fedora Package Collection Fedora Package Database 中找到既有軟體包的清單。
也請查看 In Progress Review Requests 與 Retired Packages 清單。你可以直接使用 Fedora Packages Git Repositories 來檢視 SPEC 檔 (與修補檔)。你可以使用 <cod> yum-utils 軟體來下載 SRPMS:
# yum -y install yum-utils $ yumdownloader --source sourcepackage-name
另外,也可手動從 Fedora mirror http/ftp 網頁下的 releases/41/Everything/source/SRPMS
目錄取得源碼軟體包。請將「41
」替換成你想要使用的 Fedora 發行版本,接著下載該軟體的 .src.rpm
軟體包。
一旦你下載好 SRPM,請將它安裝到 ~/rpmbuild
:
$ rpm -ivh sourcepackage-name*.src.rpm
你也可以用 rpm2cpio
將 SRPM 包解開放到目錄中:
$ mkdir PROGRAMNAME_src_rpm $ cd PROGRAMNAME_src_rpm $ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i
有時候利用既有的軟體包作為開始是最簡單的方式,只要稍微清理一下就能讓 Fedora 使用。RPM Find 和 PKGS.org 可以幫你找到一些非 Fedora 系統的 RPM。你可以安裝其他系統的 SRPM,就像安裝 Fedora 的 SRPM 一樣。若找不到可以利用的軟體包,你或許可以參考看看給 Ubuntu 或 Debian 用的源碼軟體包 (不是 .deb
檔。源碼軟體包的檔案是標準的 tarball,但是有個「debian/
」子目錄)。如果 FreeBSD ports collection 中有你要的軟體,你可以下載 the FreeBSD ports tarball,然後看看他們的打包資訊是否能幫助你作為起點。不過,也有可能這些都一點幫助也沒有。不同的散布版有不同的規則,所以他們的作法或許對 Fedora 而言反而不妥。
製作 SPEC 檔
現在你需要在 ~/rpmbuild/SPECS
目錄中製作一份 SPEC 檔。你應該根據程式名稱來命名 (例:「program.spec
」) 這份檔案。你可以使用封存檔的名稱,或如果軟體作者有倡議該用怎樣的名稱就用該名稱,但無論如何都應遵守 軟體包命名規約 中的規範。
SPEC 樣板與範例
樣板
首次製作 SPEC 檔時,可以利用 vim 或 emacs 來自動建立樣板:
$ cd ~/rpmbuild/SPECS $ vim program.spec
以下是樣板看起來的模樣 (注意:供應的樣板不一定有遵守 Fedora 打包規約):
Name: Version: Release: 1%{?dist} Summary: Group: License: URL: Source0: BuildRequires: Requires: %description %prep %autosetup %build %configure make %{?_smp_mflags} %install %make_install %files %doc %changelog
你可以用 $RPM_BUILD_ROOT
取代 %{buildroot}
。這兩者都能用,只不過記得前後一致就好。
你也可以用 rpmdev-newspec
指令來製作 SPEC 檔。rpmdev-newspec NAME-OF-NEW-PACKAGE
可為新軟體包製作初始 SPEC 檔,適合各種類型的軟體包使用。它會根據你給的軟體包名稱來猜測可能的種類給予對應的樣板,你也可以直接指定特定的樣板。請見 /etc/rpmdevetools/spectemplate-*.spec
來查閱可用的樣板,也可見 rpmdev-newspec --help
瞭解更多資訊。舉例來說,若想為 python 模組製作個新 SPEC 檔:
cd ~/rpmbuild/SPECS rpmdev-newspec python-antigravity vi python-antigravity.spec
範本
eject
以下是 Fedora 16 中 eject
程式的 SPEC 檔:
Summary: A program that ejects removable media using software control Name: eject Version: 2.1.5 Release: 21%{?dist} License: GPLv2+ Group: System Environment/Base Source: %{name}-%{version}.tar.gz Patch1: eject-2.1.1-verbose.patch Patch2: eject-timeout.patch Patch3: eject-2.1.5-opendevice.patch Patch4: eject-2.1.5-spaces.patch Patch5: eject-2.1.5-lock.patch Patch6: eject-2.1.5-umount.patch URL: http://www.pobox.com/~tranter ExcludeArch: s390 s390x BuildRequires: gettext BuildRequires: libtool %description The eject program allows the user to eject removable media (typically CD-ROMs, floppy disks or Iomega Jaz or Zip disks) using software control. Eject can also control some multi-disk CD changers and even some devices' auto-eject features. Install eject if you'd like to eject removable media using software control. %prep %autosetup -n %{name} %build %configure make %{?_smp_mflags} %install %make_install install -m 755 -d %{buildroot}/%{_sbindir} ln -s ../bin/eject %{buildroot}/%{_sbindir} %find_lang %{name} %files -f %{name}.lang %doc README TODO COPYING ChangeLog %{_bindir}/* %{_sbindir}/* %{_mandir}/man1/* %changelog * Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.5-21 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild * Fri Jul 02 2010 Kamil Dudka <kdudka@redhat.com> 2.1.5-20 - handle multi-partition devices with spaces in mount points properly (#608502)
SPEC 檔概覽
其他有用的指引:
- RPM Guide 描寫如何寫作 SPEC 檔。
- IBM 系列文章 "Packaging software with RPM" Part 1, Part 2, and Part 3。
- Maximum RPM 包含最詳盡的資訊,但內容有點陳舊過時。
你需要遵守 Fedora 規約: Package Naming Guidelines, Packaging guidelines,以及 Package review guidelines。
你可以用「#
」字號作為註解的前導字元,但請避免用到可展開成許多列 (以 %
作開頭) 的巨集 (因為它們會先被替換展開)。如果要註解掉一列,百分比符號請改成兩個 (%%
)。此外,也請避免使用列內註解 (「#」),例如在同一列中使用指令稿指令提示符。
下方列的是主要標籤。請注意巨集 %{name}
、%{version}
、和 %{release}
可用來各自指稱 Name 名稱、Version 版本與 Release 發行版次標籤。只要更改標籤,巨集就會自動更新使用新值。
- Name:軟體包的 (基礎) 名稱,應該與 SPEC 檔名相符。它必須遵守 Package Naming Guidelines,一般只用小寫。
- Version:上游版本號。請見打包規約的 Version tag section。如果版本包含非數字標籤 (即版本標籤不是用數字表示),你可能需要在 Release 發行版次標籤中加入額外的非數字字元。如果上游版本標籤用的是完整日期來區隔版本,請考慮以
yy.mm[dd]
(例如:2008-05-01
就變成8.05
) 格式來作為版本號。 - Release:發行版次。初始值一般都應該是
1%{?dist}
。每次新發行同版本軟體的軟體包就遞增一個數字。若上游發行新的版本,就對應修改 Version 標籤,然後把 Release 發行版次重設回1
。請見打包規約的 Release tag section。選標的 Dist tag 可能會用得到。 - Summary:簡要的、只用一列的軟體包摘要。記得使用美式英文。 還有,「絕對不可以」加上半形句號 (.) 作為結尾。
- Group:這個標籤需要使用先前就已經存在過的群組,例如「Applications/Engineering」;請執行「
less /usr/share/doc/rpm-*/GROUPS
」來查閱完整列表。任何含有文件的子軟體包,請用「Documentation」作為群組 (例如:kernel-doc
)。 注意:這個標籤從 Fedora 17 之後就棄用了。請見 [File Reference Preamble] - License:授權條款,必須是開源軟體授權。請不要用舊的 Copyright 標籤。採用標準縮寫 (例如:「
GPLv2+
」),並且明確 (例如可採用 GPL 2 或後續版本,就寫「GPLv2+
」,而不是只隨便寫個「GPL
」或「GPLv2
」就算了)。請見 Licensing 與 Licensing Guidelines。你可以用「and
」以及「or
」來合併列出多種授權 (例如:「GPLv2 and BSD
」)。 - URL: 有關該程式更多資訊的完整 URL (例如該程式的專案網站)。 注意:這不是原本源碼的來源 URL,源碼封存檔的來源 URL 應該用下列的 Source0。
- Source0:包含 (原始) 元初源碼的壓縮後封存檔的完整 URL,即上游發行該源碼的位置。「
Source
」與「Source0
」同義。如果你給的是完整的 URL (而且你也該這麼做),會用其基礎名稱去查找SOURCES
目錄。如果可以的話,請用%{name}
和%{version}
替換嵌入 URL 中,這樣只要有所變動時都會自動對應。下載源碼檔案時記得保留時間戳記。如果不只有一份源碼封存檔,請用Source1
、Source2
等等依序羅列。如果你要在元初來源外還要再加一些全新的檔案,請將它們列在元初來源之後。任何你製作出的 SRPM 都會包入這些來源的副本,除非你有另外直接指定那就例外。請見 Source URL 瞭解更多特殊案例的資訊 (例如:revision control 修訂控制)。 - Patch0:第一個要套用到源碼上的修補檔 (patch) 名稱。如果你需要在檔案解壓縮之後對一些檔案作修補,你應該要先編輯檔案並將兩者間的差異儲存成「patch」檔,然後放在
~/rpmbuild/SOURCES
目錄下。一個 Patch 應該只做一種目的更動 (logical change),所以正常來講可能會有多個 patch 檔。 - BuildArch:如果你要打包的檔案並不依賴任何架構 (例如:shell 指令稿、資料檔等),那麼請用「
BuildArch: noarch
」。二進位檔 RPM 的架構就會跟著變成「noarch
」。 - BuildRoot:這是 %install 程序 (在 %build 程序之後) 期間檔案要「安裝」到的地方。這一項目前在 Fedora 中是多餘的,只有 EPEL5 還需要它。預設情況下,建置根基目錄放在「
%{_topdir}/BUILDROOT/
」。 - BuildRequires:建置 (編譯) 該程式所需要的軟體包列表,以半形逗號分隔各個項目。這個欄位可以 (而且通常) 多列重複。這些依賴項目 不會 自動判定,所以你需要納入建置該程式所需要的 所有 項目。有些常見軟體包可以省略,例如
gcc
。如果有必要,你也可以指定最低要求版本 (例:"ocaml >= 3.08
")。如果你需要/EGGS
檔案,可以執行「rpm -qf /EGGS
」來判斷它的所屬軟體包。請維持最低限度的依賴 (例如你不需要 perl 的功能,那就用sed
而不需用到perl
),但請注意有些應用程式若沒有某功能相關的依賴項目時,會永久停用該功能;這些情況中你可能需要納入額外的軟體包。auto-buildrequires
軟體包可能會有所用處。 - 'Requires:當程式安裝之時所需要的軟體包清單,請以半形逗號隔開各個項目。請注意 BuildRequires 標籤應列出的是建置二進位檔 RPM 的項目清單,而 Requires 標籤列出的是安裝/執行該程式所需的項目清單;一個軟體包可以放在其中一個清單,或同時兩個清單中。在許多情況下,
rpmbuild
會自動偵測依賴項目,所以不見得需要 Requires 標籤。然而,你可能會希望特別標明那些軟體包是需要的,或是哪些軟體包沒自動偵測到而你需要手動標明。 - %description:長篇的、跨多列的程式描述。請使用美式英文。每一列都必須小於等於 80 個字元。空白列表示新段落的開始。有些圖形使用者介面安裝程式會重新格式化段落;以空白起頭的列會被視為已預先格式化過的格式,會如其所述表現,顯示時一般採用等寬字型。請見 RPM Guide.
- %prep:「準備」程式的指令稿指令 (例如:將之解壓縮),這樣才能建置程式。一般這只是「
%autosetup
」。如果源碼檔案要解開放到NAME
的話,常見的變化形式是「%autosetup -n NAME
」。請見下方的 %prep 小節瞭解更多資訊。 - %build:「建置」程式的指令稿指令 (例如:編譯它),準備完成以便後續安裝。程式應該有附上如何執行此步驟的指示。請見下方 %build 小節來瞭解更多資訊。
- %install:「安裝」程式的指令稿指令。指令應該要將檔案從
BUILD
目錄%{_builddir}
複製到建置根基目錄%{buildroot}
中。請見下方的 %install 小節瞭解更多細節。 - %check:「測試」程式的指令稿指令。這是在 %install 程序後執行,所以如果你需要此區段的話,請將它放在該處。通常它僅包含「
make test
」或「make check
」。這要和 %build 分開,這樣人們才能在需要的時候略過自我測試。 - %clean: 清理建置根基目錄的指令。請注意這個區段目前在 Fedora 中是多餘的,並且只有 EPEL 需要。一般這只包含:
rm -rf %{buildroot}
- %files:會安裝的檔案清單。請見下方 %files 小節以瞭解更多細節。
- %changelog:軟體包的變動。請使用上述格式。請「不要」把軟體的變更記錄放在這裡。這裡是 RPM 自身的變更記錄。
- ExcludeArch:如果軟體包無法在某特定架構上成功編譯、建置或運作,請在此標籤下列出這些架構。* 你可以加入些代碼區段,這樣代碼會在軟體包於真實系統上安裝或移除時執行 (與之相反的是只執行 %install 指令稿,它只會作虛擬安裝 (pseudo-install),安裝到建置根基目錄中)。這些代碼稱之為「scriptlet」指令稿片段,他們通常以軟體包中的資訊更新執行中的系統。請見下方的「scriptlet」瞭解更多細節。
RPM 也支援從單一 SPEC 檔製作出多個軟體包 (稱為 子軟體包) 的功能,例如 name-libs
和 name-devel
等軟體包。
請不要製作「relocatable」可重新變換位置的軟體包;他們不會幫 Fedora 加值,反而把事情搞得更複雜。
SPEC 檔區段詳解
%prep 區段
%prep 區段描述的是如何解開壓縮後軟體包的方法,這樣才能拿來建置。一般而言,這包含「%autosetup
」指令。另外,你可以使用「%setup
」和「%patch
」指令搭配參照 Source0 (與 Source1 等) 條目。請見 Maximum RPM 一文中的 %setup and %patch 小節 瞭解更多細節。
自 RPM 4.4.2 起可以使用 %{patches} 和 %{source} 巨集,若你有大量補丁或來源清單,以及 %autosetup 效果並非你所想要的話會很好用,例如你可以這樣做:
for p in %{patches}; do ... done
然而請記住,使用上述功能,會讓你的 SPEC 和 RHEL 以及其他 RPM 散布版中所使用的 RPMS 不相容。
%prep 區段:%autosetup 指令
「%autosetup
」指令會解開來源軟體包。可用選項包括:
-n
name :如果 Source tarball 所要解開成的目錄名稱與 RPM 名稱不同,這個切換開關用來指定正確的目錄名稱。舉例來說,如果 tarball 要解開成 FOO 目錄,則使用「%autosetup -n FOO
」。-c
name :如果 Source tarball 需要解開成多個目錄,而非單一個目錄時,這個切換開關可以用來建立名為 name 的目錄,然後將內容解開放在裡面。
如我你改用「%setup
」指令,則通常使用 -q
' 來抑止不必要的輸出。
如果你打算解開多份檔案,有更多 %spec 選項可以用,這在你製作子軟體包時會很有用 (請見下方)。比較重要的有:
-a number |
在切入目錄後,只解開指定數字的 Source 目錄 (例:「–a 0 」代表 Source0)。
|
-b number |
在切入目錄前,只解開指定數字的 Source 目錄 (例:「–b 0 」代表 Source0)。
|
-D |
在解開之前不要刪除目錄。 |
-T |
停用自動解開封存檔。 |
%prep 區段:%patch 指令
如果你用的是「%autosetup
」指令,就不需要下列的手動補丁管理程序。如果你的需求很複雜,或是需要和 EPEL 相容,還是可能需要用到。「%patch0
」指令會套用 Patch0 (而 %patch1 會套用 Patch1,依此類推)。補丁是對來源程式碼做出必要修改使之符合打包規約的正常作法。常用的「-pNUMBER
」選項會傳遞引數給 patch
程式來套用對應補丁。
補丁的檔名通常看起來像是「telnet-0.17-env.patch
」這樣,命名格式依循「%{name} - %{version} - REASON.patch
」(不過有時候會省略 version 版本)。補丁檔通常是「diff -u
」的成果;如果你是從if you do this from the subdirectory of ~/rpmbuild/BUILD
的子目錄執行這個指令的,那麼你之後便不必指定 -p
層級。
這是為單一檔案製作補丁的典型程序:
cp foo/bar foo/bar.orig vim foo/bar diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
如果需要修改許多檔案,有個簡單的方法,就是複製 BUILD
下的整個子目錄,然後執行子目錄的 diff。在你切入「~rpmbuild/BUILD/NAME
」目錄後,執行以下指令:
cp -pr ./ ../PACKAGENAME.orig/ ... 修改許多檔案 ... diff -ur ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/NAME.REASON.patch
如果你想在一個補丁中編輯多重檔案,你也可以在編輯之前用同樣的檔名結尾「.orig
」來複製原始檔案。然後,你可以用「gendiff
」(在 rpm-build
軟體包中) 製作檔案差異的補丁檔。
試著確保你的路徑完全符合情境。預設的「fuzz」值是「0
」,代表比對要求完全相同。你可以加入「%global _default_patch_fuzz 2
」來轉換成舊版 Fedora RPM 版本所採用的值,但我們建議你應盡量避免這樣做。
如 Packaging/PatchUpstreamStatus 所詳述的,SPEC 檔中所有的補丁上方都要有個註解描述它的目前上游狀態為何。如果這是 Fedora 特別需要的補丁,你應該提及為何它如此特別。Fedora 專案致力不與上游分歧;請見 PackageMaintainers/WhyUpstream 瞭解此事的重要性。
%prep 區段:未修改的檔案
有時候,來源的一個或多個檔案並不需要解壓縮。你可以「prep」準備這些項目到建置目錄中,如 (這裡的 SOURCE1
代表對應的來源檔):
cp -p %SOURCE1 .
%build 區段
「%build」區段偶爾會有點複雜;在這個區段中你設置組態,並編譯/建置用來安裝的檔案。
許多程式採用 GNU configure
的方法 (或據此變化)。預設情況下,檔案會安裝到前綴為「/usr/local
」的路徑下,這對解開檔案的存放來說相當合理;但是,現在你是要打包程式,所以請將路徑前綴改成「/usr
」。函式庫則應該視架構而定,安裝到 /usr/lib
或 /usr/lib64
中。
由於 GNU configure
非常常見,可以自動使用「%configure
」巨集來喚起正確的選項 (例如,將前綴路徑改成 /usr
)。有些變化也多能作用:
%configure make %{?_smp_mflags}
若要凌駕 makefile 變數,請將它作為參數傳遞給 make
:
make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}
至於其他深入資訊,請參見 "GNU autoconf, automake, and libtool" 以及 "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer。
也有些程式使用 cmake
。請參見 Packaging/cmake。
%install 區段
本區段內含「安裝」該程式用的指令稿指令,即從 %{_builddir}
資料夾複製相關檔案到 %{buildroot}
中 (通常代表從 ~/rpmbuild/BUILD
複製到 ~/rpmbuild/BUILDROOT
),並且根據需要在 %{buildroot}
中新建資料夾。
有些術語的名稱可能讓人會錯意:
- 「建置目錄 build directory」,也稱為
%{_builddir}
,實際上和「建置根基 build root」,又稱為%{buildroot}
,是不一樣的資料夾。我們會在前者中編譯,而要打包的檔案則從前者複製到後者去。 - 在 %build 區段中,目前的目錄起始於
%{buildsubdir}
,是 %prep 階段中在%{_builddir}
下建立的子資料夾。這個資料夾名稱通常會是~/rpmbuild/BUILD/%{name}-%{version}
這樣。 - %install 區段在終端使用者安裝二進位 RPM 軟體包時並 不會 執行 ;事實上 %install 區段只有在製作軟體包時才會執行。
一般來說,這裡執行的是「make install
」之類的:
%install rm -rf %{buildroot} # redundant except for RHEL 5 %make_install
理想上您應該使用 %make_install,對於支援的程式來說,它等同於 DESTDIR=%{buildroot}
,因為它會重新導引檔案安裝到指定的目錄中,也就是我們在 %install 區段中預期發生的事。
如果程式不支援 DESTDIR
(且僅在有此情況之下),您有許多 (下方所列) 方式可以避開問題:
- 修補 makefile 來讓它支援
DESTDIR
。在DESTDIR
中視需要建立目錄,並提交該 patch 補丁給上游。 - 使用「
%makeinstall
」巨集。這個方法可能有效,但也可能導致些微失敗。該巨集會展開成「make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install
」,而可能導致有些程式無法正常運作。請在%{buildroot}
下視需要建立目錄。 - 考慮使用
auto-destdir
軟體包。它需要「BuildRequires: auto-destdir
」、並將「make install
」修改成「make-redir DESTDIR=%{buildroot} install
」。這只在安裝僅使用到特定常用指令來安裝檔案時才能作用,例如cp
和install
。 - 手動執行安裝。這可能牽涉到在
%{buildroot}
下建立必要的目錄,並從%{_builddir}
複製檔案到%{buildroot}
裡去。要特別注意更新,通常會有新檔名或修改過檔名。此程序的範例:
%install rm -rf %{buildroot} mkdir -p %{buildroot}%{_bindir}/ cp -p mycommand %{buildroot}%{_bindir}/
%check 區段
如果可以自我測試的話,將它們納入其中的話會是個好主意。他們應該放在 %check 區段中 (緊接在 %install 區段之後,因為應該測試 %buildroot 中的檔案) 而不是放在 %build 區段中,這樣才能在必要時刻輕易略過。
通常,此區段包含:
make test
有時候也可以用:
make check
請探索一下 Makefile 的用法,並選擇適當的方式。
%files 區段
此區段宣告哪些檔案與目錄是由該軟體包擁有,還有哪些檔案與目錄會放到二進位檔 RPM 中。
%files 基礎
%defattr
會設定預設的檔案權限,通常可以在 %files
區段的開頭看到使用。請注意到,如果不需要修改權限的話,那就不再需要用到它。它的使用格式為:
%defattr(<file permissions>, <user>, <group>, <directory permissions>)
第四個參數通常會省略。通常我們會這樣用 %defattr(-,root,root,-)
,其中「-
」代表預設權限。
您應該列出該軟體包擁有的所有檔案和目錄。請盡量用巨集來取代目錄名稱,您可以到 Packaging:RPMMacros (舉例:使用 %{_bindir}/mycommand
取代 /usr/bin/mycommand
) 來查看巨集表。如果起頭樣式為「/
」(或從巨集擴展而來),則從 %{buildroot}
目錄取用。否則,將假定檔案位在目前的目錄中 (例如:在 %{_builddir}
內部,例如您想要納入的文件檔)。若您的軟體包僅安裝單一檔案如 /usr/sbin/mycommand
,則 %files
區段可以像這樣簡單:
%files %{_sbindir}/mycommand
若要讓您的軟體包較不受上游改動而影響,請依這種樣式比對來宣告該軟體包擁有的目錄下所有檔案:
%{_bindir}/*
若要納入單一目錄:
%{_datadir}/%{name}/
請注意,%{_bindir}/*
並不會宣稱此軟體包擁有 /usr/bin
目錄,而只有包含其下的檔案。如果您列出一個目錄,則您正試圖宣稱該軟體包擁有這個目錄,以及該目錄內的所有檔案與子目錄。所以,請 不要 列出 %{_bindir}
,而且要小心處理那些可能和其他軟體包共享的目錄。
如果有下列情形可能引發錯誤:
- 試圖樣式比對,卻沒比對到任何檔案或目錄
- 重複列出或重複比對到某個檔案或目錄
- 沒有列出
%{buildroot}
下的某個檔案或目錄
您也可以使用 %exclude
glob 來從前個比對中排除檔案。這對於想用不同的樣式比對來將幾乎全部檔案納入其中時會很有用,但是請注意如果沒有比對到任何東西也會造成失敗。
%files 前綴字
您可能需要在 %files
區段的內容中加入一個或多個前綴字;請用空格隔開。請見 Max RPM section on %files directives。
通常,「%doc
」用來列出 %{_builddir}
內,但未複製到 %{buildroot}
中的文件檔。通常包括 README
和 INSTALL
檔。它們會放到 /usr/share/doc
下適當的目錄中,而 /usr/share/doc
的擁有權不必宣告。
注意: 如果有指定 %doc
條目,rpmbuild < 4.9.1 在安裝之前會將檔案安裝到其中的 doc 文件目錄移除。這代表已經放到裡面去的檔案,例如,在 %install
區段中安裝的檔案,會被移除,因此最終不會出現在軟體包中。如果您想要在 %install
區段中安裝一些檔案,請將它們安裝到建置目錄 (是 build dir,而不是建置根基 build root) 內的暫時鄰架目錄 (temporary staging directory) 中,例如 _docs_staging
,接著將之納入 %files
列表中,如 %doc _docs_staging/*
這樣。
組態檔應該要放在 /etc
中,一般會這樣指定 (可以確保使用者所作的更動不會在更新時被覆蓋):
%config(noreplace) %{_sysconfdir}/foo.conf
如果更新程序用的是無法向前相容的組態格式 (non-backwards-compatible configuration format),則應這樣指定:
%config %{_sysconfdir}/foo.conf
「%attr(mode, user, group)
」可以用來指派更精細的權限控制,而「-
」代表是用預設值:
%attr(0644, root, root) FOO.BAR
如果檔案是以特定的自然語言撰寫,請使用 %lang
來標註:
%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
使用到區域語言 (Locale) 檔案的程式應該遵循 處理 i18n 檔的建議方法 (英):
- 在
%install
步驟中找出檔名:%find_lang ${name}
- 加入必要的建置依賴:
BuildRequires: gettext
- 使用找到的檔名:
%files -f ${name}.lang
以下前綴字在 Fedora 中 無效:%license
和 %readme
。
%files 與檔案系統階層標準 (Filesystem Hierarchy Standard, FHS)
您應該遵守 檔案系統階層標準 (FHS)。執行檔應放在 /usr/bin
,全域組態檔放進 /etc
,函式庫放到 /usr/lib
(或 /usr/lib64
) 等等。只有一項例外:一般不該給使用者或管理員執行的執行檔,應該放到 /usr/libexec
中的子資料夾中,資料夾名稱為 %{_libexecdir}/%{name}
.
請 不要 把檔案安裝到 /opt
或 /usr/local
中。
不幸地,許多程式預設情況下並不遵守 FHS。尤其是,系統架構獨立的函式庫被放到 /usr/lib
而非 /usr/share
之中。前者是給系統架構依賴的函式庫使用,後者才是給系統架構獨立的函式庫運用;這代表不同 CPU 架構的系統都能共享 /usr/share
資料夾。Fedora 中也是有一些例外 (例如 Python 和 Perl),然而 Fedora 比起其他散佈版來說更嚴格遵守標準規範,rpmlint
一般會在你將 ELF 以外的檔案放進 /usr/lib
內時提出抱怨。
%files 範例
以下為 %files 區段的簡單範例:
%files %doc README LICENSE %{_bindir}/* %{_sbindir}/* %{_datadir}/%{name}/ %config(noreplace) %{_sysconfdir}/*.conf
找出重複檔案
您可以列出任兩個二進位軟體包的重複檔案,做法爲:
cd ~/rpmbuild/RPMS/ARCH # 請將 "ARCH" 替換為您的系統架構 rpm -qlp PACKAGE1.*.rpm | sort > ,1 rpm -qlp PACKAGE2.*.rpm | sort > ,2 comm -12 ,1 ,2
小指令稿 (Scriptlet)
當終端使用者在安裝 RPM 時,您可能想要執行一些指令。這可以透過小指令稿完成。請見 Packaging/ScriptletSnippets。
小指令稿可以:
- 在軟體包安裝之前 (
%pre
) 或之後 (%post
) 執行 - 在軟體包移除之前 (
%preun
) 或之後 (%postun
) 執行 - 在處理事項的開頭 (
%pretrans
) 或結尾 (%posttrans
) 執行
舉例來說,每一會在任何 dinamic linker 預設路徑中儲存共享函式庫檔案的二進位檔 RPM 軟體包,都必須在 %post
和 %postun
中呼叫 ldconfig
。如果該軟體包有多個附帶函式庫的子軟體包,則每個軟體包也都應該執行相同的動作。
%post -p /sbin/ldconfig %postun -p /sbin/ldconfig
如果僅執行單一指令,則「-p
」選項會執行相接的指令但不會喚起 shell。然而,若有許多指令時,請省去這個選項,並在其下納入 shell 指令。
如果你在小指令稿中有執行任何程式,你就必須以「Requires(CONTEXT)
」(例: Requires(post)
) 的形式來列出所有的執行需求。
%pre
、%post
、%preun
、和 %postun
提供了 $1
引數,表示動作完成之後系統上留下的此名稱之軟體包有幾個。請不要拿這個值來比較是否等於 2
,而是比較是否大於或等於 2
。至於 %pretrans
和 %posttrans
,$1
的值則恆為 0
。
舉例來說,如果軟體包安裝了一份 info manual (資訊手冊),那麼可以用 info
軟體包提供的 install-info
來更新資訊手冊索引。首先,我們不保證 info
軟體包總會存在,除非我們明確宣告它是必備的部分;再來,我們不想要在 install-info
失敗之時讓軟體包的執行動作完全失敗:
Requires(post): info Requires(preun): info ... %post /sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || : %preun if [ $1 = 0 ] ; then /sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || : fi
還有一件安裝資訊手冊時相關的小瑕疵。install-info
指令會更新資訊目錄,所以我們應該要在 %install
區段中刪掉 %{buildroot} 中無用的空目錄:
rm -f %{buildroot}%{_infodir}/dir
另一個類似小指令稿的能力是「triggers」(觸發器),可以在其他軟體包已安裝或已移除之時,為你的軟體包執行一些動作。請見 RPM Triggers。
巨集 (Macro)
巨集是 %{string}
這類寫法的文字。典型的巨集有:
巨集 | 典型擴展 | 意義 |
---|---|---|
%{_bindir} |
/usr/bin |
二進位檔資料夾 (Binary directory):執行檔通常存放的位置。 |
%{_builddir} |
~/rpmbuild/BUILD |
建置資料夾 (Build directory):檔案放在建置目錄下的子目錄中編譯。請見 %buildsubdir 。
|
%{buildroot} |
~/rpmbuild/BUILDROOT |
建置根基 (Build root):在 %install 階段中的檔案「安裝」之處,會將 %{_builddir} 子目錄下的檔案複製到 %{buildroot} 的子目錄之下。(過去,%{buildroot} 所採用的位置是「/var/tmp/」。)
|
%{buildsubdir} |
%{_builddir}/%{name} |
建置子資料夾 (Build subdirectory):在 %build 階段中檔案會在 %{_builddir} 的子目錄中編譯。這個位置會在 %autosetup 後設置。
|
%{_datadir} |
/usr/share |
共用資料夾。 |
%{_defaultdocdir} |
/usr/share/doc |
預設文件資料夾。 |
%{dist} |
.fcNUMBER |
散佈版+版本短名 (例:「.fc41 」)
|
%{fedora} |
NUMBER |
fedora 發行版號 (例:「41 」)
|
%{_includedir} |
/usr/include
| |
%{_infodir} |
/usr/share/info
| |
%{_initrddir} |
/etc/rc.d/init.d
| |
%{_libdir} |
/usr/lib
| |
%{_libexecdir} |
/usr/libexec
| |
%{_localstatedir} |
/var
| |
%{_mandir} |
/usr/share/man
| |
%{name} |
軟體包的名稱,由 Name: tag 決定 | |
%{_sbindir} |
/usr/sbin
| |
%{_sharedstatedir} |
/var/lib
| |
%{_sysconfdir} |
/etc
| |
%{version} |
軟體包版本,由 Version: tag 決定 |
您可以查看 /etc/rpm/*
和 /usr/lib/rpm
、甚至是 /usr/lib/rpm/macros
以進一步瞭解巨集。或是用 rpm --showrc
來顯示 RPM 運用這些巨集時所採用的值 (會根據 rpmrc
與巨集組態檔而有所變動)。
您可以利用 %global 來定義自己的巨集值,但是請確定在使用巨集之前先已定義過。(巨集在定義之時也可以指涉 (refer to) 其他巨集。) 範例:
%global date 2012-02-08
請用 rpmbuild
的「-E
」選項來尋找巨集在 SPEC 檔中代表的值:
rpmbuild -E '%{_bindir}' myfile.spec
也請參見 Packaging/RPMMacros 和 RPM Guide chapter 9。
其他標籤 (tag)
除了 Requires 和 BuildRequires 標籤之外,你還可以使用以下這些控制依賴關係:
- Provides:列出此軟體包提供的虛擬軟體包名稱。例如,可能有個
foo
軟體包需要來自其他程式的「bar」功能;若有許多軟體包可以滿足該需求,則這些軟體包可以指定「Provides: bar
」,而「foo
」軟體包則可以指定「Requires: bar
」。你也可以使用 "alternatives" 系統,但是若同個系統中有多位使用者,不同人可能希望使用不同的預設值,此時請避免使用它,畢竟這些設定屬於系統全域設定。請用「rpm -q --provides PACKAGENAME
」來查看指定的軟體包提供那些東西。一些 Fedora 中虛擬軟體包的範例:- MTA:用作郵件傳輸代理 (mail transport agent, MTA),例如 sendmail。
- tex(latex): 用作 latex
- Obsoletes:當這個軟體包安裝時移除另一個指名的軟體包。當軟體包名稱更換之時,或是用該軟體包完全取代另一個不同的軟體包之時可以使用。
- Conflicts:表示無法與此軟體包同時安裝的其他軟體包。如果可以請避免使用這個標籤。請見 Packaging/Conflicts。
- BuildConflicts:表示在建置此軟體包之時無法安裝的軟體包。如果可以請避免使用這個標籤。
若要處理不同的系統架構,有兩種標籤可以使用:
- ExcludeArch:排除此軟體包無法建置的系統架構。例如:
ExcludeArch: ppc
- ExclusiveArch:僅納入指定的系統架構。除非絕對正確,否則請避免使用。
可用的系統架構列在 Architectures 中。
子軟體包 (或稱細分包,Subpackage)
一份 SPEC 檔可以定義多份二進位檔軟體包。換句話說,一個內含一份 SPEC 檔的 SRPM 檔可能製作出許多 RPM 檔來。請注意到這依然只會有一道製作 (%prep、%build、%install 等) 程序。 name-doc
和 name-devel
為常見的文件檔和開發檔子軟體包。
請使用 %package
巨集指令來定義子軟體包:
%package subpackage_name
在每個 %package
指令之後,請列出該子軟體包的數個標籤 (tag)。這應該至少包括 Summary 和 Group 標籤、以及 %description subpackage_name
和 %files subpackage_name
指令:
任何子軟體包中未特別指定到的東西,都會從其親代沿襲下來。
預設情況下,如果該軟體包的名稱為「foo
」而子軟體包名稱為「bar
」,則子軟體包成果則會是「foo-bar
」。你可以利用「-n
」選項 (但如果你在這裡特別指定的話,你也需要在所有其他的指令中用到這道指令) 來凌駕原先的規則:
%package -n new_subpackage_name
請見 RPM Guide 針對子軟體包所寫的小節瞭解更多資訊。
條件判斷 (Conditional)
你可以插入條件判斷陳述,例如測試你是否會為特定系統架構製作二進位檔:
%ifarch ARCHITECTURE_NAME
反面 (negated) 的論述版本為:
%ifnarch ARCHITECTURE_NAME
或更一般的條件判斷式:
%if TRUE_OR_FALSE
也有個可選擇性使用的「%else
」區段;以上這些全都必須以「%endif
」作結尾。
應用程式專門規約
有許多應用程式專門規約可以協助你 (例:專門的程式語言、應用程式、函式庫、建置系統等)。大多都列在 應用程式專用打包規約/規約 (英) 之中。一些應用程式專門規約的例子有:
如果上述的資訊都沒有涵括到,還有一些可以幫助你找到應用程式專用協助的方法:
- Fedoraproject.rog 上的「SEARCH」指令。
- PackagingDrafts
- Special Interest Group (SIG)
- 名稱以「Packaging」起頭的 Wiki 頁面
其他注意事項 (Miscellaneous hints)
Packaging/FrequentlyMadeMistakes 有列出常見錯誤的相關資訊。PackageMaintainers/Packaging Tricks 則有列出一些建議、以及具爭議性的技巧。
請試著撰寫你的 SPEC 檔,盡可能讓上游發行新版本時一切都能水到渠成,使你除了要改版本號並刷新來源檔案外,都不必做任何其他修改。舉例來說,如果要替 *.txt 檔設執行位元,請不要用
chmod a-x Filename1.txt Filename2.txt Filename3.txt
而是考慮用以下這種方式來處理,可以直接處理使用相同命名規則的新檔名:
chmod a-x *.txt
如果你想要查看大量的小指令稿範例,你可以利用下列指令來顯示所有已安裝程式的小指令稿:
rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less
請不要嘗試和使用者互動;RPM 是以支援批量安裝為設計核心。如果有個程式需要顯示 EULA 終端使用者授權協議,則該動作應是初次執行時才做,而非安裝之時做。
建議你不要試圖啟動服務,因為在大量安裝的過程中可能會讓一切變得緩慢。若你有安裝 init 或 systemd 指令稿,請考慮用 chkconfig
或 systemctl
來安排服務在下次重新開機之時啟動/停止該項服務。在解除安裝之前,如果這些服務還在跑,一般而言你應該先嘗試停止這些服務。
解除安裝應該要盡可能還原安裝階段中所做過的改變,但是不要移除任何使用自行建立的檔案。
一般而言,如果有二進位執行檔,則一般二進位軟體包應該剝離除錯用符號 (debugging symbols),並放到 name-debug
子軟體包中。如果不應發生這樣的事,你可以在你的 SPEC 檔頂端放入停用剝離動作:
%global _enable_debug_package 0 %global debug_package %{nil} %global __os_install_post /usr/lib/rpm/brp-compress %{nil}
若想避免剝離動作,你也需要在 %install
區段中做以下動作:
export DONT_STRIP=1
在 SPEC 檔中檢查 Fedora 版本作條件判斷式建置的方法:A way to check for the version of Fedora in a SPEC file for conditional builds is:
%if 0%{?fedora} <= <version>
?
會讓巨集在 %fedora
未定義之時評斷為空白。這樣會讓結果成為 0
(數字零,所以很好),而 %fedora
若真的有個數值時也不會有所干擾。(請注意這種做法在 Koji 的「scratch」建置中沒有作用,%fedora
的值會在 SRPM 製作之時就設定好。)
GUI 程式必須有桌面條目 (desktop entry),這樣用戶才能從圖形化桌面選單中喚起這些程式。對於 .desktop
檔案,請見 Fedora packaging guidelines for desktop files 和 desktop entry spec;至於 /usr/share/icons
,請見 icon theme spec。
建置二進位軟體包
利用 rpmlint 作測試
若要在早期捕捉個種常見錯誤,請在嘗試用 SPEC 檔建置任何軟體包之前先對它執行 rpmlint
:
$ rpmlint program.spec
如果回報的錯誤看起來不怎麼合理,請重新以「-i
」選項執行以取得更詳細的訊息。
請以無報錯為目標,不過有時 rpmlint
會有誤報的情況發生。Fedora 打包規約 中有解釋到那些錯誤可以忽略。
以 SPEC 檔製作二進位 RPM 包
一旦你做好 SPEC 檔之後,請執行以下指令來建置 SRPM 與二進位 RPM:
$ rpmbuild -ba program.spec
如果製作成功,RPM 會放到 ~/rpmbuild/RPMS
裡面,而 SRPM 會放到 ~/rpmbuild/SRPMS
之內。
如果製作失敗,請前往對應的資料夾來看看留下了什麼。若想取得除錯協助,你可以用「--short-circuit
」選項來略過早期的成功階段。例如:若想要 (略過更早期階段) 重新從 %install
階段開始,請執行:
$ rpmbuild -bi --short-circuit program.spec
若你只想要製作 SRPM 檔 (不會執行 %prep
或 %build
或其他階段),請執行:
rpmbuild -bs program.spec
利用 rpmlint 來測試二進位 RPM 檔
rpmlint
可以對 SPEC 檔、RPM 檔、SRPM 檔執行來檢查是否存在錯誤。你需要在發佈軟體包之前解除或糾正發出的警告。這個網頁提供一些常見問題的解釋。如果你位於 SPEC 目錄中,請執行:
$ rpmlint NAME.spec ../RPMS/*/NAME*.rpm ../SRPMS/NAME*.rpm
請進入 ~/rpmbuild/RPMS
目錄,再進入系統架構子目錄中。你會看到一些二進位檔 RPM。請用以下指令快速查看這些檔案和權限 (來檢查看看是否正確):
$ rpmls *.rpm
如果一切看起都很好,請以 root 身份安裝:
# rpm -ivp package1.rpm package2.rpm package3.rpm ...
請以不同的方式來測試程式看是否全部都正常運作。如果它是 GUI 工具,請確認有出現在桌面選單中,否則代表 .desktop
條目可能有錯。
稍後可以利用以下指令來解除安裝軟體包:
# rpm -e package1 package2 package3
Mock 和 Koji
Mock 是在近乎空白的環境下,運用你剛製作的 SRPM 來建置二進位軟體包的強大工具。這可以揭露你實際的建置依賴關係。如果建置失敗,則代表你忘記在 BuildRequires 中列出其中一些東西。請參見 Using Mock to test package builds。一旦你的帳號屬於「mock
」群組的成員之一,你可以執行這樣的指令來做本地端測試:
$ mock -r fedora-9-i386 rebuild path_to_source_RPM
你可以利用 Koji (會運用 mock
) 在各種不同的系統上執行建置,包括那些你沒有的系統架構。PackageMaintainers/Join 和 PackageMaintainers/UsingKoji 上面有更多有關 Koji 的資訊。一旦設定完成,你就可以在各種平臺上使用以下指令來測試你的 SRPM:
$ koji build --scratch dist-f9 path_to_source_RPM
請將 dist-f9
以任意近期 Fedora 發行版本替換,但別使用 dist-rawhide
。請記住,%fedora
、%fc9
、等這類的值都不會在 scratch build 中得到修正,所以如果你的 SPEC 檔會依據上述值來做不同的事,則無法作用。
你的 Koji 建置僅能依賴 TARGET 散佈版軟體庫中實際存在的軟體包。所以,如果你的軟體包依賴 Bodhi 尚未發行的其他軟體包,就無法用 Koji 來為已發行的散佈版作建置。如果你需要對尚未成為穩定版的發行更新建置軟體包,請透過 Bodhi 提交 Koji 建置根基凌駕請求 (Koji buildroot override requet)。如果它並非你的軟體包依賴,請聯絡其維護者。[在 Bodhi 可以處理 Koji 建置根基凌駕請求之前,以前的舊方法是在此處對 rel-eng 提交請票 (ticket):https://fedorahosted.org/rel-eng/newticket ,並請求將該軟體包加入成為建置根基凌駕之一。]
有用的工具
rpmdevtools
軟體包有各種好用工具;「rpm -qil rpmdevtools
」會展示給你看它會安裝哪些東西。
rpmdev-bumpspec
:增進 SPEC 檔中的發行版本標籤,並以當下時間與版本格式加入 changelog 評註:
rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
yum-utils
軟體包也提供一些好用工具:
yumdownloader
:請執行以下指令下載該軟體包的 SRPM:
yumdownloader --source PACKAGENAME
auto-buildrequires
軟體包有一對優質工具可以幫助我們找出適當的 BuildRequires 條目。在安裝這個軟體包之後,請用「auto-br-rpmbuild
」替換 「rpmbuild
」,你就會看見自動產生的 BuildRequires 清單。
你可能發現到 RUST 滿好用的 (GPL),但是它無法製作出符合 Fedora 軟體包品質的 SPEC 檔。Alien 則可以在軟體包格式之間轉換;它無法製作出乾淨的 SRPM,但是從既有的軟體包轉換程式或許能提供一些有用的資訊。
最後,docker-rpm-builder (APL 2.0) 使用 Docker 來建置 RPM 軟體包;想用 rpmbuild 建置的目標架構需要與主控散佈版相同,至於 mock 則對於任何目標架構的 Fedora/Centos/RHEL 散佈版都能良好處理,這是無論 Docker 是否能跑都能運用的最後工作。
若你想要為你的軟體包建置出不同的散佈版與系統架構,並且公開存取 yum 軟體庫,你可以提交你的 src.rpm 到 Copr。
規約與規則
當你製作軟體包之時,你需要遵守下列規則與規約:
有許多官方規約可以引導你處理一些特定情況 (例:Java 程式、OCaml 程式、GNOME 程式等)。你也可以從 SIG 瞭解更多資訊,與 軟體包維護者 小節。
你也可以查看所有關於打包的 Wiki 頁面來看是否有適用的。
如果找不到,你可能想要找一些非官方的好用建議,例如 Packaging Drafts 和 Packaging Drafts To Do。
你也可以從 SuSE、 Debian 的資料中找到一些想法,但是 各個散佈版所用的規則會不同,所以不要直接想說他們的東西可以直接拿來用。
你製作的 .spec 檔必須是開源軟體,如 FPCA 中所提及。
維護軟體包
一旦你的軟體包被接受,你和你的共同維護者會需要維護這份軟體包。請見 Package update HOWTO 和 Package update guidelines。如果你在多個 Fedora 發行版中更新了它的版本,請即時往前做 (例:為 Fedora N 發行新版,一旦被接受,就做 Fedora N-1)。系統會假定新的 Fedora 版本會有相同版本或更後續版本的程式。
請鼓勵上游開發者使用標準源碼發行慣例。請使用標準慣例以便讓打包流程更輕鬆。若想要瞭解更多資訊,請見:
- Releasing Free/Libre/Open Source Software (FLOSS) for Source Installation (簡明摘要)
- GNU Coding Standards release process
- Software Release Practice HOWTO
- Filesystem Hierarchy Standard (FHS)
- Packaging Unix software
更多資訊
Package Maintainers 頁面連結到許多其他有用的網頁去,而 Package update HOWTO 則描述了如何更新你已經在 Fedora 中維護的既有軟體包。
若想瞭解更多資訊,在 Fedora Wiki 以外的地方,可以看看下面這些:
- How to build RPM packages on Fedora - very brief run-through
- Packaging software with RPM (developerWorks) Part 1, Part 2, and Part 3
- Fedora Classroom had a IRC session on packaging and you can refer to the logs at https://fedoraproject.org/wiki/Building_RPM_packages_%2820090405%29
- Fedora Packager's Handbook
- When Sally met Eddie - a simple tale, but little detail
- Maximum RPM Book - most complete information, but in some cases old/obsolete
- RPM Guide, section on creating RPMs - this has lots of good information, and is slightly more up-to-date, but is a draft
- Developer's guide, section on building RPMs
- Creating RPMS slides from Guru Labs
- The fight, my first attempt to make a readable rpm package building introduction.
- Cambridge RPM tutorial is a presentation on creating basic RPMs
- RPM HOWTO: RPM at Idle by Donnie Barnes
- RPM HowTo by Dawson
- Cross-distribution package HOWTO has hints if you're building one RPM for many distributions.
- Mandriva Rpm HowTo (en) is an RPM tutorial, though for Mandriva (nee Mandrake). Note: In Fedora, do not recompress original tarballs, as Mandriva suggests, because that would change their cryptographic hashes.
- Creating Your Own Linux RPM's - The Initial Software Build is another brief intro, but it makes the point that "The process of building RPM's is much simpler than creating packages for Solaris... Fewer steps, and the ability to add all of your software information into one specification file, makes for a much tighter (and easier to modify or reproduce) software packaging system."
- All you need to know about RPM (more about installing packages than creating them)
- The rpm.org Wiki has some useful information, such as the list of known RPM problems
註:rpm5.org 網站也有提供一些文件,但是請不要依靠裡面的內容;那是 Jeff Johnson 維護的 RPM「分支」,也就是 fork。Fedora (和 Novell/SuSE) 所用的 RPM 則是基於 rpm.org。 lwn.net 有個簡要的文章報導這件事。