From Fedora Project Wiki
(add category zh)
(43 intermediate revisions by 4 users not shown)
Line 1: Line 1:
''翻譯:[[User:Kaio| Caius 'kaio' Chance]]''
{{autolang}}
''翻譯:[[User:Kaio| Caius 'kaio' Chance]] 與 [[User:Zerng07|Cheng-Chia Tseng]]''


== 建立套件教程 ==
== 簡介 ==


本頁面解說如何建立 Fedora 專用 RPM 套件的基本流程(更具體說就是如何建立一個 .spec 檔案)。本頁面也會提供一些實用的資訊關於怎樣做會成功怎樣做會失敗,這樣可以節省您往後很多時間。
本頁旨在詳細解說製作 RPM 軟體包的方法,特別是指製作 SPEC 檔的方法。不像其他的 RPM 教學指引,本頁有針對 Fedora 的規格作解說,並附上 Fedora 專用的規約 (guideline) 連結。由於本頁內容是以 Fedora Wiki 系統作維護,比起其他教學指引可能資訊還新一些。除了專注於 Fedora 的部份之外,文件中的大部份內容都能用於其他採用 RPM 作為軟體包管理系統的 Linux 散布版。如果你覺得按耐不住了,你可以改看較簡短的 [[How_to_create_an_RPM_package/zh-tw|如何製作 RPM 軟體包]]。


本頁面 '''' 是 Fedora 的正式包裝指南(如是,請參閱 [[Packaging:Guidelines|  包裝指南]] 及 [[Packaging:NamingGuidelines|  套件命名指南]])。然而,本頁面 ''應該'' 跟它們兼容。
'''目前 Fedora 文件已發行一份給打包者遵守的草擬規約,請見 [http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide Packagers Guide]'''


雖然本頁面不會深入各種主題,但是會指引到那些有更詳細內容的文件。不像很多 RPM 指南文件,本文件專用於 Fedora(附帶很多 Fedora 專用指南的連結)和更新(在 Fedora Wiki 上維護的原因)。
請注意本篇內文'''並非 '''Fedora 官方軟體包的'''規約''', [[Packaging:Committee| 打包委員會]] 才是處理 Fedora 中軟體打包守則與規約的組織。其中最重要的是:


例如,它警告 [http://lists.autistici.org/message/20080709.212842.3f8877db.de.html RPM 4.4.2.x 開始作用這改變帶來] 的重大影響。雖則它集中在 Fedora,本文件的大部分 ''都'' 適用於其他基於 RPM 的發行版。
* [[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]]


如果你打算建立一個 RPM 套件放到 Fedora 源,跟隨[[Join the package collection maintainers|如何加入 Fedora 套件集合維護者]]的程序,包括以下各種 Fedora 導引。
'''[[Packaging:Guidelines|Packaging Guidelines]] 及 [[Packaging:NamingGuidelines|Package Naming Guidelines]] 皆是 Fedora 打包的主要規約。本頁的內容應與規約相容。


== 設定您的系統及帳號 ==
若你打算為 Fedora 軟體庫製作個 RPM 軟體包,請遵循 [[Join the package collection maintainers]] 中的步驟來做。


在您建立 Fedora 上的 RPM 套件之前,您需要安裝某些核心開發工具及設定您將會用的帳號。作為 root(不要輸入"#"!):
== 準備系統 ==


  # yum groupinstall "Development Tools"
在你為 Fedora 建立 RPM 軟體包之前,你需要安裝一些核心開發工具,並設置你會用到的帳號:
  # yum install rpmdevtools
# yum install @development-tools
# yum install fedora-packager


您就能建立一個新的 "傻瓜用戶" (Dummy User) 專用作建立 RPM 套件。如是者,如果任何東西變得非常不妙,程式及編譯進程不能破壞您的檔案,或者把您的私密檔案/金鑰分發到全世界。還有絶對不要用 root 建立您的套件。
你可以特別為 RPM 軟體包的製作建立個傻瓜使用者 (dummy user),以避免建置程序出錯摧毀你的檔案,或將私人金鑰傳給全世界。
{{admon/caution|你「永遠」都不該以 <code>root</code> 使用者的身份製作 RPM 軟體包。用 root 帳號建置 RPM 非常危險,因為軟體在打包之前就會將二進位檔安裝在系統之中,所以你必須總是使用一般使用者來建置,以免意外污染你的系統。}}


您可以輸入以下命令,快速地建立一個新用戶叫 "makerpm" :
建立一位名為 <code>makerpm</code> 的傻瓜使用者,將使用者加入 'mock' 群組中,設定個密碼,並以該位使用者身份登入:


  # /usr/sbin/useradd makerpm
# /usr/sbin/useradd makerpm
# usermod -a -G mock makerpm
# passwd makerpm


然後登入那個特別的傻瓜用戶(makerpm)。
一旦你以建置用假使用者登入後,在你的家屋目錄中執行以下指令來建立需要的目錄結構:
$ rpmdev-setuptree


當您已經登入那個將會建立套件的用戶,在您的個人文件夾輸入以下命令以建立文件夾結構(不要輸入"#"!):
<code>rpmdev-setuptree</code> 程式會建立 <code>~/rpmbuild</code> 目錄與一組子目錄 (例:<code>SPECS</code> 與 <code>BUILD</code>),你將利用它們製作軟體包。同時也會建立 <code>~/.rpmacros</code> 檔,可用來設定許多選項。


  $ rpmdev-setuptree
[[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> 組態中。


"rpmdev-setuptree" 程式將會建立一個 ~/rpmbuild 文件夾。在 "rpmbuild" 之下是一系列子文件夾(例如 SPECS 及 BUILD),您將會使用它們建立您的套件。"rpmdev-setuptree" 也會建立一個 ~/.rpmmacros 檔案用來讓 rpm 和 rpmbuild 應當地使用那些文件夾。
一般來說往後就不再需要重複以上步驟。


[[Packaging:Guidelines#Timestamps|包裝指南建議使用能保存檔案時間標記的命令]]:如果您使用 wget 或 curl 獲取源碼檔案,您可以把它弄成自動。如果您使用 wget 獲取源碼檔案,可考慮在 ~/.wgetrc 加上 "timestamping = on"。再者,如果您使用 curl,可考慮在 ~/.curlrc 加入 "-R"。
== 建置 RPM 軟體包的基本要領 ==


當您完成設定用戶帳號,您應該不會需要再重做一次這些步驟。
製作 RPM 軟體包,你需要先有「<code>.spec</code>」文字檔,這份檔案提供打包軟體的相關資訊。接著針對 SPEC 檔執行 <code>rpmbuild</code> 指令,進行產生軟體包的一系列步驟。


== 編譯 RPM 套件的基本步驟 ==
一般來說,你應該將原始 (原生) 來源,例如來自原開發者的 <code>.tar.gz</code> 檔,放進 <code>~/rpmbuild/SOURCES</code> 目錄中。將 <code>.spec</code> 檔放進 <code>~/rpmbuild/SPECS</code> 目錄中,並命名為「''NAME''.spec」,而 ''NAME'' 為軟體包的基礎名稱。最後同時製作二進位軟體包與源碼軟體包,先將目錄切換至 <code>~/rpmbuild/SPECS</code> 並執行:


要建立一個 RPM 套件,您將會需要建立一個 ".spec" 文字檔包含軟體如何被包裝的資訊。然後,您向 spec 檔案執行 "rpmbuild" 命令,它會進行一系列的步驟去製作您的套件。
$ rpmbuild -ba ''NAME''.spec


一般您應該把您的原版 (prestine) 源碼,例如把來自原作者的 .tar.gz 檔案,放在 "~/rpmbuild/SOURCES"。您應該把 .spec 檔案放在 "~/rpmbuild/SPECS" 及命名成 "''名字''.spec",''名字''是套件的(基礎)名字。要建立所有套件(包括二位元及源碼套件),您進入 "~/rpmbuild/SPECS" 文件夾再執行:
<code>rpmbuild</code> 會讀取 <code>.spec</code> 檔,並以下列所述階段走過檔案內容。以 <code>%</code> 開頭的字為預先定義的巨集 (請見下方的表格)。


rpmbuild -ba ''名字''.spec
{|border="1" cellspacing="0"
 
! 階段 !! 讀取 !! 寫入 !! 動作
這樣做之後,rpmbuild 將會讀取 .spec 檔案然後試圖進行以下步驟(以此順序;以下前輟 % 的名字是預先定義的巨集,亦列出了每個步驟一般會讀取及寫入的文件夾):
 
{|
! Stage !! Reads !! Writes !! Action
|-
|-
|%prep||%_sourcedir||%_builddir||它讀取源碼包及套用 patch 到源碼文件夾 %_sourcedir (大多是 ~/rpmbuild/SOURCES)。它解開源碼包到一個編譯文件夾 %_builddir 以下的一個次文件夾 (大多是 ~/rpmbuild/BUILD/) 及套用該 patch。
|<code>%prep</code> (準備) ||<code>%_sourcedir</code>||<code>%_builddir</code>||它會讀取源碼目錄 <code>%_sourcedir</code> 下的源碼及補丁。它解開源碼封存檔,將內容放到建置資料夾 <code>%_builddir</code> (大多是 ~/rpmbuild/BUILD/) 內部的子資料夾內部,並套用補丁。
|-
|-
|%build||%_builddir||%_builddir||它編譯編譯文件夾 %_builddir (大多是 ~/rpmbuild/BUILD/)的檔案。這經常包含執行 "./configure ; make" 相似的命令。
|<code>%build</code> (建置) ||<code>%_builddir</code>||<code>%_builddir</code>||它會在建置資料夾 <code>%_builddir</code> 內部編譯檔案。這通常是執行 "<code>./configure && make</code>" 之類的指令。
|-
|-
|%check||%_builddir||%_builddir||Check that the software works properly.  This is often implemented by running some variation of "make test".  Many packages don't implement this stage.
|<code>%install</code> (安裝) ||<code>%_builddir</code>||<code>%_buildrootdir</code>||它會讀取建置資料夾 <code>%_builddir</code> 內部的檔案,並寫入建置根基資料夾 <code>%_buildrootdir</code> 內部的一個目錄下。寫入的檔案即是使用者在安裝二進位軟體包時所要安裝的檔案。請留意這個怪異的術語:''建置根基 (build root) 資料夾'' 並 '''不是''' 前面所說的 ''建置資料夾''。 本步驟通常是執行 "<code>make install</code>"
|-
|-
|%install||%_builddir||%_buildrootdir||This reads the files underneath the build directory %_builddir (usually ~/rpmbuild/BUILD/) and writes to a directory underneath the build root directory %_buildrootdir (usually ~/rpmbuild/BUILDROOT).  The files that are written are the files that are supposed to be installed when the binary package is installed by an end-user.  Beware of the weird terminology: The ''build root directory'' is '''not''' the same as the ''build directory''.  This is often implemented by running "make install".
|<code>%check</code> (檢查) ||<code>%_builddir</code>||<code>%_builddir</code>||檢查軟體是否可以順利運作。這通常是執行 "<code>make test</code>" 之類的指令。許多軟體包不處理這個步驟。
|-
|-
|bin||%_buildrootdir||%_rpmdir||This reads the files underneath the build root directory %_buildrootdir (usually ~/rpmbuild/BUILDROOT/) to create binary RPM packages underneath the RPM directory %_rpmdir (usually ~/rpmbuild/RPMS/).  Inside the RPM directory is a directory for each architecture, and a "noarch" directory for packages that apply to any architecture.  These RPM files are the packages for users to install.
|<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||This creates a source RPM package (.src.rpm) inside the source RPM directory %_srcrpmdir (usually ~/rpmbuild/SRPMS).  These files are needed for reviewing and updating packages.
|<code>src</code> (源碼包) ||<code>%_sourcedir</code>||<code>%_srcrpmdir</code>||它會在源碼 RPM 資料夾 <code>%_srcrpmdir</code> 下製作源碼 RPM 軟體包 (<code>.src.rpm</code>)。這些檔案用於軟體包的校閱與上傳。
|}
|}


<!-- Note: The words "in" and "underneath" in the table above have different meanings.  Given file /a/b/c, c is "underneath" but not "in" a. -->
註:上述表格中的「下」與「內部」意思不同。例如有個檔案位於 /a/b/c,則 c 位於 a 的「內部」而非 a 之「下」。


As you can tell, certain directories have certain purposes in rpmbuild.  These are:
如你所見,在 rpmbuild 中,特定的資料夾有特定的用途。這些是:
{|
{|
! Macro Name !! Name !! Usually !! Purpose
! 巨集名稱 !! 名稱 !! 通常 !! 用途
|-
|-
|%_specdir||Specification directory||~/rpmbuild/SPECS||RPM specifications (.spec) files
|%_specdir||規格 (Specification) 資料夾||~/rpmbuild/SPECS||RPM 規格 (.spec)
|-
|-
|%_sourcedir||Source directory||~/rpmbuild/SOURCES||Pristine source package (e.g., tarballs) and patches
|%_sourcedir||來源 (Source) 資料夾||~/rpmbuild/SOURCES||元初來源封存檔 (如:tarball) 與補丁 (patch)
|-
|-
|%_builddir||Build directory||~/rpmbuild/BUILD||Source files are unpacked and compiled in a subdirectory underneath this.
|%_builddir||建置 (Build) 資料夾||~/rpmbuild/BUILD||解開源碼檔並在此資料夾內部的子資料夾下編譯。
|-
|-
|%_buildrootdir||Build root directory||~/rpmbuild/BUILDROOT||Files are installed under here during the %install stage.
|%_buildrootdir||建置根基 (Build root) 資料夾||~/rpmbuild/BUILDROOT||%install 階段中,檔案安裝於此處。
|-
|-
|%_rpmdir||Binary RPM directory||~/rpmbuild/RPMS||Binary RPMs are created stored under here.
|%_rpmdir||二進位 (Binary) RPM 資料夾||~/rpmbuild/RPMS||二進位 RPM 檔於此製作、儲存。
|-
|-
|%_srcrpmdir||Source RPM directory||~/rpmbuild/SRPMS||Source RPMs are created and stored here.
|%_srcrpmdir||源碼 (Source) RPM 資料夾||~/rpmbuild/SRPMS||源碼 RPM 檔於此製作、儲存。
|}
|}


Should a stage fail, you'll need to look at the output to see ''why'' it failed, and change the .spec file (or other input) as needed.
如果在某個階段失敗了,你需要查看詳細輸出內容以瞭解 ''為何'' 失敗,並根據所需修改 .spec (或其他輸入來源)
 
== 準備好打包某個程式 ==


== Getting ready to package a particular program ==
如果需要有其他的特別程式才能建置或執行你想要打包的程式,先安裝那些程式然後記下來是哪些 (你會用到這些資訊)。


If there are special programs that are required to build or run the program you are packaging, install those
若要為 Fedora 軟體庫打包程式,你 ''必須'' 將元初 (原始) 來源連同修補檔與建置指示都一起包進去;採用預先編譯過的代碼「''並不''」妥當。請將原始來源 (通常是 <code>.tar.gz</code> 檔) 放在 <code>~/rpmbuild/SOURCES</code> 目錄 (建置 RPM 的使用者帳號下) 中,然後用它來安裝檔案。
other programs and write down what they were (you'll need that information).


To package a program for the Fedora repository, you ''must'' package pristine (original) sources, along
請先閱讀這個程式的手動安裝指示;你接下來會需要編輯「.spec」檔來將流程自動化,所以你必須先瞭解應該要怎麼做。
with the patches and build instructions;
在你試圖用 RPM 建置程式之前,最好你先親手「實際跑過 (dry run)」建置一次 (如果你對 RPM 還不是很熟的話,這真的很重要)
it's ''not'' okay to start with pre-compiled code.
除了一些例外,Fedora 軟體中包含的所有二進位檔與函式庫,都必須從源碼軟體包中所含的源碼建置。
Install the file with the original source (usually a .tar.gz file) in the
"~/rpmbuild/SOURCES" directory (of the rpm building user account).


Read through the manual installation instructions for your program;
=== 拆分程式 ===
you're going to be automating this by editing a ".spec" file, so you have
to understand what you're supposed to do first.
It's probably best if you try a "dry run", going through its build and installation
procedure without trying to do it via RPM first
(that's especially true if you're not familiar with RPM).
With a few exceptions, all program binaries and program libraries included in Fedora packages must be built from the source code that is included in the source package.


=== Split up the program ===
應用程式源碼經常與其他外部函式庫一起發行,也就是說整個「綁在一塊」。
然而,[[Packaging:No_Bundled_Libraries|請不要將外部函式庫和主程式綁在一塊,統統包成一個軟體包]]。
相反的,請將他們拆分開來成為獨立的軟體包 。


Application source code is often released with the source code of other external libraries
=== 判斷授權 ===
"bundled" into them.
[[Packaging:No_Bundled_Libraries|Do not bundle external libraries and the application that uses them into a single package]].  Instead, split them up into separate packages.


=== Licensing ===
請只打包法律上允許你打包的軟體。


Only package software that's legal for you to package.
請參見 [[Packaging:Guidelines#Legal]]、[[Licensing:Main]]、和 [[Packaging:LicensingGuidelines]]。
通常來說,只有以核可的開源軟體 OSS 授權 (例如 GPL、LGPL、BSD-new、MIT/X、或 Apache 2.0 等授權) 發行的軟體可以打包。
請確認軟體真的以這種方式授權 (例如:查看源碼的標頭、README 檔等等)。
如果軟體有綁函式庫,請確認這些函式庫也是採用 OSS 授權。


As noted in the [[Packaging/Guidelines#Legal|packaging guidelines' legal section]],
=== 重複使用既有的軟體包資訊 ===
if you intend for it to be in the Fedora repository, be sure to follow the
[[Licensing:Main]] and [[Packaging:LicensingGuidelines]] guidelines.
In general, you need to only package software that is released as open source software (OSS)
using an approved OSS license (such as the GNU GPL, GNU LGPL, BSD-new, MIT/X, or Apache 2.0 licenses).
Check to make sure that the software really is licensed this way
(e.g., spot-check source code headers, README files, and so on).
If there are bundled libraries, make sure they are also OSS.


=== Reuse existing package information ===
盡可能重複使用。例如,請確認你想打包的不是早就有人打包過的東西。你可以從 Fedora Package Collection [https://admin.fedoraproject.org/pkgdb/ Fedora Package Database] 中找到既有軟體包的清單。


Try to reuse what you can.
也請查看 [[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:
Obviously, make sure you aren't packaging something that is already packaged;
# yum -y install yum-utils
you can find a list of existing packages in Fedora Package Collection in the [https://admin.fedoraproject.org/pkgdb/packages/ Fedora Package Database].
Also check the [[PackageMaintainers/InProgressReviewRequests | In Progress Review Requests]] (for packages that are currently being reviewed)
and the [[PackageMaintainers/RetiredPackages | Retired Packages]] list.
Failing that, see if someone has already started to package it for Fedora.
Google for "PROGRAMNAME Fedora rpm" or similar... maybe you can pick up where
they started.
You can use
http://cvs.fedoraproject.org/viewcvs/rpms/
directly to view .spec files (and patches) of any similar packages already in Fedora.
You can download the source RPMs using a program from the yum-utils package, by:
  $ yumdownloader --source sourcepackage-name
  $ yumdownloader --source sourcepackage-name


Alternately, an existing source rpm can be retrieved manually by browsing to the [http://mirrors.fedoraproject.org/publiclist Fedora mirror]'s http or ftp page,
另外,也可手動從 [http://mirrors.fedoraproject.org/publiclist Fedora mirror] http/ftp 網頁下的 <code>releases/{{FedoraVersion}}/Everything/source/SRPMS</code> 目錄取得源碼軟體包。請將「<code>{{FedoraVersion}}</code>」替換成你想要使用的 Fedora 發行版本,接著下載該軟體的 <code>.src.rpm</code> 軟體包。
select releases/11/Everything/source/SRPMS
(replace "11" with the Fedora release you want),
and downloading the source RPMs you want (they end in .src.rpm).


Once you have the source RPM, running the following command installs the src.rpm
一旦你下載好 SRPM,請將它安裝到 <code>~/rpmbuild</code>:
  $ rpm -ivh sourcepackage-name*.src.rpm
  $ rpm -ivh sourcepackage-name*.src.rpm
which places the package's .spec file into ~/rpmbuild/SPECS and other source and patch files in ~/rpmbuild/SOURCES).


You can also unpack the .src.rpm in a directory using rpm2cpio:
你也可以用 <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


''Sometimes'' it's easiest to start with an existing package, and then clean it up for Fedora.
有時候利用既有的軟體包作為開始是最簡單的方式,只要稍微清理一下就能讓 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] may help you find rpm's for non-Fedora systems.
(You can install source RPMs for other systems the same way as for Fedora).
Failing that, you might look at the source package files (not the .deb binary package files)
for [http://packages.ubuntu.com/ Ubuntu] or
[http://www.debian.org/distrib/packages Debian]
(source package files are standard tarballs with a "debian/" subdirectory, possibly
associated with patch files).
If the [http://www.freebsd.org/ports/installing.html FreeBSD ports collection] has it,
you could
[ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz download the FreeBSD ports tarball]
and see if their packaging information helps as a starting point.
'''However''', this is sometimes not helpful at all.
Different distributions have different rules, and what they do may be quite
inappropriate for Fedora.


== Creating a spec file ==
== 製作 SPEC 檔 ==


You now need to create a ".spec" file in the "~/rpmbuild/SPECS" directory.
現在你需要在 <code>~/rpmbuild/SPECS</code> 目錄中製作一份 SPEC 檔。你應該根據程式名稱來命名 (例:「<code>program.spec</code>」) 這份檔案。你可以使用封存檔的名稱,或如果軟體作者有倡議該用怎樣的名稱就用該名稱,但無論如何都應遵守 [[Packaging/NamingGuidelines|軟體包命名規約]] 中的規範。
You should name it after the program name, e.g., "program.spec".  Use the archive name or the name advocated by the software author where you can, but be sure to follow the
[[Packaging/NamingGuidelines| Package Naming Guidelines]].


=== Creating a blank spec file ===
=== SPEC 樣板與範例 ===


When you're creating a spec file for the first time, you can create its initial version using emacs or vim (as of 7.1.270-1),
==== 樣板 ====
they will automatically create a template for you.  E.G.:
首次製作 SPEC 檔時,可以利用 vim 或 emacs 來自動建立樣板:
   $ cd ~/rpmbuild/SPECS
   $ cd ~/rpmbuild/SPECS
   $ vi program.spec
   $ vim program.spec
 
以下是樣板看起來的模樣 ('''注意:'''供應的樣板不一定有遵守 Fedora 打包規約):


Here's an example of what that template will look like:
  Name:
  Name:
  Version:
  Version:
Line 191: Line 158:
  URL:
  URL:
  Source0:
  Source0:
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
   
   
  BuildRequires:
  BuildRequires:
Line 199: Line 165:
   
   
  %prep
  %prep
  %setup -q
  %autosetup
   
   
  %build
  %build
Line 206: Line 172:
   
   
  %install
  %install
  rm -rf %{buildroot}
  %make_install
make install DESTDIR=%{buildroot}
%clean
rm -rf %{buildroot}
   
   
  %files
  %files
%defattr(-,root,root,-)
  %doc
  %doc
   
   
  %changelog
  %changelog


你可以用 <code>$RPM_BUILD_ROOT</code> 取代 <code>%{buildroot}</code>。這兩者都能用,只不過記得前後一致就好。


You may have $RPM_BUILD_ROOT instead of %{buildroot}; just be consistent.
你也可以用 <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 檔:
 
You may also use the <code>rpmdev-newspec</code> command to create a spec file for you.  <code>rpmdev-newspec NAME-OF-NEW-PACKAGE</code> can create an initial spec file for a new package, tailored to various types of packages.  It will guess what kind of template to use based on the package name, or you can specify a particular template; see <code>/etc/rpmdevtools/spectemplate-*.spec</code> for available templates.  See <code>rpmdev-newspec --help</code> for more information. For example, to create a new spec file for a python module:


  cd ~/rpmbuild/SPECS
  cd ~/rpmbuild/SPECS
Line 227: Line 187:
  vi python-antigravity.spec
  vi python-antigravity.spec


=== An example: eject ===
==== 範本 ====
===== 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


Here's a simple example, a Fedora 9 package for the "eject" program:
install -m 755 -d %{buildroot}/%{_sbindir}
ln -s ../bin/eject %{buildroot}/%{_sbindir}


Summary: A program that ejects removable media using software control
%find_lang %{name}
Name: eject
 
Version: 2.1.5
%files -f %{name}.lang
Release: 11%{dist}
%doc README TODO COPYING ChangeLog
License: GPL
%{_bindir}/*
Group: System Environment/Base
%{_sbindir}/*
Source: http://metalab.unc.edu/pub/Linux/utils/disk-management/%{name}-%{version}.tar.gz
%{_mandir}/man1/*
Source1: eject.pam
 
Patch1: eject-2.1.1-verbose.patch
%changelog
Patch2: eject-timeout.patch
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1.5-21
Patch3: eject-2.1.5-opendevice.patch
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
Patch4: eject-2.1.5-spaces.patch
 
Patch5: eject-2.1.5-lock.patch
* Fri Jul 02 2010 Kamil Dudka <kdudka@redhat.com> 2.1.5-20
Patch6: eject-2.1.5-umount.patch
- handle multi-partition devices with spaces in mount points properly (#608502)
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
</pre>
URL: http://www.pobox.com/~tranter
ExcludeArch: s390 s390x
BuildRequires: gettext
BuildRequires: automake
BuildRequires: autoconf
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
%setup -q -n %{name}
%patch1 -p1 -b .versbose
%patch2 -p1 -b .timeout
%patch3 -p0 -b .opendevice
%patch4 -p0 -b .spaces
%patch5 -p0 -b .lock
%patch6 -p1 -b .umount
%build
%configure
make
%install
rm -rf %{buildroot}
make DESTDIR=%{buildroot} install
# pam stuff
install -m 755 -d %{buildroot}/%{_sysconfdir}/pam.d
install -m 644 %{SOURCE1} %{buildroot}/%{_sysconfdir}/pam.d/%{name}
install -m 755 -d %{buildroot}/%{_sysconfdir}/security/console.apps/
echo "FALLBACK=true" > %{buildroot}/%{_sysconfdir}/security/console.apps/%{name}
install -m 755 -d %{buildroot}/%{_sbindir}
pushd %{buildroot}/%{_bindir}
mv eject ../sbin
ln -s consolehelper eject
popd
%find_lang %{name}
%clean
rm -rf %{buildroot}
%files -f %{name}.lang
%defattr(-,root,root)
%doc README TODO COPYING ChangeLog
%attr(644,root,root) %{_sysconfdir}/security/console.apps/*
%attr(644,root,root) %{_sysconfdir}/pam.d/*
%{_bindir}/*
%{_sbindir}/*
%{_mandir}/man1/*
%changelog
* Wed Apr 02 2008 Zdenek Prikryl &lt;zprikryl at, redhat.com&gt; 2.1.5-11
- Added check if device is hotpluggable
- Resolves #438610


You can also use the "BuildRoot:" entry from the template instead, although both are acceptable, the one from the template is the preferred one.
== SPEC 檔概覽 ==


=== Spec file pieces explained ===
其他有用的指引:
* [http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html RPM Guide] 描寫如何寫作 SPEC 檔。
The [http://docs.fedoraproject.org/drafts/rpm-guide-en/ch-creating-rpms.html RPM Guide, section on creating RPMs],
* 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]
describes the details of how to fill in a spec file.
* [http://rpm.org/max-rpm-snapshot/ Maximum RPM] 包含最詳盡的資訊,但內容有點陳舊過時。
The developerWorks series "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.html Part 3] is also handy.
[http://rpm.org/max-rpm-snapshot/ Maximum RPM] has the most complete information, but is dated.


You will need to follow the Fedora guidelines, such as the
你需要遵守 Fedora 規約: [[Packaging/NamingGuidelines|Package Naming Guidelines]], [[Packaging/Guidelines|Packaging guidelines]],以及 [[Packaging/ReviewGuidelines|Package review guidelines]]
[[Packaging/NamingGuidelines| Package Naming Guidelines]],
[[Packaging/Guidelines| Packaging Guidelines]], and
[[Packaging/ReviewGuidelines|Package review guidelines]].


You can insert comments with a leading "#" character, but
你可以用「<code>#</code>」字號作為註解的前導字元,但請避免用到可展開成許多列 (以 <code>%</code> 作開頭) 的巨集 (因為它們會先被替換展開)。如果要註解掉一列,百分比符號請改成兩個 (<code>%%</code>)。此外,也請避免使用列內註解 (#),例如在同一列中使用指令稿指令提示符。
don't insert potentially-multiline-macros (words beginning with "%") in a comment
(macros are expanded first); if you're commenting out a line, double the percent signs ("%%").  Also, don't use inline comments ("#") on the same line after
a script command.


Here are the major fields/areas that you will need to fill in:
下方列的是主要標籤。請注意巨集 <code>%{name}</code>、<code>%{version}</code>、和 <code>%{release}</code> 可用來各自指稱 Name 名稱、Version 版本與 Release 發行版次標籤。只要更改標籤,巨集就會自動更新使用新值。
* Name: The (base) name of the package.  It must follow the [[Packaging/NamingGuidelines| Package Naming Guidelines]].  In many cases, this will be in all lower case.  Elsewhere in the spec file, you can refer to the name using the macro %{name} - that way, if the name changes, the new name will be used by those other locations. This name should match the spec file name.
* '''Name''':軟體包的 (基礎) 名稱,應該與 SPEC 檔名相符。它必須遵守 [[Packaging/NamingGuidelines|Package Naming Guidelines]],一般只用小寫。
* Version: The upstream version number. See [http://fedoraproject.org/wiki/Packaging/NamingGuidelines#Package_Version Packaging/Naming guidelines - package version] for more information. If the version is non-numeric (contains tags that are not numbers or digits), you may need to include the additional non-numeric characters in the release field. If upstream uses full dates to distinguish versions, consider using version numbers of the form yy.mm[dd] (so a 2008-05-01 release becomes 8.05). Elsewhere in the spec file, refer to this value as %{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: The initial value of the release should normally be "1%{?dist}". Then, increment the number every time you release a new package for the same version of software.  If a new version of the software being packaged is released, the version number should be changed to reflect the new software version, and the release number should be reset to 1.  See [http://fedoraproject.org/wiki/Packaging/NamingGuidelines#Package_Release Name Guidelines - package release] for more. [[Packaging/DistTag]] describes the "dist" tag, which isn't required but can be useful. Use %{release} to reuse this value.
* '''Release''':發行版次。初始值一般都應該是 <code>1%{?dist}</code>。每次新發行同版本軟體的軟體包就遞增一個數字。若上游發行新的版本,就對應修改 Version 標籤,然後把 Release 發行版次重設回 <code>1</code>。請見打包規約的 [[Packaging/NamingGuidelines#Release_Tag|Release tag section]]。選標的 [[Packaging/DistTag|Dist tag]] 可能會用得到。
* Summary: A brief, one-line summary of the package. Use American English, and ''do not'' end in a period.
* '''Summary''':簡要的、只用一列的軟體包摘要。記得使用美式英文。 還有,'''「絕對不可以」加上半形句號 (.) 作為結尾。'''
* Group: This needs to be a pre-existing group, like "Applications/Engineering"; run "less /usr/share/doc/rpm-*/GROUPS" to see the complete list. If you create a sub-package "...-doc" with documentation, use the group "Documentation".
* '''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: Its license; for software, this must be an open source software license.  Use a standard abbreviation, e.g., "GPLv2+".  Try to be specific, e.g., use "GPLv2+" (GPL version 2 or greater) instead of just "GPL" or "GPLv2" where it's true.  See [[Licensing]] and the [[Packaging/LicensingGuidelines| Licensing Guidelines]] for more information.  You can list multiple licenses by combining them with "and" and "or", e.g., "GPLv2 and BSD".  Call this tag "License"; don't use the older, inaccurately named tag "Copyright".
* '''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: The URL for more information about the program, e.g., the project website.  Note: This is NOT where the original source code came from, see "Source" (next!).
* '''URL''': 有關該程式更多資訊的完整 URL (例如該程式的專案網站)。 '''''注意:這不是原本源碼的來源 URL,源碼封存檔的來源 URL 應該用下列的 Source0'''''。
* Source0: The URL for the compressed archive containing (original) pristine source code, as upstream released it. "Source" is synonymous with "Source0".  If you give a full URL (and you should), its basename will be used when looking in the SOURCES directory. If possible, embed %{name} and %{version}, so that changes to either will go to the right place.  '''Warning:''' ''Source0:'' and ''URL:'' are different - normally they are both URLs, but the "URL:" entry points to the project website, while the "Source0:" entry points to the actual file containing the source code (and is typically a .tar.gz file).  As noted in the guidelines, "When downloading sources, patches etc, consider using a client that preserves the upstream timestamps. For example wget -N or curl -R. To make the change global for wget, add this to your ~/.wgetrc: timestamping = on, and for curl, add to your ~/.curlrc: -R."  If there is more than one source, name them Source1, Source2, and so on. If you're adding whole new files in addition to the pristine sources, you can list each of them as sources as well, but list them ''after'' the pristine sources. A copy of each of these sources will be included in any source package you create (unless you specially direct otherwise).  See [[Packaging/SourceURL]] for more information on special cases (using revision control, when upstream uses prohibited code, etc.).
* '''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: The name of the first patch that you will apply to the source code.  If you need to patch the files after they've been uncompressed, you should edit the files, save their differences as a "patch" file in your ~/rpmbuild/SOURCES directory.  Patches should make only one logical change, so it's quite possible to have multiple patch files.
* '''Patch0''':第一個要套用到源碼上的修補檔 (patch) 名稱。如果你需要在檔案解壓縮之後對一些檔案作修補,你應該要先編輯檔案並將兩者間的差異儲存成「patch」檔,然後放在 <code>~/rpmbuild/SOURCES</code> 目錄下。一個 Patch 應該只做一種目的更動 (logical change),所以正常來講可能會有多個 patch 檔。
* BuildRoot: This is where files will be "installed" during the "%install" process (which happens after the %build compilation process).  Normally you should just leave this line alone; under the usual Fedora setup, this will be a macro that will create a new special directory under /var/tmp. Newer versions of RPM will ignore this value, and instead place the build root in "%{_topdir}/BUILDROOT/".
* '''BuildArch''':如果你要打包的檔案並不依賴任何架構 (例如:shell 指令稿、資料檔等),那麼請用「<code>BuildArch: noarch</code>」。二進位檔 RPM 的架構就會跟著變成「<code>noarch</code>」。
* BuildRequires: A comma-separated list of packages required for building (compiling) the program.  These are ''not'' automatically determined, so you need to include ''everything'' needed to build the program.  There are a few packages that are so common in builds that you don't need to mention them, such as "gcc"; see the [[Packaging/Guidelines| Packaging Guidelines]] for the complete list of the packages you may omit.  You can also specify minimum versions, if necessary, like this: "ocaml >= 3.08". You can have more than one line of BuildRequires (in which case they are all required for building).  If you need file /EGGS, you can get its package by running "rpm -qf /EGGS"; if EGGS is a program, you determine its package quickly by running "rpm -qf `which EGGS`".  Try to specify only the minimal set of packages necessary to properly build the package, since each one will slow down a "mock"-based build (e.g., try to use sed instead of perl if you don't really need perl's abilities).  Watch out: Some applications permanently disable functions if their package isn't detected during the build; in those cases you may need to include those additional packages.  If you have trouble figuring out this list, the "auto-br-rpmbuild" command (from the auto-buildrequires package) may be helpful.
* '''BuildRoot''':這是 %install 程序 (%build 程序之後) 期間檔案要「安裝」到的地方。這一項目前在 Fedora 中是多餘的,只有 EPEL5 還需要它。預設情況下,建置根基目錄放在「<code>%{_topdir}/BUILDROOT/</code>」。
* Requires: A comma-separate list of packages that are required when the program is installed.  Note that the list of packages for ''Requires'' (what's required when installing/running) and ''BuildRequires'' (what's required to build the binary RPM) are independent; a package may be in one list but not the other, or it could be in both.  The dependencies of binary packages are in many cases automatically detected by rpmbuild, so it is often the case that you don't need to specify the ''Requires'' tag at all. But if you want to highlight some specific packages as being required, or require a package that rpm can't detect should be required, then add it here.
* '''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}} 軟體包可能會有所用處。
* %description - A longer, multi-line description of the program.  Use American English. All lines must be 80 characters or less. "Blank lines are assumed to separate paragraphs. Some graphical user interface installation programs will reformat paragraphs...  (lines that) start with whitespace, such as a space or tab, will be treated as preformatted text and displayed as is, normally with a fixed-width font." (per the [http://docs.fedoraproject.org/drafts/rpm-guide-en/ch09s03.html RPM Guide]).
* '''Requires'':當程式安裝之時所需要的軟體包清單,請以半形逗號隔開各個項目。請注意 BuildRequires 標籤應列出的是建置二進位檔 RPM 的項目清單,而 Requires 標籤列出的是安裝/執行該程式所需的項目清單;一個軟體包可以放在其中一個清單,或同時兩個清單中。在許多情況下,<code>rpmbuild</code> 會自動偵測依賴項目,所以不見得需要 Requires 標籤。然而,你可能會希望特別標明那些軟體包是需要的,或是哪些軟體包沒自動偵測到而你需要手動標明。
* %prep - Script commands to "prepare" the program, that is, to uncompress it so that it will be ready for building (compiling).  Typically this is just "%setup -q" or some variation of it; a common variation is "%setup -q -n NAME" if the source file unpacks into NAME. See the "%prep" section below for more.
* '''%description''':長篇的、跨多列的程式描述。請使用美式英文。每一列都必須小於等於 80 個字元。空白列表示新段落的開始。有些圖形使用者介面安裝程式會重新格式化段落;以空白起頭的列會被視為已預先格式化過的格式,會如其所述表現,顯示時一般採用等寬字型。請見 [http://docs.fedoraproject.org/drafts/rpm-guide-en/ch09s03.html RPM Guide].
* %build - Script commands to "build" the program, that is, to compile it and get it ready for installing.  The program should come with instructions on how to do this.  See the "%build" section below for more.
* '''%prep''':「準備」程式的指令稿指令 (例如:將之解壓縮),這樣才能建置程式。一般這只是「<code>%autosetup</code>」。如果源碼檔案要解開放到 <code>NAME</code> 的話,常見的變化形式是「<code>%autosetup -n NAME</code>」。請見下方的 %prep 小節瞭解更多資訊。
* %check - Script commands to self-test the program. This is run after %build and before %install, so you should place it there if you have this section.  Often it simply contains "make test" or "make check".  This is separated from %build so that people can skip the self-test if they desire.  This isn't documented in many places.
* '''%build''':「建置」程式的指令稿指令 (例如:編譯它),準備完成以便後續安裝。程式應該有附上如何執行此步驟的指示。請見下方 %build 小節來瞭解更多資訊。
* %install - Script commands to "install" the program.  The commands should copy the files from the "build directory" %{_builddir} (which would be under ~/rpmbuild/BUILD) into the buildroot directory, %{buildroot} (which would normally be under /var/tmp). See the "%install" section below for more.
* '''%install''':「安裝」程式的指令稿指令。指令應該要將檔案從 <code>BUILD</code> 目錄 <code>%{_builddir}</code> 複製到建置根基目錄 <code>%{buildroot}</code> 中。請見下方的 %install 小節瞭解更多細節。
* %clean - instructions to clean out the build root. Typically:
* '''%check''':「測試」程式的指令稿指令。這是在 %install 程序後執行,所以如果你需要此區段的話,請將它放在該處。通常它僅包含「<code>make test</code>」或「<code>make check</code>」。這要和 %build 分開,這樣人們才能在需要的時候略過自我測試。
* '''%clean''': 清理建置根基目錄的指令。請注意這個區段目前在 Fedora 中是多餘的,並且只有 EPEL 需要。一般這只包含:
  rm -rf %{buildroot}
  rm -rf %{buildroot}
* %files - the list of files that will be installed.  See the "%files" section below for more.
* '''%files''':會安裝的檔案清單。請見下方 %files 小節以瞭解更多細節。
* %changelog - Changes in the package.  Use the format example above.
* '''%changelog''':軟體包的變動。請使用上述格式。'''請「不要」把軟體的變更記錄放在這裡。這裡是 RPM 自身的變更記錄。'''
* ExcludeArch: If the package does not successfully compile, build or work on an architecture, then those architectures should be listed in the spec in an ExcludeArch tag.
* '''ExcludeArch''':如果軟體包無法在某特定架構上成功編譯、建置或運作,請在此標籤下列出這些架構。* 你可以加入些代碼區段,這樣代碼會在軟體包於真實系統上安裝或移除時執行 (與之相反的是只執行 %install 指令稿,它只會作虛擬安裝 (pseudo-install),安裝到建置根基目錄中)。這些代碼稱之為「scriptlet」指令稿片段,他們通常以軟體包中的資訊更新執行中的系統。請見下方的「scriptlet」瞭解更多細節。
* You can add sections so that code will run when packages are installed or removed on the real system (as opposed to just running the %install script, which only does a pseudo-install to the build root).  These are called "scriptlets", and they are usually used to update the running system with information from the package.  See the "Scriptlets" section below for more.


Don't use the tags "Packager" or "Vendor".  Don't use "Copyright" - use "License" instead.
RPM 也支援從單一 SPEC 檔製作出多個軟體包 (稱為 [[How_to_create_an_RPM_package#Subpackages|子軟體包]]) 的功能,例如 <code>name-libs</code> 和 <code>name-devel</code> 等軟體包。
Don't create a "relocatable" package - they don't add value in Fedora yet they make things more complicated.


RPM supports subpackages, that is, a single spec file can generate many
{{admon/caution|請'''「不要」'''使用這些標籤|
binary packages.  For example, if the documentation is very large, you might generate
* Packager
a separate "-doc" subpackage.
* Vendor
See below for more.
* Copyright}}


=== %prep section ===
請'''不要'''製作「relocatable」可重新變換位置的軟體包;他們不會幫 Fedora 加值,反而把事情搞得更複雜。
The "%prep" section describes how to unpack the compressed packages so that they can be built.
Typically, this is a set of "%setup" and/or %patch commands, which reference the Source0:, Source1:, etc. lines above.
See the [http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html Maximum RPM section on %setup and %patch] for more details.


'''Warning:''' In spec files, don't use in-line comments (a "#" comment on the same line after a command), and don't put macros (words beginning with "%") in a comment unless you quote the "%" as "%%".  Macros can cause failures if they are in a comment, because they are always expanded (even when in a comment) and they can expand to multiple lines.  This is true for %prep, %build, and so on.
== SPEC 檔區段詳解 ==


The new RPM 4.4.2.x series adds two new macros, %{patches} and %{sources}, so you can do things like:
The %prep section describes how to unpack the compressed packages so that they can be built. Typically, this includes the "<code>%autosetup</code>" command.  Alternatively, you can use "<code>%setup</code>" and "<code>%patch</code>" commands with reference to the Source0 (and Source1 etc.) lines. See the [http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html Maximum RPM section on %setup and %patch] for more details.
 
The %{patches} and %{sources} macros are available since RPM 4.4.2 and are useful if you have a large list of patches or sources and %autosetup is not what you want, then you can do:
  for p in %{patches}; do
  for p in %{patches}; do
...
    ...
  done
  done
These new macros can very useful if you have a large list of patches or sources.
However, keep in mind that using these will make your spec
incompatible with the rpm used in Fedora 9 and earlier, RHEL, and
many other RPM-based distros.


==== %prep section: %setup command ====
However, keep in mind that using these will make your SPEC incompatible with RPMS used in RHEL and other RPM-based dirstributions.
 
==== %prep 區段:%autosetup 指令 ====
 
The "<code>%autosetup</code>" command unpacks a source package. Switches include:
* '''<code>-n</code> ''name''''' : If the Source tarball unpacks into a directory whose name is not the RPM name, this switch can be used to specify the correct directory name. For example, if the tarball unpacks into the directory FOO, use "<code>%autosetup -n FOO</code>".
* '''<code>-c</code> ''name''''' : If the Source tarball unpacks into multiple directories instead of a single directory, this switch can be used to create a directory named ''name'' and then unpack into it.


The "%setup" command unpacks a source package, and takes several switches.  Normally you should use "-q" (quiet) to prevent setup from babbling about every file it unpacks.  Here are a few switches besides -q:
If you use "<code>%setup</code>" command instead, then ''<code>-q</code>''' is commonly used to suppress unecessary output.  
* -n ''name'': If the name of the rpm is something other than what the Source unpacks to, use this switch to state the ''name'' it unpacks to.  E.G., if the tarball unpacks into a directory MYNAME, use %setup -q -n MYNAME
* -c ''name'': If the tarball doesn't unpack into a single directory, this creates a directory named ''name'' and then unpacks into it.  Useful if you have one of those annoying tarballs that doesn't have a single common subdirectory embedded in it.


There are
There are [http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html more %spec options if you are unpacking multiple files], which is primarily useful if you
[http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html more %spec options if you are unpacking multiple files], which is primarily useful if you
are creating subpackages (see below).  The key ones are:
are creating subpackages (see below).  The key ones are:


{|
{|
|-
|-
| -a number || Only unpack the source directive of the given number, such as –a 0 for source0:, after changing to the directory.
| <code>-a number</code> || Only unpack the Source directive of the given number after changing directory (e.g. "<code>–a 0</code>" for Source0).
|-
|-
| -b number ||  Only unpack the source directive of the given number, such as –b 0 for source0:, before changing to the directory.
| <code>-b number</code> ||  Only unpack the Source directive of the given number before changing directory (e.g. "<code>–b 0</code>" for Source0).
|-
|-
| -D || Do not delete the directory before unpacking.
| <code>-D</code> || Do not delete the directory before unpacking.
|-
|-
| -T || Disable the automatic unpacking of the archives.
| <code>-T</code> || Disable the automatic unpacking of the archives.
|}
|}


==== %prep section: %patch commands ====
==== %prep 區段:%patch 指令 ====


The "%patch0" command applies patch 0 (similar for 1, 2, etc.). Patches are the normal way to change to the source code if necessary to package it. The normal "-pNUMBER" option applies, which simply passes that argument on to ''patch''.
If you have used "<code>%autosetup</code>" command, the following manual patch management is not necessary.  If you have complex requirements or need compatibility with EPEL, you may still need this. The "<code>%patch0</code>" command applies Patch0 (and %patch1 applies Patch1 etc.). Patches are the normal method of making necessary changes to the source code for packaging. The usual "<code>-pNUMBER</code>" option applies, which passes that argument onto the program <code>patch</code>.


Patch file names often look like "telnet-0.17-env.patch", that is, ''%{name}''-''%{version}''-''patch_purpose''.patch (some people omit -''%{version}''). Patch files are typically the result of a "diff -u"; if you do this from the subdirectory of ~/rpmbuild/BUILD, you won't have to specify a -p level later.  You can use all the normal ways of creating a patch file.
Patch file names often look like "<code>telnet-0.17-env.patch</code>", which is the format <code>%{name} - %{version} - REASON.patch</code>" (though sometimes version is omitted). Patch files are typically the result of "<code>diff -u</code>"; if you do this from the subdirectory of <code>~/rpmbuild/BUILD</code> then you won't have to specify a <code>-p</code> level later.


If you're creating a patch file a single file FILENAME, a common way is to copy it to FILENAME.orig, modify it, and then save the results of "diff -u FILENAME.orig FILENAME".  If you change directory to "~/rpmbuild/BUILD/''NAME''", you could create a patch file to change a single file by doing:
This is a typical procedure for creating a patch for a single file:
  cp X/Y.Z X/Y.Z.orig
  cp foo/bar foo/bar.orig
  vim X/Y.Z
  vim foo/bar
  diff -u X/Y.Z.orig X/Y.Z > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
  diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch


If you're going to edit many files, one easy method is to copy the whole subdirectory underneath BUILD, and then do subdirectory diffs; once you change directory to "~rpmbuild/BUILD/''NAME''", you can:
If editing many files, one easy method is to copy the whole subdirectory underneath <code>BUILD</code> and then do subdirectory diffs.  After you have changed directory to "<code>~rpmbuild/BUILD/NAME</code>", do the following:
  cp -pr ./ ../PACKAGENAME.orig/
  cp -pr ./ ../PACKAGENAME.orig/
  ... many edits ...
  ... many edits ...
  diff -u ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/''NAME''.''REASON''.patch
  diff -ur ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/''NAME''.''REASON''.patch


If you edit many files in one patch, you can also copy the original files using some consistent ending such as ".orig" before editing them. Then, you can use "gendiff" (in the rpm package) to create a patch with the differences.  Do "man gendiff" for more information.
If you edit many files in one patch, you can also copy the original files using some consistent ending such as "<code>.orig</code>" before editing them. Then, you can use "<code>gendiff</code>" (in the <code>rpm-build</code> package) to create a patch with the differences.


Try to ensure that in your patch the "context" matches exactly.
Try to ensure that your patch match the context exactly. The default "fuzz" value is "<code>0</code>", requiring matches to be exact. You can work around this by adding "<code>%global _default_patch_fuzz 2</code>" to revert to the value found in older versions of RPM in Fedora, but it is generally recommended to avoid doing this.
In old versions of Fedora, the default "fuzz" value was 2, which meant that imprecise matches were acceptable.
However, the version of [http://lwn.net/Articles/289235/ RPM used by Fedora 10 and later] have a default fuzz to 0, requiring that matches be exact.
You can work around this by adding "%global _default_patch_fuzz 2", but it's better to not
have the problem by making the patch match the context exactly.


As explained in [[Packaging/PatchUpstreamStatus]], all patches in Fedora spec files SHOULD have a comment above them about their upstream status. This should document the upstream bug/email that includes it (including the date), or if it's Fedora-unique, why it it unique.
As explained in [[Packaging/PatchUpstreamStatus]], all patches should have a comment above them in the SPEC file about their upstream status. This should document the upstream bug/email that includes it (including the date). If it is unique to Fedora, you should mention why it is unique. The Fedora Project tries not to deviate from upstream; see [[PackageMaintainers/WhyUpstream]] for the importance of this.
The Fedora Project focuses, as much as possible, on not deviating from upstream in the software it includes in the repository - see [[PackageMaintainers/WhyUpstream|Staying close to upstream projects]] for more about why it's important to do this.


==== %prep section: Unmodified files ====
==== %prep 區段:未修改的檔案 ====


Sometimes, you'll package just a straight file that doesn't need to be uncompressed, e.g., a "Source1:" that is just a simple PDF file.  These might not be from external sources, e.g., perhaps you've had to create a few additional files that weren't in the original sources so that the package cleanly installs in Fedora.  You can "prep" those into the build directory by doing this (replace "1" with whatever number it is):
有時候,來源的一個或多個檔案並不需要解壓縮。你可以「prep」準備這些項目到建置目錄中,如 (這裡的 <code>SOURCE1</code> 代表對應的來源檔)
  cp -p %SOURCE1 .
cp -p %SOURCE1 .


=== %build section ===
=== %build 區段 ===


The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.
The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.


Many programs follow the GNU configure approach (or some variation). By default, they will install to a prefix of "/usr/local" (/usr/local/bin, /usr/local/lib, etc.), which is a reasonable default for unpackaged files. However, since you ''are'' packaging it, you will want to change the prefix to "/usr", since this is now a package maintained by the system itself. If there are any libraries, they'll need to be installed in the right directory, which is either /usr/lib or /usr/lib64 depending on the architecture (the actual value is in %{_libdir}).
Many programs follow the GNU <code>configure</code> approach (or some variation). By default, they will install to a prefix of "<code>/usr/local</code>", which is reasonable for unpackaged files. However, since you are packaging it, change the prefix to "<code>/usr</code>". Libraries should be installed to either <code>/usr/lib</code> or <code>/usr/lib64</code> depending on the architecture.


Since the GNU "configure" system is so common, rpm pre-defines a macro named "%configure", which invokes GNU configure with the right options (e.g., it changes --prefix to /usr). This means that some variation of this will often work as a build command:
Since GNU <code>configure</code> is so common, the macro "<code>%configure</code>" can be used to automatically invoke the correct options (e.g. change the prefix to <code>/usr</code>). Some variation of this often works:
   %configure
   %configure
   make %{?_smp_mflags}
   make %{?_smp_mflags}


Sometimes you'll want to override the variables of a makefile; you can easily do that by passing them as parameters to make, like this:
To override makefile variables, pass them as parameters to <code>make</code>:
  make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}
  make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}


If you need to do something complicated with GNU-generated configure, take a look at [http://sourceware.org/autobook/ "GNU autoconf, automake, and libtool"].  A good presentation on these as well as "make" is [http://www.suse.de/~sh/automake/automake.pdf "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer].
More more information, see [http://sourceware.org/autobook/ "GNU autoconf, automake, and libtool"] and [http://www.suse.de/~sh/automake/automake.pdf "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer].


Some programs use Cmake.  See [[Packaging/cmake]] for some suggestions.
Some programs use <code>cmake</code>.  See [[Packaging/cmake]].


If you include some self-tests (and that's a good idea), put them in a separate "%check" section that immediately follows the "%build" area, instead of including them in %build.  That way, it will be easy for the system to skip unnecessary self-tests.
=== %install 區段 ===


=== %check section ===
This section involves script commands to "install" the program, copying the relevant files from <code>%{_builddir}</code> to <code>%{buildroot}</code> (which usually means from <code>~/rpmbuild/BUILD</code> to <code>~/rpmbuild/BUILDROOT</code>) and creating directories inside <code>%{buildroot}</code> as necessary.


The "%check" section does testing, often it's "make test".
Some of the terminology can be misleading:
This is not documented in many other sources of RPM info.
* The "build directory", also known as <code>%{_builddir}</code> is not the same as the "build root", also known as <code>%{buildroot}</code>. Compilation occurs in the former directory, while files to be packaged are copied from the former to the latter.
* During the %build section, the current directory will start at <code>%{buildsubdir}</code>, which is the subdirectory within <code>%{_builddir}</code> that was created during %prep stage. This is usually something like <code>~/rpmbuild/BUILD/%{name}-%{version}</code>.
* The %install section is '''not''' run when the binary RPM package is installed by the end-user, but is only run when creating a package.


=== %install section ===
Normally, some variation of "<code>make install</code>" is performed here:
 
The "%install" section is a set of script commands to "install" the program. The commands in this section should copy the files from a directory inside the "build directory" %{_builddir} (normally ~/rpmbuild/BUILD/''something'') into the build root directory, %{buildroot} (normally /var/tmp/''something''), creating the directories inside %{buildroot} as necessary.
 
'''Watch out''': Some of the terminology is very misleading:
* The ''build directory'' (under which compilations occur during %build) and the ''build root'' (where files are copied into during the %install process) are '''different'''.  The point of the %install process is to copy files, such as those under the build directory, to the right place in the build root. Perhaps "buildroot" should be called "installroot", but it's too late now, the terminology is entrenched.
* The build directory is normally ~/rpmbuild/BUILD, while the build root (where files get installed to during %install) is normally ~/rpmbuild/BUILDROOT.  The %prep stage will normally create a subdirectory underneath the build directory as part of %setup, and populate the build directory with files (based on the source information in %_sourcedir, which is typically in ~/rpmbuild/SOURCES).  During %build, the current directory will actually start at %{buildsubdir}, that newly-created  subdirectory under the build directory.  Typically %{buildsubdir} is something like ~/rpmbuild/BUILD/%{name}-%{version}.
* The "%install" script is ''not'' used when the binary rpm package is installed by the end-user!! The term "%install" is misleading, in fact, the script must ''not'' install the programs in the REAL final locations (e.g., in /usr/bin), but under the buildroot %{buildroot}.
 
Normally, the install script would first erase the %{buildroot} directory, and then do some variation of "make install" (ideally using DESTDIR=%{buildroot}, if the program supports it). Here's an example of an %install section:
  %install
  %install
  rm -rf %{buildroot}
  rm -rf %{buildroot} # redundant except for RHEL 5
  make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install
  %make_install


Ideally, every program would have a "make install" command that supported the [http://www.gnu.org/prep/standards/html_node/DESTDIR.html ''DESTDIR'' convention].  If the program includes a "make install" that supports DESTDIR, where possible, ''use it''. The DESTDIR convention supports redirecting file installations to descend from a specific directory, which is exactly what we want during %install.
Ideally you should use %make_install which is equivalent to [http://www.gnu.org/prep/standards/html_node/DESTDIR.html <code>DESTDIR=%{buildroot}</code>] if the program supports it, as it redirects file installations to the specified directory and is exactly what we want to happen during the %install section.


Installing a program that does not support DESTDIR can be much harder, and no option is as good as native DESTDIR support.  Consider these alternatives:
If the program does not support <code>DESTDIR</code> (and only if), you can workaround it in one of several (inferior) ways:
* Patch the makefile so that it ''does'' support DESTDIR. Create directories inside DESTDIR where necessary (feel free to use "mkdir -p", the "-p" option of mkdir is now standard and widely supported).  Be sure to submit the patch upstream.
* Patch the makefile so that is supports <code>DESTDIR</code>. Create directories inside <code>DESTDIR</code> where necessary and submit the patch upstream.
* Use "%makeinstall". Many older RPM documents suggest using "%makeinstall", which ''might'' work if "make install" doesn't support DESTDIR.  However, as noted in the Fedora guidelines, the %makeinstall macro "must NOT be used when make install DESTDIR=%{buildroot} works. %makeinstall is (merely) a kludge that can work with Makefiles that don't make use of the DESTDIR variable...".  Unfortunately, this sometimes has subtle failures, which is why %makeinstall should not be used if DESTDIR works.  The reason is based on how %makeinstall works. The "%makeinstall" macro expands to something like "<tt>make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install</tt>".  Many programs will quietly recompile or change parts of the program when values like prefix are changed, resulting in an incorrect installation. See the Fedora guidelines if you want the details on why this approach can fail.  You will probably need to create appropriate directories inside %buildroot before calling %makeinstall (e.g., <tt>mkdir -p %{buildroot}%{_bindir}/</tt>).
* Use the "<code>%makeinstall</code>" macro. This method might work, but can lead to subtle failures. It expands to something like "<code>make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install</code>", which can result in some programs failing to work properly. Create directories inside <code>%{buildroot}</code> where necessary.
* Consider using the auto-destdir package. This requires "BuildRequires: auto-destdir", and changing "make install" to "make-redir DESTDIR=%{buildroot} install". This only works well if the installation uses only certain common commands to install files, like cp and install; see "man make-redir" for details.
* Consider using the <code>auto-destdir</code> package. This requires "<code>BuildRequires: auto-destdir</code>", and changing "<code>make install</code>" to "<code>make-redir DESTDIR=%{buildroot} install</code>". This only works well if the installation uses only certain common commands to install files, like <code>cp</code> and <code>install</code>.
* Do the installation "by hand", that is, instead of invoking a build system, copy the files to the correct locations. Basically, this would be a sequence that would create directories that weren't already created by the "BuildRequires" packages (typically using install -d or mkdir -p), followed by copying of files from the current directory (inside the build directory) into the buildroot directory (typically using "cp -p" and/or "install -p"). Running "make -n install" may make it easy to determine what this sequence should be.  Be sure to create directories inside %buildroot where necessary. One serious problem with this approach is that it's easy to fail to install new or renamed files during an update&mdash;so if there's a better approach, use it instead.  If you ''do'' perform the installation "by hand", be ''especially'' careful with updates when using this approach. For example:
* Perform the installation by hand. This would involve creating the necessary directories under <code>%{buildroot}</code> and copying files from <code>%{_builddir}</code> to <code>%{buildroot}</code>. Be especially careful with updates, which often contain new or changed filenames. An example of this procedure:
  %install
  %install
  rm -rf %{buildroot}
  rm -rf %{buildroot}
Line 482: Line 396:
  cp -p mycommand %{buildroot}%{_bindir}/
  cp -p mycommand %{buildroot}%{_bindir}/


As noted in the [[Packaging:Guidelines#Timestamps|packaging guidelines' timestamp section]],  "when adding file copying commands in the spec file, consider using a command that preserves the files' timestamps, eg. cp -p or install -p".  So, if the makefile lets you override the install command (typically named INSTALL), you might want something like INSTALL="install -p" CP="cp -p" as make parameters, like this:
=== %check 區段 ===
make INSTALL="install -p" CP="cp -p" DESTDIR=%{buildroot} install
 
如果可以自我測試的話,將它們納入其中的話會是個好主意。他們應該放在 %check 區段中 (緊接在 %install 區段之後,因為應該測試 %buildroot 中的檔案) 而不是放在 %build 區段中,這樣才能在必要時刻輕易略過。


=== %files section ===
通常,此區段包含:
The %files section identifies what files and directories were added by the package - and thus, which files and directories are ''owned'' by the package. Ownership is important - when you type "rpm -qif ''blah''",  you'll see who owns ''blah''.  This section is used when performing the ''bin'' stage, to determine which files are placed into each binary RPM file.
  make test


==== %files Basics ====
有時候也可以用:
make check


The %files section normally begins with a %defattr line which sets the default file permissions. The format of this is %defattr(<file permissions>, <user>, <group>, <directory permissions>), that is, one can specify the permissions to apply to files and directories in the %files section. The fourth parameter is often omitted. Usually one uses %defattr(-,root,root,-), where "-" means "use the default permissions".
請探索一下 Makefile 的用法,並選擇適當的方式。


This is followed by names or patterns of the directories or files to be installed and owned by this package. You should use macros for directory names, e.g., use %{_bindir}/myfile instead of /usr/bin/myfile, and %{_sbindir}/killaccount instead of /usr/sbin/killaccount. If a name or pattern begins with "/" when expanded, then it is presumed to have been copied into the %{buildroot} followed by that pattern; when installed on the final system, it will be copied into that name ''without'' the buildroot prefix.  If you don't precede the pattern with "/", then it is presumed to be in the current directory (e.g., inside the build directory) - this is used for "documentation" files. So if your package just installs /usr/bin/mycommand, then your %files section ''could'' simply say:
=== %files 區段 ===
此區段宣告哪些檔案與目錄是由該軟體包擁有,還有哪些檔案與目錄會放到二進位檔 RPM 中。
 
==== %files 基礎 ====
 
The <code>%defattr</code> sets the default file permissions, and is often found at the start of the <code>%files</code> section. Note that this is no longer necessary unless the permissions need to be altered. The format of this is:
%defattr(<file permissions>, <user>, <group>, <directory permissions>)
The fourth parameter is often omitted. Usually one uses <code>%defattr(-,root,root,-)</code>, where "<code>-</code>" uses the default permissions.
 
You should then list all the files and directories to be owned by the package. Use macros for directory names where possible, which can be viewed at [[Packaging:RPMMacros]] (e.g. use <code>%{_bindir}/mycommand</code> instead of <code>/usr/bin/mycommand</code>). If the pattern begins with a "<code>/</code>" (or when expanded from the macro) then it is taken from the <code>%{buildroot}</code> directory. Otherwise, the file is presumed to be in the current directory (e.g. inside <code>%{_builddir}</code>, such as documentation files that you wish to include). If your package only installs a single file <code>/usr/sbin/mycommand</code>, then the <code>%files</code> section can simply be:
  %files
  %files
%defattr(-,root,root,-)
  %{_sbindir}/mycommand
  %{_sbindir}/mycommand


Any file or directory identified in the %files section is ''owned'' by the defining package. You should make sure that you declare ownership of every new file or directory the package creates.  You can use wildcards (*) which match a set of files - this makes the package less sensitive to changes. For example, you can declare that all the files that were copied into %{buildroot}/usr/bin are owned by this package by declaring:
To make your package less sensitive to upstream changes, declare all files within a directory to be owned by the package with a pattern match:
  %{_bindir}/*
  %{_bindir}/*


Note that "%{_bindir}/*" does not claim that this package owns the /usr/bin directory - it claims that all the files that were installed inside the ''build root'' 's /usr/bin are owned by the package.
To include a single directory:
If you list a ''directory'' in the %files section, then you are claiming that this package owns that subdirectory and all files and directories in it, recursively (''all'' the way down) if they are present in the build root.  Do not list the "/usr/bin" or "%{_bindir}" directories directly in your %files list, because that would claim ownership of /usr/bin and everything inside it.  Claiming ownership of "%{_bindir}/*" is fine, though; that just claims ownership of the subdirectories and files you placed ''under'' %{buildroot}/%{_bindir}.  If you create a subdirectory such as %{_datadir}/%{name}, (/usr/share/NAME), you ''should'' include that directory in the %files list:
  %{_datadir}/%{name}/
  %{_datadir}/%{name}/


It's usually easier to use wildcards for filenames, and that's also better at copying with changes in upstream.  Older RPM documentation typically shows long lists under %files with individual names, such as /usr/bin/program1 followed by /usr/bin/program2. Because of the way Fedora now uses buildroots, that is no longer necessary.
Note that <code>%{_bindir}/*</code> does not claim that this package owns the <code>/usr/bin</code> directory, but only the files contained within. If you list a directory, then you are claiming that the package owns that directory and all files and subdirectories contained within. Thus, do '''not''' list <code>%{_bindir}</code> and be careful of directories that may be shared with other packages.


It's an error if ''no'' file matches the wildcard of a line, so only note the directories that actually matter.  Also, you can't identify the same file or directory more than once.  Finally, it's an error to have something in the buildroot and ''not'' listed under %files; the whole point of copying something into the buildroot is because you intend to have it installed in the final system.  If you don't intend that, remove those files during the %install process.
An error will occur if:
* a pattern match does not match any file or directory
* a file or directory is listed or matched more than once
* a file or directory in the <code>%{buildroot}</code> has not been listed


It is also possible to exclude files from a previous match by using a %exclude glob. This can be useful for including "almost all" of the files that match a different glob. However, note that, like any other file glob, even a %exclude glob will fail if it matches nothing. (This might be considered counterintuitive, as the whole point is essentially to ensure that a certain file ISN'T there, so this rule is especially important to remember.)
It is also possible to exclude files from a previous match by using the <code>%exclude</code> glob. This can be useful for including almost all of the files included by a different pattern match, but note that it will also fail if it does not match anything.


==== %files prefixes ====
==== %files prefixes ====
You may need to add one or more prefixes to a %files entry (if more than one, use a space to separate them).
You may need to add one or more prefixes to lines in the <code>%files</code> section; seperate them with a space. See [http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html Max RPM section on %files directives].


Typically there is a "%doc" entry with a list of documentation files that didn't get copied into the buildroot; usually there is at least a README and LICENSE file.  You ''must'' include the license file, if there is one. You may prefix some of these with %attr(mode, user, group) to set the file permission mode, user, or group.  You don't need to claim ownership of the /usr/share/doc/%{name} directory, that's automatic if there's a %doc entry.  Any %doc entry must not affect the runtime of the application (if it is in %doc, the program must run properly if it is not present).
Usually, "<code>%doc</code>" is used to list documentation files within <code>%{_builddir}</code> that were not copied to <code>%{buildroot}</code>. A <code>README</code> and <code>INSTALL</code> file is usually included. They will be placed in an appropriate directory under <code>/usr/share/doc</code>, whose ownership does not need to be declared.


There is a potential 'gotcha' with %doc entries: if you have a %doc entry, then you can't use commands during %install to copy files into the documentation directory descending from %_defaultdocdir. That's because if there's a %doc entry, rpmbuild will automatically remove the docdir files created by %install before installing the files listed with %doc. This can hit you if, for example, you want an "examples" subdirectory in the documentation directory.  In this case, don't use "%doc" to mark documentation.  Instead, create the directories and copy the files into %{buildroot}%{_defaultdocdir}/%{name}-%{version}/ during %install, and make sure that %files includes an entry for "%{_defaultdocdir}/%{name}-%{version}/".  They will still be correctly marked as documentation.
'''Note:''' If specifying a <code>%doc</code> entry, rpmbuild < 4.9.1 removes the doc directory it installs files into before installing them. This means that files already in it, for example installed in the <code>%install</code> section, are removed and do not end up in the package. If you want to install some files in the <code>%install</code> section, install them into a temporary staging directory inside the build dir (not build root), for example <code>_docs_staging</code>, and include them in the in the <code>%files</code> list like <code>%doc _docs_staging/*</code>.


If you save configuration files (under /etc - don't put them under /usr), you should normally prefix them with %config(noreplace) unless this program version uses a non-backwards-compatible configuration format (in which case, prefix them with %config).
Configuration files should be placed in <code>/etc</code> and are normally specified like this (which makes sure user changes aren't overwritten on update):
%config(noreplace) %{_sysconfdir}/foo.conf
If the update uses a non-backwards-compatible configuration format, then specify them like this:
%config %{_sysconfdir}/foo.conf


Prefixing a %files entry with "%attr(mode, user, group)" lets you set the permissions for particular file(s), e.g., "%attr(0644, root, root)".  A "-" means "use the default".
"<code>%attr(mode, user, group)</code>" can be used for finer control over permissions, where a "<code>-</code>" means use the default:
%attr(0644, root, root) FOO.BAR


If a file is in particular natural language, use %lang to note that. E.G.:
If a file is in particular natural language, use <code>%lang</code> to note that:
  %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
  %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*


Some documentation claims that %license and %readme are valid prefixes; they are ''not'' valid in Fedora.  Use %doc instead.
Programs using Locale files should follow the [[Packaging:Guidelines#Handling_Locale_Files|recommended method of handling i18n files]]:
* find the filenames in the <code>%install</code> step: <code> %find_lang ${name}</code>
* add the required build dependencies: <code>BuildRequires: gettext</code>
* use the found filenames: <code>%files -f ${name}.lang</code>
 
These prefixes are '''not''' valid in Fedora: <code>%license</code> and <code>%readme</code>.


==== %files and Filesystem Hierarchy Standard (FHS) ====
==== %files and Filesystem Hierarchy Standard (FHS) ====


You should follow the [http://www.pathname.com/fhs/ Filesystem Hierarchy Standard (FHS)], i.e., ordinary application executables go into /usr/bin, global configuration files go into /etc, ordinary libraries go into /usr/lib, and so on, with one exception: executables that should ''not'' normally be executed directly by users or administrators should go into a subdirectory of /usr/libexec; usually you'd refer to the necessary directory as "%{_libexecdir}/%{name}".
You should follow the [http://www.pathname.com/fhs/ Filesystem Hierarchy Standard (FHS)]. Executables go in <code>/usr/bin</code>, global configuration files go in <code>/etc</code>, libraries go into <code>/usr/lib</code> (or <code>/usr/lib64</code>) and so on. There is one exception: executables that should not normally be executed directly by users or administrators should go in a subdirectory of <code>/usr/libexec</code>, which is referred to as <code>%{_libexecdir}/%{name}</code>.


You shouldn't be installing files under /usr/local; that is where ''unpackaged'' files go.
Do '''not''' install files into <code>/opt</code> or <code>/usr/local</code>.
Typically there will be a "prefix" attribute that lets you set the prefix to be "/usr" instead of "/usr/local".


Unfortunately, many programs' "normal" installation routines do not follow the FHS.
Unfortunately, many programs do not follow the FHS by default. In particular, architecture-independent libraries get placed in <code>/usr/lib</code> instead of <code>/usr/share</code>. The former is for architecture-dependent libraries, while the latter is for architecture-independent libraries, which means that systems with different CPU architectures can share <code>/usr/share</code>. There are many exceptions in Fedora (such as Python and Perl), but Fedora applies this rule more strictly than some distributions. <code>rpmlint</code> will generally complain if you put anything other than ELF files into <code>/usr/lib</code>.
In particular, many programs normally place architecture-independent libraries under /usr/lib, instead of
under /usr/share as the FHS requires.
The [http://www.pathname.com/fhs/pub/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA FHS /usr/lib section] says that
/usr/lib is for architecture-''dependent'' data (e.g., ELF files like .so files), while
[http://www.pathname.com/fhs/pub/fhs-2.3.html#USRSHAREARCHITECTUREINDEPENDENTDATA /usr/share] is for
architecture-''independent'' data.  That way, systems with different CPUs can share /usr/share.
There are many exceptions to this rule in Fedora (e.g., Python and Perl), but Fedora applies this rule more
strictly than some distributions. Note, for example, that rpmlint will complain if you
put just about anything other than ELF files into /usr/lib.


==== %files example ====
==== %files example ====
Line 548: Line 473:
Here's a simple example of a %files section:
Here's a simple example of a %files section:
  %files
  %files
%defattr(-,root,root,-)
  %doc README LICENSE
  %doc README LICENSE
  %{_bindir}/*
  %{_bindir}/*
  %{_sbindir}/*
  %{_sbindir}/*
  %{_datadir}/%{name}/
  %{_datadir}/%{name}/
%config(noreplace) %{_sysconfdir}/*.conf
==== Finding duplicates ====
You can list any duplicates of two binary packages by doing:
cd ~/rpmbuild/RPMS/ARCH # Substitute "ARCH" for your architecture
rpm -qlp PACKAGE1.*.rpm | sort > ,1
rpm -qlp PACKAGE2.*.rpm | sort > ,2
comm -12 ,1 ,2


=== Scriptlets ===
=== Scriptlets ===
You can add sections so that code will run when packages are installed or removed on the real system (as opposed to just running the %install script, which only does a pseudo-install to the build root).  These are called "scriptlets", and they are usually used to update the running system with information from the package.


The scriptlets in %pre and %post are run before and after a package is installed (respectively). The scriptlets %preun and %postun are run before and after a package is uninstalled. The scriptlets %pretrans and %posttrans are run at start and end of a transaction.  See [[Packaging/ScriptletSnippets]] for more examples and details.  For example, every binary RPM package which stores shared library files (not just symlinks) in any of the dynamic linker's default paths, must call ldconfig in %post and %postun (post-install and post-uninstall). If the package has multiple subpackages with libraries, each subpackage should also have a %post/%postun section that calls /sbin/ldconfig. For example:
When an end-user installs the RPM, you may want some commands to be run. This can be achieved through scriptlets. See [[Packaging/ScriptletSnippets]].
 
Scriptlets can be run:
* before ('''<code>%pre</code>''') or after ('''<code>%post</code>''') a package is installed
* before ('''<code>%preun</code>''') or after ('''<code>%postun</code>''') a package is uninstalled
* at the start ('''<code>%pretrans</code>''') or end ('''<code>%posttrans</code>''') of a transaction
 
For example, every binary RPM package that stores shared library files in any of the dynamic linker's default paths, must call <code>ldconfig</code> in <code>%post</code> and <code>%postun</code>. If the package has multiple subpackages with libraries, each subpackage should also perform the same actions.
  %post -p /sbin/ldconfig
  %post -p /sbin/ldconfig
  %postun -p /sbin/ldconfig
  %postun -p /sbin/ldconfig


''Beware'': The "-p" option specifies what ''command processor'' to use for the commands on the following lines.
If only running a single command, then the "<code>-p</code>" option runs the adjacent command without invoking the shell. However, for several commands, omit this option and include the shell commands beneath.
If there are no following lines, then using /sbin/ldconfig as the "command processor" is a minor efficiency improvement compared to putting "/sbin/ldconfig" on the next line, and letting the shell invoke it.
That's because by using "-p",
the shell isn't invoked simply to invoke a single program.
But if you have multiple shell commands,
don't use "-p" or /sbin/ldconfig after it!  Instead, leave it blank, and include the shell commands under it.


If you are going to run programs in scriptlets, they must be installed before you run them.
If you run any programs within the scriptlets, then you must specify any requirements in the form "<code>Requires(CONTEXT)</code>" (e.g. <code>Requires(post)</code>).
You have to use special variants of the "Requires:" tag, so that
the program will be installed before you try to use it.  These are of the form "Requires(CONTEXT):", e.g., "Requires(post)".


Most scriptlets (%pre, %post, %preun, and %postun) provide an argument you can use,
<code>%pre</code>, <code>%post</code>, <code>%preun</code>, and <code>%postun</code> provide the argument <code>$1</code>, which is the number of packages of this name which will be left on the system when the action completes. Don't compare for equality with <code>2</code>, but instead check if they are greater than or equal to <code>2</code>. For <code>%pretrans</code> and <code>%posttrans</code>, <code>$1</code> is always <code>0</code>.
accessed via $1, which is the number of packages of this name which will be left on the system
when the action completes.
Don't compare for ''equality'' with 2; check if they are ''greater than or equal than'' 2, since
users can arrange to have multiple versions of a package installed simultaneously.
For %pretrans and %posttrans, $1 is always 0.
 
For example, after adding an info manual to the system the dir file
which indexes the info manuals should be updated.
Basically, after you install the info manual, you need to run the program install-info.  That's fine, except that install-info is part of package info, and there's no guarantee that info is installed unless we require it. Also, if "install-info" fails, we don't want to fail ''all'' processing. Here's one way to do that:


For example, if the package installs an info manual, then the info manual index must be updated with <code>install-info</code> from the <code>info</code> package. Firstly, there is no guarantee that the <code>info</code> package will be available unless we explicitly declare it as required, and secondly, we don't want to fail completely if <code>install-info</code> fails:
  Requires(post): info
  Requires(post): info
  Requires(preun): info
  Requires(preun): info
Line 593: Line 517:
  fi
  fi


Another scriptlet-like abilility are ''triggers''.  You can define triggers for when ''other'' packages
There is one other glitch related to installing info manuals. The <code>install-info</code> command will update the info directory, so we should delete the useless empty directory from the %{buildroot} during the <code>%install</code> section:
are installed or uninstalled. See ''Maximum RPM'' for more information about triggers.
rm -f %{buildroot}%{_infodir}/dir
 
Another scriptlet-like ability are "triggers", which can be run for your package when other packages are installed or uninstalled. See [http://rpm.org/api/4.4.2.2/triggers.html RPM Triggers].


=== Macros ===
=== Macros ===


Spec files may contain "macro" references (text beginning with "%"), which are replaced with other values.
Macros are text in the format <code>%{string}</code>. Typical macros:
You can follow % by a word, e.g., "%name", but just like shell variables you must bracket the name with {...}
if letters or digits immediately follow, e.g., "%{name}".
 
As noted in the
[[Packaging/Guidelines| Packaging Guidelines]],
There are two styles for referring some values such as the rpm Build Root and Optimization Flags:
* "macro style": %{buildroot}, %{optflags}
* "variable style": $RPM_BUILD_ROOT, $RPM_OPT_FLAGS
Pick a style and use it consistently throughout your packaging; this document uses "macro style".
 
Here are some typical macros:


{|
{|
! Macro !! Typical Expansion !! Meaning
! Macro !! Typical Expansion !! Meaning
|-
|-
| %{_bindir} || /usr/bin || Binary directory (where executables are usually stored)
| <code>%{_bindir}</code> || <code>/usr/bin</code> || Binary directory: where executables are usually stored.
|-
|-
| %{_builddir} || ~/rpmbuild/BUILD || Build directory; files are compiled a subdirectory of the build directory. See %buildsubdir.
| <code>%{_builddir}</code> || <code>~/rpmbuild/BUILD</code> || Build directory: files are compiled within a subdirectory of the build directory. See <code>%buildsubdir</code>.
|-
|-
| %{buildroot} || ~/rpmbuild/BUILDROOT || Build root, where files are "installed" during %install. The %install stage copies files from a subdirectory of %{_builddir} to a subdirectory of %{buildroot}. Historically %{buildroot} was in "/var/tmp/".
| <code>%{buildroot}</code> || <code>~/rpmbuild/BUILDROOT</code> || Build root: where files are "installed" during the <code>%install</code> stage, which copies files from a subdirectory of <code>%{_builddir}</code> to a subdirectory of <code>%{buildroot}</code>. (Historically, <code>%{buildroot}</code> was in "/var/tmp/".)
|-
|-
| %{buildsubdir} || %{_builddir}/%{name} || Build subdirectory, where files are compiled during %build. It's under %{_builddir}, set after %setup.
| <code>%{buildsubdir}</code> || <code>%{_builddir}/%{name}</code> || Build subdirectory: a subdirectory within <code>%{_builddir}</code> where files are compiled during the <code>%build</code> stage. It is set after <code>%autosetup</code>.
|-
|-
| %{_datadir} || /usr/share || Share directory.
| <code>%{_datadir}</code> || <code>/usr/share</code> || Share directory.
|-
|-
| %{_defaultdocdir} || /usr/share/doc || Default documentation directory.
| <code>%{_defaultdocdir}</code> || <code>/usr/share/doc</code> || Default documentation directory.
|-
|-
| %{dist} || .fc''NUMBER'' || Distribution+version short name (e.g., ".fc9")
| <code>%{dist}</code> || <code>.fc''NUMBER''</code> || Distribution+version short name (e.g. "<code>.fc{{FedoraVersion}}</code>")
|-
|-
| %{fedora} || ''NUMBER'' || Number of fedora release (e.g., 9)
| <code>%{fedora}</code> || <code>''NUMBER''</code> || Number of fedora release (e.g. "<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} || || Name of package, set by Name: tag
| <code>%{name}</code> || || Name of package, set by Name: tag
|-
|-
| %{_sbindir} || /usr/sbin
| <code>%{_sbindir}</code> || <code>/usr/sbin</code>
|-
|-
| %{_sharedstatedir} || /usr/com
| <code>%{_sharedstatedir}</code> || <code>/var/lib</code>
|-
|-
| %{_sysconfdir} || /etc
| <code>%{_sysconfdir}</code> || <code>/etc</code>
|-
|-
| %{version} || || Version of package, set by Version: tag
| <code>%{version}</code> || || Version of package, set by Version: tag
|}
|}


To see more about macros you
Learn more about macros by looking in <code>/etc/rpm/*</code> and <code>/usr/lib/rpm</code>, especially <code>/usr/lib/rpm/macros</code>. Also use <code>rpm --showrc</code> to show values that RPM will use for macros (altered by <code>rpmrc</code> and macro configuration files).
can look in /etc/rpm/* and the "macros" files under "/usr/lib/rpm/",
especially /usr/lib/rpm/macros.
You can also use "rpm --showrc" to show the values rpm will use for all of the options
currently set in rpmrc and macro configuration files.


You can set your own macro values using %global; be sure to define them before you use them. Macro definitions
You can set your own macro values using %global, but be sure to define them before you use them. (Macro definitions can also refer to other macros.) For example:
can refer to other macros.  For example:
  %global date 2012-02-08
  %global myvalue 50


You can use rpmbuild to find the value of some macro, using its "-E" (--eval) option. For example, to find the current expansion of %{_bindir} in myfile.spec, you can run:
Use the "<code>-E</code>" option of <code>rpmbuild</code> to find the value of a macro in a SPEC file:
  rpmbuild -E '%{_bindir}' myfile.spec
  rpmbuild -E '%{_bindir}' myfile.spec


[[Packaging/RPMMacros]] has more information on macros, as does
Also see [[Packaging/RPMMacros]] and [https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s07.html RPM Guide chapter 9].
[http://docs.fedoraproject.org/drafts/rpm-guide-en/ch09s07.html RPM Guide chapter 9].


=== Other tags ===
=== Other tags ===


We noted the "Requires" and "BuildRequires" tags earlier.
In addition to Requires and BuildRequires tags, you can also use these for controlling dependencies:
There are a few other tags for controlling dependencies:
* '''Provides''': list virtual package names that this package provides. For example, there might be a package "<code>foo</code>" that demands a particular functionality "bar" from another program. If there are several packages that can satisfy that demand, those packages can specify "<code>Provides: bar</code>" and the "<code>foo</code>" package can specify "<code>Requires: bar</code>". You could also use the [http://dailypackage.fedorabook.com/index.php?/archives/6-Wednesday-Why-The-Alternatives-System.html "alternatives" system], but avoid if multiple users on the same system might want different default, as these settings are system-wide. Use "<code>rpm -q --provides PACKAGENAME</code>" to see what a given package provides. Some examples of virtual packages in Fedora:
Provides, Obsoletes, Conflicts, and BuildConflicts.
** MTA: Used for mail transport agents, such as sendmail.
* "Provides:" lets you list ''virtual'' package names that this package provides. Sometimes there are several different packages that can provide a function, and using packages won't care which one.  In that case, each of the packages that provide the function should "provide" a virtual package, and then using packages can list the virtual package name under "Requires:".  For example, several different packages might provide "latex"; if you depend on the virtual package "tex(latex)", then users can choose which package to get "latex" from. If you provide virtual packages, you might also want to use the [http://dailypackage.fedorabook.com/index.php?/archives/6-Wednesday-Why-The-Alternatives-System.html "alternatives" system], but be careful: "alternatives" settings are ''system-wide'', so if multiple users on the same system might want different defaults, don't use the alternatives system. You can find out what a given package provides (both virtual and non-virtual names) by querying "rpm -q --provides PACKAGENAME". Some virtual packages in Fedora are:
** tex(latex): Used for latex
** ''MTA'' : Used for mail transport agents, such as sendmail.
* '''Obsoletes''': remove another named package(s) when this package is installed. Use when the package name changes or when it totally replaces a different package.
** ''tex(latex)'' : Used for latex
* '''Conflicts''': state what other packages cannot be installed simultaneously to this one. Avoid this if you can. See [[Packaging/Conflicts]].
* "Obsoletes:" lets you state that installing this package should (normally) cause the removal of the other named package(s). This is useful when a package's name changes, or when a package wholly replaces a different package.
* '''BuildConflicts''': state what packages cannot be installed when building this package. Avoid this if you can.
* "Conflicts:" lets you state what packages cannot be installed simultaneously this one. Obviously, try to avoid this if you can; see [[Packaging/Conflicts]] if you think you need to use it.
* "BuildConflicts:" lets you state what packages cannot be installed when building this package. Obviously, try to avoid this if you can.


You can control which architectures a package builds (or doesn't build). For example, if your package can't compile on ppc, you can do this:
To manage different architectures, there are two tags:
* '''ExcludeArch''': to exclude an architecture on which the package doesn't build. For example:
  ExcludeArch: ppc
  ExcludeArch: ppc
There's also an "ExclusiveArch" tag. The valid architectures one can specify in these tags are listed in the [[Architectures]] section.
* '''ExclusiveArch''': to include only the specified architecture. Avoid this unless absolutely correct.
Valid architectures are listed at [[Architectures]].


=== Subpackages ===
=== Subpackages ===
A spec file can define more than one binary package, e.g., client and server,
or runtime and developer packages.
If there's a large amount of documentation, it may be split into a NAME-doc subpackage.
You will always have one spec file and one source RPM (SRPM), even if there are
multiple binary RPMs that they generate.
A spec file that produces multiple binary packages still has only
one creation process, so there is only one
%prep, %build, %check, and %install section that creates all the files
for all the packages.


In a spec file, use the %package directive to start defining a subpackage:
A SPEC file can define several binary package. In other words, one SRPM with one SPEC file can result in several RPMS. Note that there is still only one creation (%prep, %build, %install etc.) process. <code>name-doc</code> and <code>name-devel</code> subpackages are common for documentation and development files respectively.
%package sub_package_name


By default, the subpackage name is PACKAGE_NAME, "-", SUBPACKAGE_NAME; you can
Use the <code>%package</code> directive to start defining a subpackage:
use "-n" to override this and make a new name:
  %package subpackage_name
  %package -n new_sub_package_name
 
After each <code>%package</code> directive, list the tags for the subpackage. This should at least include the Summary and Group tags, as well as the <code>%description subpackage_name</code> and <code>%files subpackage_name</code> directives:


After the %package directive, list the tags for the subpackage.
This should include at least the "Summary:" and "Group:" tags and directives
"%description SUBPACKAGE_NAME" and "%files SUBPACKAGE_NAME".
Anything not specified by the subpackage will be inherited from its parent.
Anything not specified by the subpackage will be inherited from its parent.
For the directives, if you used "-n" with %package,
you'll need it again for these directives.
You need to specify the name for the other directives, e.g., %pre and %post,
if you use them in the subpackage.


[http://docs.fedoraproject.org/drafts/rpm-guide-en/ch10s04.html See the RPM Guide section on subpackages] for more information.
By default, if the package name is "<code>foo</code>" and the subpackage name is "<code>bar</code>", then the resulting subpackage will be "<code>foo-bar</code>". You can override it with the "<code>-n</code>" option (but you'll need to use it in all other directives too if you specify it here):
%package -n new_subpackage_name
 
[http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch10s04.html See the RPM Guide section on subpackages] for more information.


=== Conditionals ===
=== Conditionals ===


You can insert conditional statements.
You can insert conditional statements, for example to test if you are creating a binary for a certain architecture:
E.G., you can test if you are creating a binary for a certain architecture
with:
  %ifarch ARCHITECTURE_NAME
  %ifarch ARCHITECTURE_NAME
the negated version with:
the negated version with:
Line 727: Line 622:
  %if TRUE_OR_FALSE
  %if TRUE_OR_FALSE


There is an optional "%else" section; all of these are closed with "%endif".
There is an optional "<code>%else</code>" section; all of these are closed with "<code>%endif</code>".


=== Application Specific Guidelines ===
=== Application Specific Guidelines ===
Line 744: Line 639:
=== Miscellaneous hints ===
=== Miscellaneous hints ===


Try to write your scripts so that when upstream makes changes, the packaging is likely to work when you change the version number and reload the source file(s). For example, if it contains *.txt files with execute bits, instead of doing:
[[Packaging/FrequentlyMadeMistakes]] has information on frequently-made mistakes. There are also some recommendations and controversial tricks on
[[PackageMaintainers/Packaging Tricks]].
 
Try to write your SPEC files so that it is likely to work when a new release is made upstream, without any changes aside from bumping the version number and refreshing the source files. For example, if it contains *.txt files with execute bits, instead of doing
   chmod a-x Filename1.txt Filename2.txt Filename3.txt
   chmod a-x Filename1.txt Filename2.txt Filename3.txt
consider doing this, which will handle new filenames that use the same file naming convention:
consider doing this, which will handle new filenames that use the same file naming convention:
Line 751: Line 649:
If you want to see lots of examples of scriptlets, you can show all the scriptlets on installed programs using:
If you want to see lots of examples of scriptlets, you can show all the scriptlets on installed programs using:
   rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less
   rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less
[[Packaging/FrequentlyMadeMistakes]] has information on frequently-made mistakes.


Don't try to interact with the user; RPM is designed to support batch installs.  If an application needs to show a EULA, that needs to be part of its initial execution, not its installation.
Don't try to interact with the user; RPM is designed to support batch installs.  If an application needs to show a EULA, that needs to be part of its initial execution, not its installation.


You might not want to start services, because in a big install that could slow things down. If you install an init script, consider using chkconfig to arrange for the service to be started and stopped on the next reboot.  Before ''uninstalling'' you should normally try to stop its services if it's running.
You might not want to start services, because in a big install that could slow things down. If you install an init or systemd script, consider using <code>chkconfig</code> or <code>systemctl</code> to arrange for the service to be started/stopped on the next reboot.  Before uninstalling, you should normally try to stop its services if they are running.


Uninstall should reverse most changes made during installation, but don't remove any user-created files.
Uninstalling should reverse most changes made during installation, but don't remove any user-created files.


Normally, if there are binary executables, a separate "debug" package is created with the symbols, and the symbols are stripped from the normal binary packages. If this shouldn't happen, you can disable the package-creation and stripping with:
Normally, if there are binary executables, then debugging symbols are stripped from the normal binary packages and placed into a <code>name-debug</code> subpackage. If this shouldn't happen, you can disable the stripping and creation of this subpackage by putting this at the top of your 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}


A way to check for the version of Fedora in a spec file for conditional builds is:
To prevent stripping you may also need to do this in the <code>%install</code> section:
export DONT_STRIP=1
 
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>
(The ? causes the macro to evaluate to blank if %fedora is not defined, and this causes the end result to be "0", which is a number and thus ok, while not interfering with the result if there is actually a value for %fedora.)
The <code>?</code> causes the macro to evaluate to evaluate to blank if <code>%fedora</code> is not defined. This causes the end result to be the <code>0</code> (which is a number and thus fine), while not interfering with the result if there is actually a value for <code>%fedora</code>. (Note that this trick does not work in Koji "scratch" builds, where <code>%fedora</code> is set during the creation of a SRPM.)


Note that the previous trick DOES NOT work in Koji "scratch" builds - %fedora is set during the creation of a source RPM. (Thus, this trick does work in actual Koji builds as the system extracts sources from the source RPM and rebuilds the source RPM with the appropriate %fedora value.)
GUI programs must have a desktop entry so that people can invoke it from the graphical desktop menu. For <code>.desktop</code> files, see [[Packaging/Guidelines#Desktop_files|Fedora packaging guidelines for desktop files]] and [http://standards.freedesktop.org/desktop-entry-spec/latest/ desktop entry spec]. For icons within <code>/usr/share/icons</code>, see [http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html icon theme spec].


There are also some recommendations and controversial tricks on
== Building the binary package ==
[[PackageMaintainers/Packaging Tricks]].


GUI programs ''must'' have a desktop entry (so that people can invoke it from a graphical menu). The
=== Test with rpmlint ===
[http://fedoraproject.org/wiki/Packaging/Guidelines#Desktop_files Fedora packaging guidelines discuss desktop files].  See also the [http://standards.freedesktop.org/desktop-entry-spec/latest/ desktop entry spec] (for .desktop files) and
[http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html icon theme spec] (for icon-related materials such as those in /usr/share/icon).


=== Older RPM documents ===
To catch many common errors early, run <code>rpmlint</code> on your SPEC file before trying to build anything from it:
Some older documents about RPM have the most information, but some older documents make claims that are no longer true:
  $ rpmlint program.spec
* rpm files are no longer placed in a shared /usr/src/redhat directory. This is an obsolete way of using rpm and ''not'' recommended; modern systems set a %{_topdir} instead like ~/rpmbuild.
If the reported error doesn't make sense, run it again with the "<code>-i</code>" option for longer messages.
* the %install process does not install files in their final location.  Instead, it "installs" files to the buildroot.
* The "rpm" command no longer creates packages (e.g., "rpm -ba" was once legal). Use the separate "rpmbuild" program instead.
* Many historical specs use the "%define" command to define macros.  However, "%define" creates a locally defined submacro within other macro definitions; this is very rarely needed, and using %define incorrectly can cause subtle bugs.  For nearly all uses, use "%global" instead.  (See [[PackagingDrafts/global_preferred_over_define]].)
* The "BuildRoot:" value is now ignored.


== Quick test with rpmlint ==
Aim to have no errors, but sometimes <code>rpmlint</code> reports false positives. The [[Packaging/Guidelines#Use_rpmlint|Fedora packaging guidelines]]
explains which ones to ignore.


Before trying to build anything from it, you should run ''rpmlint'' on the spec file:
=== Create binary RPMS from the SPEC file ===
rpmlint program.spec
This will catch many errors early. If the reported error doesn't make sense,
run it again with the "-i" option (this gives longer messages).


Generally, you should not have errors from rpmlint, but sometimes
Once you've created your SPEC file, build the SRPM and binary RPMS by running this:
rpmlint is excessively noisy.
$ rpmbuild -ba program.spec
The
[http://fedoraproject.org/wiki/Packaging/Guidelines#Use_rpmlint Fedora packaging guidelines]
explain which ones to ignore, e.g., ignore "no-packager-tag" and "no-signature" errors.


== Creating RPMs from the spec file ==
If successful, RPMS will be created within <code>~/rpmbuild/RPMS</code> and SRPMS will be created within <code>~/rpmbuild/SRPMS</code>.


Once you've create a spec file, say "program.spec", you can create
If it fails, go to the appropriate directory and see what is left over. To help debug, you can skip earlier stages that succeeded with the "<code>--short-circuit</code>" option. For example, to restart at the <code>%install</code> stage (skipping earlier stages), do this:
source and binary RPMs by simply running this:
$ rpmbuild -bi --short-circuit program.spec
  $ rpmbuild -ba program.spec


If this works, then your binary RPM files will be created underneath ~/rpmbuild/RPMS/ and the source RPM will be in ~/rpmbuild/SRPMS.
If you just want to create an SRPM (which does not run the <code>%prep</code> or <code>%build</code> or other stages), run this:
 
When things go wrong, you can "cd" into the appropriate directory and see what's left over.
If you want to skip earlier stages, use the "--short-circuit" option; this is handy if you had a successful build, but have an error in the %install section.  For example, to restart at the %install stage (skipping earlier stages), do this:
  $ rpmbuild -bi --short-circuit program.spec
 
If you just want to create a source RPM (.src.rpm), do this in the SPECS directory:
  rpmbuild -bs program.spec
  rpmbuild -bs program.spec
This will create the source RPM in ~/rpmbuild/SRPMS.  Creating ''only'' a source rpm (.src.rpm) is quite quick, because rpm simply needs to copy the .spec file and associated SOURCES files into a .src.rpm file.  Creating a binary rpm typically takes ''much'' longer, because this requires running the %prep, %build, and %install scripts.


== Testing RPMs you've built (including rpmlint) ==
=== Testing binary RPMS with rpmlint ===


Run rpmlint on the .spec files, generated ''binary'' RPM, and generated source RPM. Rpmlint works on .spec files, binary RPMs, and source RPMs, finding different things in each.  You need to eliminate or justify rpmlint warnings before posting a package. If you are in the SPECS directory, do this:
<code>rpmlint</code> can be run on SPEC files, RPMS and SRPMS to check for errors. You need to eliminate or justify warnings before posting a package. [[Common_Rpmlint_issues|This page]] offers explanations for some of the common issues that come up. If you are in the SPECS directory, do this:
  $ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm
  $ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm


Normally rpmbuild will build a binary RPM with debugging information - this will handle that.
Enter the <code>~/rpmbuild/RPMS</code> directory and into the architecture subdirectory. You will find some binary RPMS. Quickly see their files and permissions (to check whether they are correct) by doing:
$ rpmls *.rpm


If you "cd" to the "~/rpmbuild/RPMS" directory, and then cd to the architecture subdirectory,
If they look fine, install them as root:
you'll find some binary rpms. You can quickly see their files and their permissions by using rpmls
  # rpm -ivp package1.rpm package2.rpm package3.rpm ...
(check to see that they are what you expect):
  $ rpmls *.rpm


If those look okay, you can become root and try to install them:
Test the programs in a few different ways to see if everything works correctly. If it is a GUI tool, make sure it shows up in the desktop menu, otherwise the <code>.desktop</code> entry is wrong.
# rpm -ivp XYZ1.rpm XYZ2.rpm XYZ3.rpm ...


Then, you can test them out. Use it a few different ways and see if it works correctly.  If it's a GUI tool, make sure it shows up in the menu (if it doesn't, something is wrong with your .desktop entry).
Uninstall packages later by doing:
  # rpm -e package1 package2 package3


You can uninstall packages later using:
== Mock and Koji ==
# rpm -e XYZ1 XYZ2 XYZ3


If that works, you can use Mock to do a more rigorous test that you have accurate build dependencies.  Basically, mock will create a nearly-empty environment and try to rebuild the package; if it fails, then you forgot to list something in a "BuildRequires:" statement. See [[Using Mock to test package builds]] for more information about how to use Mock; once your account is a member of the "mock" group, you can run commands like this to do local testing:
[[Projects/Mock|Mock]] is a powerful tool that uses the SRPM you have created to build binary packages within a nearly empty environment. This can reveal if you have accurate build dependencies. If it fails, then you forgot to list something in BuildRequires. See [[Using Mock to test package builds]]. Once your account is a member of the "<code>mock</code>" group, you can run commands like this to do local testing:
  $ mock -r fedora-9-i386 rebuild path_to_source_RPM
  $ mock -r fedora-9-i386 rebuild path_to_source_RPM


If a mock build fails, or the resulting program doesn't work correctly, then you almost certainly have one or more missing BuildRequires packages.
You can use Koji (which uses <code>mock</code>) to do builds on many different systems, some of which you may not have. [[PackageMaintainers/Join]] and [[PackageMaintainers/UsingKoji]] have more information about Koji. Once it's set up, you can test your SRPM on a variety of platforms by running commands like:
 
Once Mock works on your system, you can use Koji (which uses Mock) to do builds on
many different systems, some of which you may not have.
[[PackageMaintainers/Join]] and [[PackageMaintainers/UsingKoji]] have more information about Koji.
Once it's set up, you can test your source RPM
on a variety of platforms by running commands like:
  $ koji build --scratch dist-f9 path_to_source_RPM
  $ koji build --scratch dist-f9 path_to_source_RPM


You can replace dist-f9 with dist-f8, dist-f10, etc., to try other releases. Don't use "dist-rawhide", that's not really rawhide. Remember, the values of %fedora, %fc9, etc., will not be correct for a scratch build, so this won't work if your spec file does something different based on those values.
Replace <code>dist-f9</code> with any later release of Fedora, but don't use <code>dist-rawhide</code>. Remember, the values of <code>%fedora</code>, <code>%fc9</code> and so on will not be correct for a scratch build, so this won't work if your SPEC file does something different based on those values.


Your koji builds can only depend on packages that are actually in the TARGET distribution repository.  Thus, you can't use koji to build for released distributions if your package depends on other new packages that Bodhi hasn't released yet. You ''can'' use koji to build for rawhide (the next unreleased version), even if it depends on other new packages, as long as the other packages were built in the CVS "devel" section as described below.
Your Koji builds can only depend on packages that are actually in the TARGET distribution repository.  Thus, you can't use Koji to build for released distributions if your package depends on other new packages that Bodhi hasn't released yet. If you need to build against a package that is not yet a stable released update, submit a Koji buildroot override request via Bodhi. If it's not your own package you depend on, contact its maintainer(s). [Before Bodhi could handle Koji buildroot override requests, the old method has been to file a ticket with rel-eng at: https://fedorahosted.org/rel-eng/newticket and request that that package be added as a buildroot override.]
If you need to build against a package that is not yet a stable released update, you can file a ticket with rel-eng at: https://fedorahosted.org/rel-eng/newticket and request that that package be added as a buildroot override.


== Helpful tools ==
== Helpful tools ==


The "rpmdevtools" package has a number of helpful tools; "rpm -qil rpmdevtools" will show you what it installs.
The <code>rpmdevtools</code> package has a number of helpful tools; "<code>rpm -qil rpmdevtools</code>" will show you what it installs.
One particularly useful tool is rpmdev-bumpspec, which has this form:
* <code>rpmdev-bumpspec</code> : bump the release tag in the spec file and add a changelog comment with the right date and version format:
  rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
  rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
rpmdev-bumpspec will bump the release tag in the spec file(s), and add a changelog comment with the right datetime and version format.  COMMENT should typically start with "- ".


Similarly, "yum-utils" has a number of yum-specific tools.  "yumdownloader" is especially helpful; you can download the source RPM of a package by simply running "yumdownloader --source PACKAGENAME".  You can then use "rpm -U SOURCEPACKAGENAME" to install the source files.  E.G., "yumdownloader --source glib; rpm -Uvh glib*.src.rpm".
The <code>yum-utils</code> package also has some useful tools:
* <code>yumdownloader</code> : download the SRPM of the package by running:
yumdownloader --source PACKAGENAME


The auto-buildrequires package has a pair of nice tools for helping to figure out the proper BuildRequires entries.  After installing this package, replace "rpmbuild" with "auto-br-rpmbuild" and you'll see an automatically-generated buildrequires list.
The <code>auto-buildrequires</code> package has a pair of nice tools for helping to figure out the proper BuildRequires entries.  After installing this package, replace "<code>rpmbuild</code>" with "<code>auto-br-rpmbuild</code>" and you'll see an automatically generated BuildRequires list.


You might find [http://rust.sourceforge.net/ RUST] useful (GPL).
You might find [http://rust.sourceforge.net/ RUST] useful (GPL), though it does not create SPEC files of suitable quality for Fedora packages. [http://kitenet.net/~joey/code/alien/ Alien] converts between package formats. It won't produce clean SRPMS, but converting an existing package might provide helpful information.
It is "a drag &amp; drop RPM creation GUI and a 'sandboxing' toolkit that allows you to do software installations within a chrooted environment and automatically generate RPMs from arbitrary source code, without ever seeing a spec file."
If you're creating spec files, it can help you determine the %files.
Note, however, that it does not create .spec files, nor does it create packages of adequate quality for the Fedora repository; it is primarily a tool for making quick-and-dirty binary RPM packages.
(Note: it is no longer at "rusthq.com".)


[http://kitenet.net/~joey/code/alien/ Alien] converts between package formats.
Finally, [https://github.com/alanfranz/docker-rpm-builder docker-rpm-builder] (APL 2.0) uses [http://www.docker.com Docker] to build RPM packages; while using rpmbuild requires building on the same host distro as the target, and mock works fine on Fedora/Centos/RHEL distributions for any target, '''this last tool works fine whenever Docker can run'''.
It won't produce clean source RPMs, but converting an existing package
 
might provide helpful information.
If you want to build your package for diferent distribution and architectures and to have publicly accesible yum repository, you can submit your src.rpm to [https://copr.fedoraproject.org Copr].


== Guidelines and rules ==
== Guidelines and rules ==


When you create your packages, you'll need to follow the following rules and guidelines:
When you create your packages, you'll need to follow the following rules and guidelines:
* [[Join the package collection maintainers| How to join the Fedora Package Collection Maintainers]] - describes the process for becoming a Fedora package maintainer
* [[Join the package collection maintainers|How to join the Fedora Package Collection Maintainers]]
* [[Packaging:Guidelines | Packaging Guidelines]]
* [[Packaging:Guidelines|Packaging Guidelines]]
* [[Packaging:NamingGuidelines| Package Naming Guidelines]]  
* [[Packaging:NamingGuidelines|Package Naming Guidelines]]
* [[Packaging:DistTag| Dist Tag Guidelines]]  
* [[Packaging:LicensingGuidelines|Package Licensing Guidelines]]
* [[Packaging:ReviewGuidelines| Package Review Guidelines]]
* [[Packaging:DistTag|Dist Tag Guidelines]]  
* [[Packaging:ReviewGuidelines|Package Review Guidelines]]
 
There are many official guidelines that will help you with specific circumstances (e.g. Java programs, OCaml programs, GNOME programs). You can also learn more from the [[SIGs]] and [[:Category:Package Maintainers|Package Maintainers]] sections.


There are many official guidelines that will help you with specific circumstances
(Java programs, OCaml programs, GNOME programs, etc.); the
[[Packaging:Guidelines|Packaging Guidelines]] include cross-references to those guidelines.
You can also learn more from the [[SIGs]] and
[[:Category:Package Maintainers|Package Maintainers]] sections.
[https://fedoraproject.org/wiki/Special:Prefixindex/Packaging You can also see the list of all Wiki pages about Packaging] to see if any apply.
[https://fedoraproject.org/wiki/Special:Prefixindex/Packaging You can also see the list of all Wiki pages about Packaging] to see if any apply.


Failing that, you might find some useful recommendations in the unofficial
Failing that, you might find some useful recommendations in the unofficial [https://fedoraproject.org/wiki/Special:Search?ns0=1&search=PackagingDrafts%2F&searchx=Search Packaging Drafts] and [[PackagingDrafts|Packaging Drafts To Do]].
[https://fedoraproject.org/wiki/Special:Search?ns0=1&search=PackagingDrafts%2F&searchx=Search Packaging Drafts] and [https://fedoraproject.org/wiki/PackagingDrafts Packaging Drafts To Do].
 
These are unofficial, obviously.
You might find ideas from [http://en.opensuse.org/Packaging SuSE],
You might find ideas from [http://en.opensuse.org/Packaging SuSE],
[http://www.debian.org/doc/debian-policy/ Debian], but
[http://www.debian.org/doc/debian-policy/ Debian], but
[http://www.mail-archive.com/distributions@lists.freedesktop.org/msg00156.html distributions differ in their rules], so do not presume they can be used directly.
[http://www.mail-archive.com/distributions@lists.freedesktop.org/msg00156.html distributions differ in their rules], so do not presume they can be used directly.


The .spec files that you create must be open source software, as noted in the
'''The .spec files that you create must be open source software, as noted in the [[Legal:Fedora_Project_Contributor_Agreement|FPCA]].'''
[http://fedoraproject.org/wiki/Legal/Licenses/CLA CLA].


== Maintaining the package ==
== Maintaining the package ==


Once your package is accepted, you (or your co-maintainers) need to maintain it.
Once your package has been accepted, you and your co-maintainers will need to maintain it. See [[Package update HOWTO]] and [[Package update guidelines]]. If you update the version in multiple releases of Fedora, do it backwards in time (e.g. release for Fedora N, then once that's accepted, Fedora N-1). The system presumes that later versions of Fedora have the same or later versions of programs.
See the [[Package update HOWTO]] and [[Package update guidelines]] for more information.
If you update the version in multiple releases of Fedora, do it "backwards" in time, e.g.,
release for Fedora N, then once that's accepted, Fedora N-1
(the system presumes that later versions of Fedora have the same or later versions of programs).


Encourage the upstream developers to use standard source code release conventions. Using standard conventions makes packaging ''much'' easier. For more information, see:
Encourage the upstream developers to use standard source code release conventions. Using standard conventions makes packaging much easier. For more information, see:
* [http://www.dwheeler.com/essays/releasing-floss-software.html Releasing Free/Libre/Open Source Software (FLOSS) for Source Installation] (a quick summary)
* [http://www.dwheeler.com/essays/releasing-floss-software.html Releasing Free/Libre/Open Source Software (FLOSS) for Source Installation] (a quick summary)
* [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]
Line 914: Line 773:
* [http://offog.org/articles/packaging/ Packaging Unix software]
* [http://offog.org/articles/packaging/ Packaging Unix software]


== For more information ==
== 其他資訊 ==


The [[:Category:Package Maintainers|Package Maintainers]] page links to many other useful pages, and the
[[:Category:Package Maintainers|軟體包維護者]] 頁面可連結到許多好用網頁,而
[[Package update HOWTO]] describes how to update an existing package you already maintain in Fedora.
[[Package update HOWTO]] 描述如何在 Fedora 中維護並更新既有的軟體包。


For more information, outside of the Fedora Wiki, see:
For more information, outside of the Fedora Wiki, see:
Line 926: Line 785:
* [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/drafts/rpm-guide-en/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/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://genetikayos.com/code/repos/rpm-tutorial/trunk/rpm-tutorial.html RPM Tutorial (Fullhart)]
* [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] by Dawson
* [http://home.fnal.gov/~dawson/rpms/howto/index.html RPM HowTo by Dawson]
* [http://en.opensuse.org/SUSE_Build_Tutorial SuSE build tutorial] - but about SuSE, not Fedora. [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://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://www.mandrivaclub.com/xwiki/bin/view/KB/MandrivaRpmHowTo alt]) 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://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)
Line 943: Line 801:
[http://lwn.net/Articles/236029/ lwn.net has a brief article] about this.
[http://lwn.net/Articles/236029/ lwn.net has a brief article] about this.


[[Category:Package Maintainers]][[Category:How to]]
[[Category:Package Maintainers]]
[[Category:How to]]


[[Category: Zh]]
[[Category:Zh]]
[[Category:Zh/Translation]]

Revision as of 14:35, 13 March 2015

翻譯: Caius 'kaio' ChanceCheng-Chia Tseng

簡介

本頁旨在詳細解說製作 RPM 軟體包的方法,特別是指製作 SPEC 檔的方法。不像其他的 RPM 教學指引,本頁有針對 Fedora 的規格作解說,並附上 Fedora 專用的規約 (guideline) 連結。由於本頁內容是以 Fedora Wiki 系統作維護,比起其他教學指引可能資訊還新一些。除了專注於 Fedora 的部份之外,文件中的大部份內容都能用於其他採用 RPM 作為軟體包管理系統的 Linux 散布版。如果你覺得按耐不住了,你可以改看較簡短的 如何製作 RPM 軟體包

目前 Fedora 文件已發行一份給打包者遵守的草擬規約,請見 Packagers Guide

請注意本篇內文並非 Fedora 官方軟體包的規約 打包委員會 才是處理 Fedora 中軟體打包守則與規約的組織。其中最重要的是:

Packaging GuidelinesPackage Naming Guidelines 皆是 Fedora 打包的主要規約。本頁的內容應與規約相容。

若你打算為 Fedora 軟體庫製作個 RPM 軟體包,請遵循 Join the package collection maintainers 中的步驟來做。

準備系統

在你為 Fedora 建立 RPM 軟體包之前,你需要安裝一些核心開發工具,並設置你會用到的帳號:

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

你可以特別為 RPM 軟體包的製作建立個傻瓜使用者 (dummy user),以避免建置程序出錯摧毀你的檔案,或將私人金鑰傳給全世界。

Stop (medium size).png
你「永遠」都不該以 root 使用者的身份製作 RPM 軟體包。用 root 帳號建置 RPM 非常危險,因為軟體在打包之前就會將二進位檔安裝在系統之中,所以你必須總是使用一般使用者來建置,以免意外污染你的系統。

建立一位名為 makerpm 的傻瓜使用者,將使用者加入 'mock' 群組中,設定個密碼,並以該位使用者身份登入:

# /usr/sbin/useradd makerpm
# usermod -a -G mock makerpm
# passwd makerpm

一旦你以建置用假使用者登入後,在你的家屋目錄中執行以下指令來建立需要的目錄結構:

$ rpmdev-setuptree

rpmdev-setuptree 程式會建立 ~/rpmbuild 目錄與一組子目錄 (例:SPECSBUILD),你將利用它們製作軟體包。同時也會建立 ~/.rpmacros 檔,可用來設定許多選項。

打包規約建議保留檔案的時間戳記;如果你使用 wgetcurl 下載源碼檔案的話,你可以讓程式自動保留時間戳記。如你使用 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#LegalLicensing:Main、和 Packaging:LicensingGuidelines。 通常來說,只有以核可的開源軟體 OSS 授權 (例如 GPL、LGPL、BSD-new、MIT/X、或 Apache 2.0 等授權) 發行的軟體可以打包。 請確認軟體真的以這種方式授權 (例如:查看源碼的標頭、README 檔等等)。 如果軟體有綁函式庫,請確認這些函式庫也是採用 OSS 授權。

重複使用既有的軟體包資訊

盡可能重複使用。例如,請確認你想打包的不是早就有人打包過的東西。你可以從 Fedora Package Collection Fedora Package Database 中找到既有軟體包的清單。

也請查看 In Progress Review RequestsRetired Packages 清單。你可以直接使用 Fedora Packages Git Repositories 來檢視 SPEC 檔 (與修補檔)。你可以使用 <cod> yum-utils 軟體來下載 SRPMS:

# yum -y install yum-utils
$ yumdownloader --source sourcepackage-name

另外,也可手動從 Fedora mirror http/ftp 網頁下的 releases/39/Everything/source/SRPMS 目錄取得源碼軟體包。請將「39」替換成你想要使用的 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 FindPKGS.org 可以幫你找到一些非 Fedora 系統的 RPM。你可以安裝其他系統的 SRPM,就像安裝 Fedora 的 SRPM 一樣。若找不到可以利用的軟體包,你或許可以參考看看給 UbuntuDebian 用的源碼軟體包 (不是 .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 檔概覽

其他有用的指引:

你需要遵守 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」就算了)。請見 LicensingLicensing Guidelines。你可以用「and」以及「or」來合併列出多種授權 (例如:「GPLv2 and BSD」)。
  • URL: 有關該程式更多資訊的完整 URL (例如該程式的專案網站)。 注意:這不是原本源碼的來源 URL,源碼封存檔的來源 URL 應該用下列的 Source0
  • Source0:包含 (原始) 元初源碼的壓縮後封存檔的完整 URL,即上游發行該源碼的位置。「Source」與「Source0」同義。如果你給的是完整的 URL (而且你也該這麼做),會用其基礎名稱去查找 SOURCES 目錄。如果可以的話,請用 %{name}%{version} 替換嵌入 URL 中,這樣只要有所變動時都會自動對應。下載源碼檔案時記得保留時間戳記。如果不只有一份源碼封存檔,請用 Source1Source2 等等依序羅列。如果你要在元初來源外還要再加一些全新的檔案,請將它們列在元初來源之後。任何你製作出的 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),但請注意有些應用程式若沒有某功能相關的依賴項目時,會永久停用該功能;這些情況中你可能需要納入額外的軟體包。 Package-x-generic-16.pngauto-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-libsname-devel 等軟體包。

Stop (medium size).png
「不要」使用這些標籤
  • Packager
  • Vendor
  • Copyright

不要製作「relocatable」可重新變換位置的軟體包;他們不會幫 Fedora 加值,反而把事情搞得更複雜。

SPEC 檔區段詳解

The %prep section describes how to unpack the compressed packages so that they can be built. Typically, this includes the "%autosetup" command. Alternatively, you can use "%setup" and "%patch" commands with reference to the Source0 (and Source1 etc.) lines. See the Maximum RPM section on %setup and %patch for more details.

The %{patches} and %{sources} macros are available since RPM 4.4.2 and are useful if you have a large list of patches or sources and %autosetup is not what you want, then you can do:

for p in %{patches}; do
    ...
done

However, keep in mind that using these will make your SPEC incompatible with RPMS used in RHEL and other RPM-based dirstributions.

%prep 區段:%autosetup 指令

The "%autosetup" command unpacks a source package. Switches include:

  • -n name : If the Source tarball unpacks into a directory whose name is not the RPM name, this switch can be used to specify the correct directory name. For example, if the tarball unpacks into the directory FOO, use "%autosetup -n FOO".
  • -c name : If the Source tarball unpacks into multiple directories instead of a single directory, this switch can be used to create a directory named name and then unpack into it.

If you use "%setup" command instead, then -q' is commonly used to suppress unecessary output.

There are more %spec options if you are unpacking multiple files, which is primarily useful if you are creating subpackages (see below). The key ones are:

-a number Only unpack the Source directive of the given number after changing directory (e.g. "–a 0" for Source0).
-b number Only unpack the Source directive of the given number before changing directory (e.g. "–b 0" for Source0).
-D Do not delete the directory before unpacking.
-T Disable the automatic unpacking of the archives.

%prep 區段:%patch 指令

If you have used "%autosetup" command, the following manual patch management is not necessary. If you have complex requirements or need compatibility with EPEL, you may still need this. The "%patch0" command applies Patch0 (and %patch1 applies Patch1 etc.). Patches are the normal method of making necessary changes to the source code for packaging. The usual "-pNUMBER" option applies, which passes that argument onto the program patch.

Patch file names often look like "telnet-0.17-env.patch", which is the format %{name} - %{version} - REASON.patch" (though sometimes version is omitted). Patch files are typically the result of "diff -u"; if you do this from the subdirectory of ~/rpmbuild/BUILD then you won't have to specify a -p level later.

This is a typical procedure for creating a patch for a single file:

cp foo/bar foo/bar.orig
vim foo/bar
diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch

If editing many files, one easy method is to copy the whole subdirectory underneath BUILD and then do subdirectory diffs. After you have changed directory to "~rpmbuild/BUILD/NAME", do the following:

cp -pr ./ ../PACKAGENAME.orig/
... many edits ...
diff -ur ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/NAME.REASON.patch

If you edit many files in one patch, you can also copy the original files using some consistent ending such as ".orig" before editing them. Then, you can use "gendiff" (in the rpm-build package) to create a patch with the differences.

Try to ensure that your patch match the context exactly. The default "fuzz" value is "0", requiring matches to be exact. You can work around this by adding "%global _default_patch_fuzz 2" to revert to the value found in older versions of RPM in Fedora, but it is generally recommended to avoid doing this.

As explained in Packaging/PatchUpstreamStatus, all patches should have a comment above them in the SPEC file about their upstream status. This should document the upstream bug/email that includes it (including the date). If it is unique to Fedora, you should mention why it is unique. The Fedora Project tries not to deviate from upstream; see PackageMaintainers/WhyUpstream for the importance of this.

%prep 區段:未修改的檔案

有時候,來源的一個或多個檔案並不需要解壓縮。你可以「prep」準備這些項目到建置目錄中,如 (這裡的 SOURCE1 代表對應的來源檔):

cp -p %SOURCE1 .

%build 區段

The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.

Many programs follow the GNU configure approach (or some variation). By default, they will install to a prefix of "/usr/local", which is reasonable for unpackaged files. However, since you are packaging it, change the prefix to "/usr". Libraries should be installed to either /usr/lib or /usr/lib64 depending on the architecture.

Since GNU configure is so common, the macro "%configure" can be used to automatically invoke the correct options (e.g. change the prefix to /usr). Some variation of this often works:

 %configure
 make %{?_smp_mflags}

To override makefile variables, pass them as parameters to make:

make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}

More more information, see "GNU autoconf, automake, and libtool" and "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer.

Some programs use cmake. See Packaging/cmake.

%install 區段

This section involves script commands to "install" the program, copying the relevant files from %{_builddir} to %{buildroot} (which usually means from ~/rpmbuild/BUILD to ~/rpmbuild/BUILDROOT) and creating directories inside %{buildroot} as necessary.

Some of the terminology can be misleading:

  • The "build directory", also known as %{_builddir} is not the same as the "build root", also known as %{buildroot}. Compilation occurs in the former directory, while files to be packaged are copied from the former to the latter.
  • During the %build section, the current directory will start at %{buildsubdir}, which is the subdirectory within %{_builddir} that was created during %prep stage. This is usually something like ~/rpmbuild/BUILD/%{name}-%{version}.
  • The %install section is not run when the binary RPM package is installed by the end-user, but is only run when creating a package.

Normally, some variation of "make install" is performed here:

%install
rm -rf %{buildroot} # redundant except for RHEL 5
%make_install

Ideally you should use %make_install which is equivalent to DESTDIR=%{buildroot} if the program supports it, as it redirects file installations to the specified directory and is exactly what we want to happen during the %install section.

If the program does not support DESTDIR (and only if), you can workaround it in one of several (inferior) ways:

  • Patch the makefile so that is supports DESTDIR. Create directories inside DESTDIR where necessary and submit the patch upstream.
  • Use the "%makeinstall" macro. This method might work, but can lead to subtle failures. It expands to something like "make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install", which can result in some programs failing to work properly. Create directories inside %{buildroot} where necessary.
  • Consider using the auto-destdir package. This requires "BuildRequires: auto-destdir", and changing "make install" to "make-redir DESTDIR=%{buildroot} install". This only works well if the installation uses only certain common commands to install files, like cp and install.
  • Perform the installation by hand. This would involve creating the necessary directories under %{buildroot} and copying files from %{_builddir} to %{buildroot}. Be especially careful with updates, which often contain new or changed filenames. An example of this procedure:
%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 基礎

The %defattr sets the default file permissions, and is often found at the start of the %files section. Note that this is no longer necessary unless the permissions need to be altered. The format of this is:

%defattr(<file permissions>, <user>, <group>, <directory permissions>)

The fourth parameter is often omitted. Usually one uses %defattr(-,root,root,-), where "-" uses the default permissions.

You should then list all the files and directories to be owned by the package. Use macros for directory names where possible, which can be viewed at Packaging:RPMMacros (e.g. use %{_bindir}/mycommand instead of /usr/bin/mycommand). If the pattern begins with a "/" (or when expanded from the macro) then it is taken from the %{buildroot} directory. Otherwise, the file is presumed to be in the current directory (e.g. inside %{_builddir}, such as documentation files that you wish to include). If your package only installs a single file /usr/sbin/mycommand, then the %files section can simply be:

%files
%{_sbindir}/mycommand

To make your package less sensitive to upstream changes, declare all files within a directory to be owned by the package with a pattern match:

%{_bindir}/*

To include a single directory:

%{_datadir}/%{name}/

Note that %{_bindir}/* does not claim that this package owns the /usr/bin directory, but only the files contained within. If you list a directory, then you are claiming that the package owns that directory and all files and subdirectories contained within. Thus, do not list %{_bindir} and be careful of directories that may be shared with other packages.

An error will occur if:

  • a pattern match does not match any file or directory
  • a file or directory is listed or matched more than once
  • a file or directory in the %{buildroot} has not been listed

It is also possible to exclude files from a previous match by using the %exclude glob. This can be useful for including almost all of the files included by a different pattern match, but note that it will also fail if it does not match anything.

%files prefixes

You may need to add one or more prefixes to lines in the %files section; seperate them with a space. See Max RPM section on %files directives.

Usually, "%doc" is used to list documentation files within %{_builddir} that were not copied to %{buildroot}. A README and INSTALL file is usually included. They will be placed in an appropriate directory under /usr/share/doc, whose ownership does not need to be declared.

Note: If specifying a %doc entry, rpmbuild < 4.9.1 removes the doc directory it installs files into before installing them. This means that files already in it, for example installed in the %install section, are removed and do not end up in the package. If you want to install some files in the %install section, install them into a temporary staging directory inside the build dir (not build root), for example _docs_staging, and include them in the in the %files list like %doc _docs_staging/*.

Configuration files should be placed in /etc and are normally specified like this (which makes sure user changes aren't overwritten on update):

%config(noreplace) %{_sysconfdir}/foo.conf

If the update uses a non-backwards-compatible configuration format, then specify them like this:

%config %{_sysconfdir}/foo.conf

"%attr(mode, user, group)" can be used for finer control over permissions, where a "-" means use the default:

%attr(0644, root, root) FOO.BAR

If a file is in particular natural language, use %lang to note that:

%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*

Programs using Locale files should follow the recommended method of handling i18n files:

  • 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

These prefixes are not valid in Fedora: %license and %readme.

%files and Filesystem Hierarchy Standard (FHS)

You should follow the Filesystem Hierarchy Standard (FHS). Executables go in /usr/bin, global configuration files go in /etc, libraries go into /usr/lib (or /usr/lib64) and so on. There is one exception: executables that should not normally be executed directly by users or administrators should go in a subdirectory of /usr/libexec, which is referred to as %{_libexecdir}/%{name}.

Do not install files into /opt or /usr/local.

Unfortunately, many programs do not follow the FHS by default. In particular, architecture-independent libraries get placed in /usr/lib instead of /usr/share. The former is for architecture-dependent libraries, while the latter is for architecture-independent libraries, which means that systems with different CPU architectures can share /usr/share. There are many exceptions in Fedora (such as Python and Perl), but Fedora applies this rule more strictly than some distributions. rpmlint will generally complain if you put anything other than ELF files into /usr/lib.

%files example

Here's a simple example of a %files section:

%files
%doc README LICENSE
%{_bindir}/*
%{_sbindir}/*
%{_datadir}/%{name}/
%config(noreplace) %{_sysconfdir}/*.conf

Finding duplicates

You can list any duplicates of two binary packages by doing:

cd ~/rpmbuild/RPMS/ARCH # Substitute "ARCH" for your architecture
rpm -qlp PACKAGE1.*.rpm | sort > ,1
rpm -qlp PACKAGE2.*.rpm | sort > ,2
comm -12 ,1 ,2

Scriptlets

When an end-user installs the RPM, you may want some commands to be run. This can be achieved through scriptlets. See Packaging/ScriptletSnippets.

Scriptlets can be run:

  • before (%pre) or after (%post) a package is installed
  • before (%preun) or after (%postun) a package is uninstalled
  • at the start (%pretrans) or end (%posttrans) of a transaction

For example, every binary RPM package that stores shared library files in any of the dynamic linker's default paths, must call ldconfig in %post and %postun. If the package has multiple subpackages with libraries, each subpackage should also perform the same actions.

%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig

If only running a single command, then the "-p" option runs the adjacent command without invoking the shell. However, for several commands, omit this option and include the shell commands beneath.

If you run any programs within the scriptlets, then you must specify any requirements in the form "Requires(CONTEXT)" (e.g. Requires(post)).

%pre, %post, %preun, and %postun provide the argument $1, which is the number of packages of this name which will be left on the system when the action completes. Don't compare for equality with 2, but instead check if they are greater than or equal to 2. For %pretrans and %posttrans, $1 is always 0.

For example, if the package installs an info manual, then the info manual index must be updated with install-info from the info package. Firstly, there is no guarantee that the info package will be available unless we explicitly declare it as required, and secondly, we don't want to fail completely if install-info fails:

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

There is one other glitch related to installing info manuals. The install-info command will update the info directory, so we should delete the useless empty directory from the %{buildroot} during the %install section:

rm -f %{buildroot}%{_infodir}/dir

Another scriptlet-like ability are "triggers", which can be run for your package when other packages are installed or uninstalled. See RPM Triggers.

Macros

Macros are text in the format %{string}. Typical macros:

Macro Typical Expansion Meaning
%{_bindir} /usr/bin Binary directory: where executables are usually stored.
%{_builddir} ~/rpmbuild/BUILD Build directory: files are compiled within a subdirectory of the build directory. See %buildsubdir.
%{buildroot} ~/rpmbuild/BUILDROOT Build root: where files are "installed" during the %install stage, which copies files from a subdirectory of %{_builddir} to a subdirectory of %{buildroot}. (Historically, %{buildroot} was in "/var/tmp/".)
%{buildsubdir} %{_builddir}/%{name} Build subdirectory: a subdirectory within %{_builddir} where files are compiled during the %build stage. It is set after %autosetup.
%{_datadir} /usr/share Share directory.
%{_defaultdocdir} /usr/share/doc Default documentation directory.
%{dist} .fcNUMBER Distribution+version short name (e.g. ".fc39")
%{fedora} NUMBER Number of fedora release (e.g. "39")
%{_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 of package, set by Name: tag
%{_sbindir} /usr/sbin
%{_sharedstatedir} /var/lib
%{_sysconfdir} /etc
%{version} Version of package, set by Version: tag

Learn more about macros by looking in /etc/rpm/* and /usr/lib/rpm, especially /usr/lib/rpm/macros. Also use rpm --showrc to show values that RPM will use for macros (altered by rpmrc and macro configuration files).

You can set your own macro values using %global, but be sure to define them before you use them. (Macro definitions can also refer to other macros.) For example:

%global date 2012-02-08

Use the "-E" option of rpmbuild to find the value of a macro in a SPEC file:

rpmbuild -E '%{_bindir}' myfile.spec

Also see Packaging/RPMMacros and RPM Guide chapter 9.

Other tags

In addition to Requires and BuildRequires tags, you can also use these for controlling dependencies:

  • Provides: list virtual package names that this package provides. For example, there might be a package "foo" that demands a particular functionality "bar" from another program. If there are several packages that can satisfy that demand, those packages can specify "Provides: bar" and the "foo" package can specify "Requires: bar". You could also use the "alternatives" system, but avoid if multiple users on the same system might want different default, as these settings are system-wide. Use "rpm -q --provides PACKAGENAME" to see what a given package provides. Some examples of virtual packages in Fedora:
    • MTA: Used for mail transport agents, such as sendmail.
    • tex(latex): Used for latex
  • Obsoletes: remove another named package(s) when this package is installed. Use when the package name changes or when it totally replaces a different package.
  • Conflicts: state what other packages cannot be installed simultaneously to this one. Avoid this if you can. See Packaging/Conflicts.
  • BuildConflicts: state what packages cannot be installed when building this package. Avoid this if you can.

To manage different architectures, there are two tags:

  • ExcludeArch: to exclude an architecture on which the package doesn't build. For example:
ExcludeArch: ppc
  • ExclusiveArch: to include only the specified architecture. Avoid this unless absolutely correct.

Valid architectures are listed at Architectures.

Subpackages

A SPEC file can define several binary package. In other words, one SRPM with one SPEC file can result in several RPMS. Note that there is still only one creation (%prep, %build, %install etc.) process. name-doc and name-devel subpackages are common for documentation and development files respectively.

Use the %package directive to start defining a subpackage:

%package subpackage_name

After each %package directive, list the tags for the subpackage. This should at least include the Summary and Group tags, as well as the %description subpackage_name and %files subpackage_name directives:

Anything not specified by the subpackage will be inherited from its parent.

By default, if the package name is "foo" and the subpackage name is "bar", then the resulting subpackage will be "foo-bar". You can override it with the "-n" option (but you'll need to use it in all other directives too if you specify it here):

%package -n new_subpackage_name

See the RPM Guide section on subpackages for more information.

Conditionals

You can insert conditional statements, for example to test if you are creating a binary for a certain architecture:

%ifarch ARCHITECTURE_NAME

the negated version with:

%ifnarch ARCHITECTURE_NAME

or the more general conditional:

%if TRUE_OR_FALSE

There is an optional "%else" section; all of these are closed with "%endif".

Application Specific Guidelines

There are many application-specific guidelines that can help you (e.g., for specific programming languages, applications, libraries, and build systems). Many of them are listed as part of the Application Specific Guidelines of Packaging/Guidelines. Examples of application-specific guidelines are those for:

Failing that, some other ways of finding application-specific help are:

Miscellaneous hints

Packaging/FrequentlyMadeMistakes has information on frequently-made mistakes. There are also some recommendations and controversial tricks on PackageMaintainers/Packaging Tricks.

Try to write your SPEC files so that it is likely to work when a new release is made upstream, without any changes aside from bumping the version number and refreshing the source files. For example, if it contains *.txt files with execute bits, instead of doing

 chmod a-x Filename1.txt Filename2.txt Filename3.txt

consider doing this, which will handle new filenames that use the same file naming convention:

 chmod a-x *.txt

If you want to see lots of examples of scriptlets, you can show all the scriptlets on installed programs using:

 rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less

Don't try to interact with the user; RPM is designed to support batch installs. If an application needs to show a EULA, that needs to be part of its initial execution, not its installation.

You might not want to start services, because in a big install that could slow things down. If you install an init or systemd script, consider using chkconfig or systemctl to arrange for the service to be started/stopped on the next reboot. Before uninstalling, you should normally try to stop its services if they are running.

Uninstalling should reverse most changes made during installation, but don't remove any user-created files.

Normally, if there are binary executables, then debugging symbols are stripped from the normal binary packages and placed into a name-debug subpackage. If this shouldn't happen, you can disable the stripping and creation of this subpackage by putting this at the top of your SPEC:

%global _enable_debug_package 0
%global debug_package %{nil}
%global __os_install_post /usr/lib/rpm/brp-compress %{nil}

To prevent stripping you may also need to do this in the %install section:

export DONT_STRIP=1

A way to check for the version of Fedora in a SPEC file for conditional builds is:

%if 0%{?fedora} <= <version>

The ? causes the macro to evaluate to evaluate to blank if %fedora is not defined. This causes the end result to be the 0 (which is a number and thus fine), while not interfering with the result if there is actually a value for %fedora. (Note that this trick does not work in Koji "scratch" builds, where %fedora is set during the creation of a SRPM.)

GUI programs must have a desktop entry so that people can invoke it from the graphical desktop menu. For .desktop files, see Fedora packaging guidelines for desktop files and desktop entry spec. For icons within /usr/share/icons, see icon theme spec.

Building the binary package

Test with rpmlint

To catch many common errors early, run rpmlint on your SPEC file before trying to build anything from it:

$ rpmlint program.spec

If the reported error doesn't make sense, run it again with the "-i" option for longer messages.

Aim to have no errors, but sometimes rpmlint reports false positives. The Fedora packaging guidelines explains which ones to ignore.

Create binary RPMS from the SPEC file

Once you've created your SPEC file, build the SRPM and binary RPMS by running this:

$ rpmbuild -ba program.spec

If successful, RPMS will be created within ~/rpmbuild/RPMS and SRPMS will be created within ~/rpmbuild/SRPMS.

If it fails, go to the appropriate directory and see what is left over. To help debug, you can skip earlier stages that succeeded with the "--short-circuit" option. For example, to restart at the %install stage (skipping earlier stages), do this:

$ rpmbuild -bi --short-circuit program.spec

If you just want to create an SRPM (which does not run the %prep or %build or other stages), run this:

rpmbuild -bs program.spec

Testing binary RPMS with rpmlint

rpmlint can be run on SPEC files, RPMS and SRPMS to check for errors. You need to eliminate or justify warnings before posting a package. This page offers explanations for some of the common issues that come up. If you are in the SPECS directory, do this:

$ rpmlint NAME.spec ../RPMS/*/NAME*.rpm ../SRPMS/NAME*.rpm

Enter the ~/rpmbuild/RPMS directory and into the architecture subdirectory. You will find some binary RPMS. Quickly see their files and permissions (to check whether they are correct) by doing:

$ rpmls *.rpm

If they look fine, install them as root:

# rpm -ivp package1.rpm package2.rpm package3.rpm ...

Test the programs in a few different ways to see if everything works correctly. If it is a GUI tool, make sure it shows up in the desktop menu, otherwise the .desktop entry is wrong.

Uninstall packages later by doing:

# rpm -e package1 package2 package3

Mock and Koji

Mock is a powerful tool that uses the SRPM you have created to build binary packages within a nearly empty environment. This can reveal if you have accurate build dependencies. If it fails, then you forgot to list something in BuildRequires. See Using Mock to test package builds. Once your account is a member of the "mock" group, you can run commands like this to do local testing:

$ mock -r fedora-9-i386 rebuild path_to_source_RPM

You can use Koji (which uses mock) to do builds on many different systems, some of which you may not have. PackageMaintainers/Join and PackageMaintainers/UsingKoji have more information about Koji. Once it's set up, you can test your SRPM on a variety of platforms by running commands like:

$ koji build --scratch dist-f9 path_to_source_RPM

Replace dist-f9 with any later release of Fedora, but don't use dist-rawhide. Remember, the values of %fedora, %fc9 and so on will not be correct for a scratch build, so this won't work if your SPEC file does something different based on those values.

Your Koji builds can only depend on packages that are actually in the TARGET distribution repository. Thus, you can't use Koji to build for released distributions if your package depends on other new packages that Bodhi hasn't released yet. If you need to build against a package that is not yet a stable released update, submit a Koji buildroot override request via Bodhi. If it's not your own package you depend on, contact its maintainer(s). [Before Bodhi could handle Koji buildroot override requests, the old method has been to file a ticket with rel-eng at: https://fedorahosted.org/rel-eng/newticket and request that that package be added as a buildroot override.]

Helpful tools

The rpmdevtools package has a number of helpful tools; "rpm -qil rpmdevtools" will show you what it installs.

  • rpmdev-bumpspec : bump the release tag in the spec file and add a changelog comment with the right date and version format:
rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES

The yum-utils package also has some useful tools:

  • yumdownloader : download the SRPM of the package by running:
yumdownloader --source PACKAGENAME

The auto-buildrequires package has a pair of nice tools for helping to figure out the proper BuildRequires entries. After installing this package, replace "rpmbuild" with "auto-br-rpmbuild" and you'll see an automatically generated BuildRequires list.

You might find RUST useful (GPL), though it does not create SPEC files of suitable quality for Fedora packages. Alien converts between package formats. It won't produce clean SRPMS, but converting an existing package might provide helpful information.

Finally, docker-rpm-builder (APL 2.0) uses Docker to build RPM packages; while using rpmbuild requires building on the same host distro as the target, and mock works fine on Fedora/Centos/RHEL distributions for any target, this last tool works fine whenever Docker can run.

If you want to build your package for diferent distribution and architectures and to have publicly accesible yum repository, you can submit your src.rpm to Copr.

Guidelines and rules

When you create your packages, you'll need to follow the following rules and guidelines:

There are many official guidelines that will help you with specific circumstances (e.g. Java programs, OCaml programs, GNOME programs). You can also learn more from the SIGs and Package Maintainers sections.

You can also see the list of all Wiki pages about Packaging to see if any apply.

Failing that, you might find some useful recommendations in the unofficial Packaging Drafts and Packaging Drafts To Do.

You might find ideas from SuSE, Debian, but distributions differ in their rules, so do not presume they can be used directly.

The .spec files that you create must be open source software, as noted in the FPCA.

Maintaining the package

Once your package has been accepted, you and your co-maintainers will need to maintain it. See Package update HOWTO and Package update guidelines. If you update the version in multiple releases of Fedora, do it backwards in time (e.g. release for Fedora N, then once that's accepted, Fedora N-1). The system presumes that later versions of Fedora have the same or later versions of programs.

Encourage the upstream developers to use standard source code release conventions. Using standard conventions makes packaging much easier. For more information, see:

其他資訊

軟體包維護者 頁面可連結到許多好用網頁,而 Package update HOWTO 描述如何在 Fedora 中維護並更新既有的軟體包。

For more information, outside of the Fedora Wiki, see:

Note: The rpm5.org site has some documentation, but do not depend on it; that is the home of a fork of RPM maintained by Jeff Johnson. The RPM used by Fedora (and Novell/SuSE) is instead based at rpm.org. lwn.net has a brief article about this.