From Fedora Project Wiki
m (internal link cleaning)
 
(29 intermediate revisions by 2 users not shown)
Line 295: Line 295:
== SPEC 檔區段詳解 ==
== SPEC 檔區段詳解 ==


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.
=== %prep 區段 ===


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:
%prep 區段描述的是如何解開壓縮後軟體包的方法,這樣才能拿來建置。一般而言,這包含「<code>%autosetup</code>」指令。另外,你可以使用「<code>%setup</code>」和「<code>%patch</code>」指令搭配參照 Source0 (與 Source1 等) 條目。請見 [http://rpm.org/max-rpm-snapshot/s1-rpm-inside-macros.html Maximum RPM 一文中的 %setup and %patch 小節] 瞭解更多細節。
 
RPM 4.4.2 起可以使用 %{patches} 和 %{source} 巨集,若你有大量補丁或來源清單,以及 %autosetup 效果並非你所想要的話會很好用,例如你可以這樣做:
  for p in %{patches}; do
  for p in %{patches}; do
     ...
     ...
  done
  done


However, keep in mind that using these will make your SPEC incompatible with RPMS used in RHEL and other RPM-based dirstributions.
然而請記住,使用上述功能,會讓你的 SPEC RHEL 以及其他 RPM 散布版中所使用的 RPMS 不相容。


==== %prep 區段:%autosetup 指令 ====
==== %prep 區段:%autosetup 指令 ====


The "<code>%autosetup</code>" command unpacks a source package. Switches include:
<code>%autosetup</code>」指令會解開來源軟體包。可用選項包括:
* '''<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>-n</code> ''name'' ''' :如果 Source tarball 所要解開成的目錄名稱與 RPM 名稱不同,這個切換開關用來指定正確的目錄名稱。舉例來說,如果 tarball 要解開成 FOO 目錄,則使用「<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.
* '''<code>-c</code> ''name'' ''' :如果 Source tarball 需要解開成多個目錄,而非單一個目錄時,這個切換開關可以用來建立名為 ''name'' 的目錄,然後將內容解開放在裡面。


If you use "<code>%setup</code>" command instead, then ''<code>-q</code>''' is commonly used to suppress unecessary output.
如我你改用「<code>%setup</code>」指令,則通常使用 ''<code>-q</code>''' 來抑止不必要的輸出。


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 有更多 %spec 選項可以用],這在你製作子軟體包時會很有用 (請見下方)。比較重要的有:
are creating subpackages (see below).  The key ones are:


{|
{|
|-
|-
| <code>-a number</code> || Only unpack the Source directive of the given number after changing directory (e.g. "<code>–a 0</code>" for Source0).
| <code>-a number</code> || 在切入目錄後,只解開指定數字的 Source 目錄 (例:「<code>–a 0</code>」代表 Source0)
|-
|-
| <code>-b number</code> ||  Only unpack the Source directive of the given number before changing directory (e.g. "<code>–b 0</code>" for Source0).
| <code>-b number</code> ||  在切入目錄前,只解開指定數字的 Source 目錄 (例:「<code>–b 0</code>」代表 Source0)
|-
|-
| <code>-D</code> || Do not delete the directory before unpacking.
| <code>-D</code> || 在解開之前不要刪除目錄。
|-
|-
| <code>-T</code> || Disable the automatic unpacking of the archives.
| <code>-T</code> || 停用自動解開封存檔。
|}
|}


==== %prep 區段:%patch 指令 ====
==== %prep 區段:%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>.
如果你用的是「<code>%autosetup</code>」指令,就不需要下列的手動補丁管理程序。如果你的需求很複雜,或是需要和 EPEL 相容,還是可能需要用到。「<code>%patch0</code>」指令會套用 Patch0 (%patch1 會套用 Patch1,依此類推)。補丁是對來源程式碼做出必要修改使之符合打包規約的正常作法。常用的「<code>-pNUMBER</code>」選項會傳遞引數給 <code>patch</code> 程式來套用對應補丁。


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.
補丁的檔名通常看起來像是「<code>telnet-0.17-env.patch</code>」這樣,命名格式依循「<code>%{name} - %{version} - REASON.patch</code>(不過有時候會省略 version 版本)。補丁檔通常是「<code>diff -u</code>」的成果;如果你是從if you do this from the subdirectory of <code>~/rpmbuild/BUILD</code> 的子目錄執行這個指令的,那麼你之後便不必指定 <code>-p</code> 層級。


This is a typical procedure for creating a patch for a single file:
這是為單一檔案製作補丁的典型程序:
  cp foo/bar foo/bar.orig
  cp foo/bar foo/bar.orig
  vim foo/bar
  vim foo/bar
  diff -u foo/bar.orig foo/bar > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
  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 <code>BUILD</code> and then do subdirectory diffs.  After you have changed directory to "<code>~rpmbuild/BUILD/NAME</code>", do the following:
如果需要修改許多檔案,有個簡單的方法,就是複製 <code>BUILD</code> 下的整個子目錄,然後執行子目錄的 diff。在你切入「<code>~rpmbuild/BUILD/NAME</code>」目錄後,執行以下指令:
  cp -pr ./ ../PACKAGENAME.orig/
  cp -pr ./ ../PACKAGENAME.orig/
  ... many edits ...
  ... 修改許多檔案 ...
  diff -ur ../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 "<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.
如果你想在一個補丁中編輯多重檔案,你也可以在編輯之前用同樣的檔名結尾「<code>.orig</code>」來複製原始檔案。然後,你可以用「<code>gendiff</code>(<code>rpm-build</code> 軟體包中) 製作檔案差異的補丁檔。
 
 
試著確保你的路徑完全符合情境。預設的「fuzz」值是「<code>0</code>」,代表比對要求完全相同。你可以加入「<code>%global _default_patch_fuzz 2</code>」來轉換成舊版 Fedora RPM 版本所採用的值,但我們建議你應盡量避免這樣做。


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.


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.
[[Packaging/PatchUpstreamStatus]] 所詳述的,SPEC 檔中所有的補丁上方都要有個註解描述它的目前上游狀態為何。如果這是 Fedora 特別需要的補丁,你應該提及為何它如此特別。Fedora 專案致力不與上游分歧;請見 [[PackageMaintainers/WhyUpstream]] 瞭解此事的重要性。


==== %prep 區段:未修改的檔案 ====
==== %prep 區段:未修改的檔案 ====
Line 355: Line 358:
=== %build 區段 ===
=== %build 區段 ===


The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.
%build」區段偶爾會有點複雜;在這個區段中你設置組態,並編譯/建置用來安裝的檔案。


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.
許多程式採用 GNU <code>configure</code> 的方法 (或據此變化)。預設情況下,檔案會安裝到前綴為「<code>/usr/local</code>」的路徑下,這對解開檔案的存放來說相當合理;但是,現在你是要打包程式,所以請將路徑前綴改成「<code>/usr</code>」。函式庫則應該視架構而定,安裝到 <code>/usr/lib</code> <code>/usr/lib64</code> 中。


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:
由於 GNU <code>configure</code> 非常常見,可以自動使用「<code>%configure</code>」巨集來喚起正確的選項 (例如,將前綴路徑改成 <code>/usr</code>)。有些變化也多能作用:
   %configure
   %configure
   make %{?_smp_mflags}
   make %{?_smp_mflags}


To override makefile variables, pass them as parameters to <code>make</code>:
若要凌駕 makefile 變數,請將它作為參數傳遞給 <code>make</code>
  make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}
  make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}


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].
至於其他深入資訊,請參見 [http://sourceware.org/autobook/ "GNU autoconf, automake, and libtool"] 以及 [http://www.suse.de/~sh/automake/automake.pdf "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer]


Some programs use <code>cmake</code>.  See [[Packaging/cmake]].
也有些程式使用 <code>cmake</code>。請參見 [[Packaging/cmake]]


=== %install 區段 ===
=== %install 區段 ===


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.
本區段內含「安裝」該程式用的指令稿指令,即從 <code>%{_builddir}</code> 資料夾複製相關檔案到 <code>%{buildroot}</code> (通常代表從 <code>~/rpmbuild/BUILD</code> 複製到 <code>~/rpmbuild/BUILDROOT</code>),並且根據需要在 <code>%{buildroot}</code> 中新建資料夾。


Some of the terminology can be misleading:
有些術語的名稱可能讓人會錯意:
* 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.
* 「建置目錄 build directory」,也稱為 <code>%{_builddir}</code>,實際上和「建置根基 build root」,又稱為 <code>%{buildroot}</code>,是不一樣的資料夾。我們會在前者中編譯,而要打包的檔案則從前者複製到後者去。
* 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>.
* %build 區段中,目前的目錄起始於 <code>%{buildsubdir}</code>,是 %prep 階段中在 <code>%{_builddir}</code> 下建立的子資料夾。這個資料夾名稱通常會是 <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 區段在終端使用者安裝二進位 RPM 軟體包時並 '''不會''' 執行 ;事實上 %install 區段只有在製作軟體包時才會執行。


Normally, some variation of "<code>make install</code>" is performed here:
一般來說,這裡執行的是「<code>make install</code>」之類的:
  %install
  %install
  rm -rf %{buildroot} # redundant except for RHEL 5
  rm -rf %{buildroot} # redundant except for RHEL 5
  %make_install
  %make_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.
理想上您應該使用 %make_install,對於支援的程式來說,它等同於 [http://www.gnu.org/prep/standards/html_node/DESTDIR.html <code>DESTDIR=%{buildroot}</code>],因為它會重新導引檔案安裝到指定的目錄中,也就是我們在 %install 區段中預期發生的事。
 
如果程式不支援 <code>DESTDIR</code>(且僅在有此情況之下),您有許多 (下方所列) 方式可以避開問題:


If the program does not support <code>DESTDIR</code> (and only if), you can workaround it in one of several (inferior) ways:
* 修補 makefile 來讓它支援 <code>DESTDIR</code>。在 <code>DESTDIR</code> 中視需要建立目錄,並提交該 patch 補丁給上游。
* Patch the makefile so that is supports <code>DESTDIR</code>. Create directories inside <code>DESTDIR</code> where necessary and submit the patch upstream.
* 使用「<code>%makeinstall</code>」巨集。這個方法可能有效,但也可能導致些微失敗。該巨集會展開成「<code>make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install</code>」,而可能導致有些程式無法正常運作。請在 <code>%{buildroot}</code> 下視需要建立目錄。
* 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.
* 考慮使用 <code>auto-destdir</code> 軟體包。它需要「<code>BuildRequires: auto-destdir</code>」、並將「<code>make install</code>」修改成「<code>make-redir DESTDIR=%{buildroot} install</code>」。這只在安裝僅使用到特定常用指令來安裝檔案時才能作用,例如 <code>cp</code> <code>install</code>
* 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>.
* 手動執行安裝。這可能牽涉到在 <code>%{buildroot}</code> 下建立必要的目錄,並從 <code>%{_builddir}</code> 複製檔案到 <code>%{buildroot}</code> 裡去。要特別注意更新,通常會有新檔名或修改過檔名。此程序的範例:
* 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 398: Line 402:
=== %check 區段 ===
=== %check 區段 ===


If self-tests are available, it is generally a good idea to include them. They should be placed in the %check section (which immediately follows the %install section, since files in %buildroot may be tested) instead of within the %build section itself, so that they can be easily skipped when necessary.
如果可以自我測試的話,將它們納入其中的話會是個好主意。他們應該放在 %check 區段中 (緊接在 %install 區段之後,因為應該測試 %buildroot 中的檔案) 而不是放在 %build 區段中,這樣才能在必要時刻輕易略過。


Often, this section contains:
通常,此區段包含:
  make test
  make test


Sometimes it can be:
有時候也可以用:
  make check
  make check


Please explore the Makefile and choose the appropriate way.
請探索一下 Makefile 的用法,並選擇適當的方式。


=== %files 區段 ===
=== %files 區段 ===
此區段宣告哪些檔案與目錄是由該軟體包擁有,還有哪些檔案與目錄會放到二進位檔 RPM 中。
此區段宣告哪些檔案與目錄是由該軟體包擁有,還有哪些檔案與目錄會放到二進位檔 RPM 中。


==== %files 基礎 ====
==== %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:
<code>%defattr</code> 會設定預設的檔案權限,通常可以在 <code>%files</code> 區段的開頭看到使用。請注意到,如果不需要修改權限的話,那就不再需要用到它。它的使用格式為:
  %defattr(<file permissions>, <user>, <group>, <directory permissions>)
  %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.
第四個參數通常會省略。通常我們會這樣用 <code>%defattr(-,root,root,-)</code>,其中「<code>-</code>」代表預設權限。


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:
您應該列出該軟體包擁有的所有檔案和目錄。請盡量用巨集來取代目錄名稱,您可以到 [[Packaging:RPMMacros]] (舉例:使用 <code>%{_bindir}/mycommand</code> 取代 <code>/usr/bin/mycommand</code>) 來查看巨集表。如果起頭樣式為「<code>/</code>(或從巨集擴展而來),則從 <code>%{buildroot}</code> 目錄取用。否則,將假定檔案位在目前的目錄中 (例如:在 <code>%{_builddir}</code> 內部,例如您想要納入的文件檔)。若您的軟體包僅安裝單一檔案如 <code>/usr/sbin/mycommand</code>,則 <code>%files</code> 區段可以像這樣簡單:
  %files
  %files
  %{_sbindir}/mycommand
  %{_sbindir}/mycommand


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}/*


To include a single directory:
若要納入單一目錄:
  %{_datadir}/%{name}/
  %{_datadir}/%{name}/


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.
請注意,<code>%{_bindir}/*</code> 並不會宣稱此軟體包擁有 <code>/usr/bin</code> 目錄,而只有包含其下的檔案。如果您列出一個目錄,則您正試圖宣稱該軟體包擁有這個目錄,以及該目錄內的所有檔案與子目錄。所以,請 '''不要''' 列出 <code>%{_bindir}</code>,而且要小心處理那些可能和其他軟體包共享的目錄。


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
* 沒有列出 <code>%{buildroot}</code> 下的某個檔案或目錄


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.
您也可以使用 <code>%exclude</code> glob 來從前個比對中排除檔案。這對於想用不同的樣式比對來將幾乎全部檔案納入其中時會很有用,但是請注意如果沒有比對到任何東西也會造成失敗。


==== %files prefixes ====
==== %files 前綴字 ====
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].
您可能需要在 <code>%files</code> 區段的內容中加入一個或多個前綴字;請用空格隔開。請見 [http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html Max RPM section on %files directives]


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.
通常,「<code>%doc</code>」用來列出 <code>%{_builddir}</code> 內,但未複製到 <code>%{buildroot}</code> 中的文件檔。通常包括 <code>README</code> <code>INSTALL</code> 檔。它們會放到 <code>/usr/share/doc</code> 下適當的目錄中,而 <code>/usr/share/doc</code> 的擁有權不必宣告。


'''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>.
'''注意:''' 如果有指定 <code>%doc</code> 條目,rpmbuild < 4.9.1 在安裝之前會將檔案安裝到其中的 doc 文件目錄移除。這代表已經放到裡面去的檔案,例如,在 <code>%install</code> 區段中安裝的檔案,會被移除,因此最終不會出現在軟體包中。如果您想要在 <code>%install</code> 區段中安裝一些檔案,請將它們安裝到建置目錄 (是 build dir,而不是建置根基 build root) 內的暫時鄰架目錄 (temporary staging directory) 中,例如 <code>_docs_staging</code>,接著將之納入 <code>%files</code> 列表中,如 <code>%doc _docs_staging/*</code> 這樣。


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):
組態檔應該要放在 <code>/etc</code> 中,一般會這樣指定 (可以確保使用者所作的更動不會在更新時被覆蓋)
  %config(noreplace) %{_sysconfdir}/foo.conf
  %config(noreplace) %{_sysconfdir}/foo.conf
If the update uses a non-backwards-compatible configuration format, then specify them like this:
如果更新程序用的是無法向前相容的組態格式 (non-backwards-compatible configuration format),則應這樣指定:
  %config %{_sysconfdir}/foo.conf
  %config %{_sysconfdir}/foo.conf


"<code>%attr(mode, user, group)</code>" can be used for finer control over permissions, where a "<code>-</code>" means use the default:
<code>%attr(mode, user, group)</code>」可以用來指派更精細的權限控制,而「<code>-</code>」代表是用預設值:
  %attr(0644, root, root) FOO.BAR
  %attr(0644, root, root) FOO.BAR


If a file is in particular natural language, use <code>%lang</code> to note that:
如果檔案是以特定的自然語言撰寫,請使用 <code>%lang</code> 來標註:
  %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
  %lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*


Programs using Locale files should follow the [[Packaging:Guidelines#Handling_Locale_Files|recommended method of handling i18n files]]:
使用到區域語言 (Locale) 檔案的程式應該遵循 [[Packaging:Guidelines#Handling_Locale_Files|處理 i18n 檔的建議方法 (英)]]
* find the filenames in the <code>%install</code> step: <code> %find_lang ${name}</code>
* <code>%install</code> 步驟中找出檔名:<code> %find_lang ${name}</code>
* add the required build dependencies: <code>BuildRequires: gettext</code>
* 加入必要的建置依賴: <code>BuildRequires: gettext</code>
* use the found filenames: <code>%files -f ${name}.lang</code>
* 使用找到的檔名: <code>%files -f ${name}.lang</code>


These prefixes are '''not''' valid in Fedora: <code>%license</code> and <code>%readme</code>.
以下前綴字在 Fedora 中 '''無效'''<code>%license</code> <code>%readme</code>


==== %files and Filesystem Hierarchy Standard (FHS) ====
==== %files 與檔案系統階層標準 (Filesystem Hierarchy Standard, FHS) ====


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>.
您應該遵守 [http://www.pathname.com/fhs/ 檔案系統階層標準 (FHS)]。執行檔應放在 <code>/usr/bin</code>,全域組態檔放進 <code>/etc</code>,函式庫放到 <code>/usr/lib</code> (<code>/usr/lib64</code>) 等等。只有一項例外:一般不該給使用者或管理員執行的執行檔,應該放到 <code>/usr/libexec</code> 中的子資料夾中,資料夾名稱為 <code>%{_libexecdir}/%{name}</code>.


Do '''not''' install files into <code>/opt</code> or <code>/usr/local</code>.
'''不要''' 把檔案安裝到 <code>/opt</code> <code>/usr/local</code> 中。


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>.
不幸地,許多程式預設情況下並不遵守 FHS。尤其是,系統架構獨立的函式庫被放到 <code>/usr/lib</code> 而非 <code>/usr/share</code> 之中。前者是給系統架構依賴的函式庫使用,後者才是給系統架構獨立的函式庫運用;這代表不同 CPU 架構的系統都能共享 <code>/usr/share</code> 資料夾。Fedora 中也是有一些例外 (例如 Python Perl),然而 Fedora 比起其他散佈版來說更嚴格遵守標準規範,<code>rpmlint</code> 一般會在你將 ELF 以外的檔案放進 <code>/usr/lib</code> 內時提出抱怨。


==== %files example ====
==== %files 範例 ====


Here's a simple example of a %files section:
以下為 %files 區段的簡單範例:
  %files
  %files
  %doc README LICENSE
  %doc README LICENSE
Line 479: Line 484:
  %config(noreplace) %{_sysconfdir}/*.conf
  %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
  cd ~/rpmbuild/RPMS/ARCH # 請將 "ARCH" 替換為您的系統架構
  rpm -qlp PACKAGE1.*.rpm | sort > ,1
  rpm -qlp PACKAGE1.*.rpm | sort > ,1
  rpm -qlp PACKAGE2.*.rpm | sort > ,2
  rpm -qlp PACKAGE2.*.rpm | sort > ,2
  comm -12 ,1 ,2
  comm -12 ,1 ,2


=== Scriptlets ===
=== 小指令稿 (Scriptlet) ===


When an end-user installs the RPM, you may want some commands to be run. This can be achieved through scriptlets. See [[Packaging/ScriptletSnippets]].
當終端使用者在安裝 RPM 時,您可能想要執行一些指令。這可以透過小指令稿完成。請見 [[Packaging/ScriptletSnippets]]


Scriptlets can be run:
小指令稿可以:
* before ('''<code>%pre</code>''') or after ('''<code>%post</code>''') a package is installed
* 在軟體包安裝之前 ('''<code>%pre</code>''') 或之後 ('''<code>%post</code>''') 執行
* before ('''<code>%preun</code>''') or after ('''<code>%postun</code>''') a package is uninstalled
* 在軟體包移除之前 ('''<code>%preun</code>''') 或之後 ('''<code>%postun</code>''') 執行
* at the start ('''<code>%pretrans</code>''') or end ('''<code>%posttrans</code>''') of a transaction
* 在處理事項的開頭 ('''<code>%pretrans</code>''') 或結尾 ('''<code>%posttrans</code>''') 執行


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.
舉例來說,每一會在任何 dinamic linker 預設路徑中儲存共享函式庫檔案的二進位檔 RPM 軟體包,都必須在 <code>%post</code> <code>%postun</code> 中呼叫 <code>ldconfig</code>。如果該軟體包有多個附帶函式庫的子軟體包,則每個軟體包也都應該執行相同的動作。
  %post -p /sbin/ldconfig
  %post -p /sbin/ldconfig
  %postun -p /sbin/ldconfig
  %postun -p /sbin/ldconfig


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.
如果僅執行單一指令,則「<code>-p</code>」選項會執行相接的指令但不會喚起 shell。然而,若有許多指令時,請省去這個選項,並在其下納入 shell 指令。


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>).
如果你在小指令稿中有執行任何程式,你就必須以「<code>Requires(CONTEXT)</code>(例: <code>Requires(post)</code>) 的形式來列出所有的執行需求。


<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>.
<code>%pre</code><code>%post</code><code>%preun</code>、和 <code>%postun</code> 提供了 <code>$1</code> 引數,表示動作完成之後系統上留下的此名稱之軟體包有幾個。請不要拿這個值來比較是否等於 <code>2</code>,而是比較是否大於或等於 <code>2</code>。至於 <code>%pretrans</code> <code>%posttrans</code><code>$1</code> 的值則恆為 <code>0</code>


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:
舉例來說,如果軟體包安裝了一份 info manual (資訊手冊),那麼可以用 <code>info</code> 軟體包提供的 <code>install-info</code> 來更新資訊手冊索引。首先,我們不保證 <code>info</code> 軟體包總會存在,除非我們明確宣告它是必備的部分;再來,我們不想要在 <code>install-info</code> 失敗之時讓軟體包的執行動作完全失敗:
  Requires(post): info
  Requires(post): info
  Requires(preun): info
  Requires(preun): info
Line 517: Line 522:
  fi
  fi


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:
還有一件安裝資訊手冊時相關的小瑕疵。<code>install-info</code> 指令會更新資訊目錄,所以我們應該要在 <code>%install</code> 區段中刪掉 %{buildroot} 中無用的空目錄:
  rm -f %{buildroot}%{_infodir}/dir
  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].
另一個類似小指令稿的能力是「triggers」(觸發器),可以在其他軟體包已安裝或已移除之時,為你的軟體包執行一些動作。請見 [http://rpm.org/api/4.4.2.2/triggers.html RPM Triggers]


=== Macros ===
=== 巨集 (Macro) ===


Macros are text in the format <code>%{string}</code>. Typical macros:
巨集是 <code>%{string}</code> 這類寫法的文字。典型的巨集有:


{|
{|
! Macro !! Typical Expansion !! Meaning
! 巨集 !!典型擴展 !! 意義
|-
|-
| <code>%{_bindir}</code> || <code>/usr/bin</code> || Binary directory: where executables are usually stored.
| <code>%{_bindir}</code> || <code>/usr/bin</code> || 二進位檔資料夾 (Binary directory):執行檔通常存放的位置。
|-
|-
| <code>%{_builddir}</code> || <code>~/rpmbuild/BUILD</code> || Build directory: files are compiled within a subdirectory of the build directory. See <code>%buildsubdir</code>.
| <code>%{_builddir}</code> || <code>~/rpmbuild/BUILD</code> || 建置資料夾 (Build directory):檔案放在建置目錄下的子目錄中編譯。請見 <code>%buildsubdir</code>
|-
|-
| <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/".)
| <code>%{buildroot}</code> || <code>~/rpmbuild/BUILDROOT</code> || 建置根基 (Build root):在 <code>%install</code> 階段中的檔案「安裝」之處,會將 <code>%{_builddir}</code> 子目錄下的檔案複製到 <code>%{buildroot}</code> 的子目錄之下。(過去,<code>%{buildroot}</code> 所採用的位置是「/var/tmp/」。)
|-
|-
| <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>.
| <code>%{buildsubdir}</code> || <code>%{_builddir}/%{name}</code> || 建置子資料夾 (Build subdirectory):在 <code>%build</code> 階段中檔案會在 <code>%{_builddir}</code> 的子目錄中編譯。這個位置會在 <code>%autosetup</code> 後設置。
|-
|-
| <code>%{_datadir}</code> || <code>/usr/share</code> || Share directory.
| <code>%{_datadir}</code> || <code>/usr/share</code> || 共用資料夾。
|-
|-
| <code>%{_defaultdocdir}</code> || <code>/usr/share/doc</code> || Default documentation directory.
| <code>%{_defaultdocdir}</code> || <code>/usr/share/doc</code> || 預設文件資料夾。
|-
|-
| <code>%{dist}</code> || <code>.fc''NUMBER''</code> || Distribution+version short name (e.g. "<code>.fc{{FedoraVersion}}</code>")
| <code>%{dist}</code> || <code>.fc''NUMBER''</code> || 散佈版+版本短名 (例:「<code>.fc{{FedoraVersion}}</code>)
|-
|-
| <code>%{fedora}</code> || <code>''NUMBER''</code> || Number of fedora release (e.g. "<code>{{FedoraVersion}}</code>")
| <code>%{fedora}</code> || <code>''NUMBER''</code> || fedora 發行版號 (例:「<code>{{FedoraVersion}}</code>)
|-
|-
| <code>%{_includedir}</code> || <code>/usr/include</code>
| <code>%{_includedir}</code> || <code>/usr/include</code>
Line 560: Line 565:
| <code>%{_mandir}</code> || <code>/usr/share/man</code>
| <code>%{_mandir}</code> || <code>/usr/share/man</code>
|-
|-
| <code>%{name}</code> || || Name of package, set by Name: tag
| <code>%{name}</code> || || 軟體包的名稱,由 Name: tag 決定
|-
|-
| <code>%{_sbindir}</code> || <code>/usr/sbin</code>
| <code>%{_sbindir}</code> || <code>/usr/sbin</code>
Line 568: Line 573:
| <code>%{_sysconfdir}</code> || <code>/etc</code>
| <code>%{_sysconfdir}</code> || <code>/etc</code>
|-
|-
| <code>%{version}</code> || || Version of package, set by Version: tag
| <code>%{version}</code> || || 軟體包版本,由 Version: tag 決定
|}
|}


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).
您可以查看 <code>/etc/rpm/*</code> <code>/usr/lib/rpm</code>、甚至是 <code>/usr/lib/rpm/macros</code> 以進一步瞭解巨集。或是用 <code>rpm --showrc</code> 來顯示 RPM 運用這些巨集時所採用的值 (會根據 <code>rpmrc</code> 與巨集組態檔而有所變動)


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 來定義自己的巨集值,但是請確定在使用巨集之前先已定義過。(巨集在定義之時也可以指涉 (refer to) 其他巨集。)
範例:
  %global date 2012-02-08
  %global date 2012-02-08


Use the "<code>-E</code>" option of <code>rpmbuild</code> to find the value of a macro in a SPEC file:
請用 <code>rpmbuild</code> 的「<code>-E</code>」選項來尋找巨集在 SPEC 檔中代表的值:
  rpmbuild -E '%{_bindir}' myfile.spec
  rpmbuild -E '%{_bindir}' myfile.spec


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].
也請參見 [[Packaging/RPMMacros]] [https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s07.html RPM Guide chapter 9]


=== Other tags ===
=== 其他標籤 (tag) ===


In addition to Requires and BuildRequires tags, you can also use these for controlling dependencies:
除了 Requires BuildRequires 標籤之外,你還可以使用以下這些控制依賴關係:
* '''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''':列出此軟體包提供的虛擬軟體包名稱。例如,可能有個 <code>foo</code> 軟體包需要來自其他程式的「bar」功能;若有許多軟體包可以滿足該需求,則這些軟體包可以指定「<code>Provides: bar</code>」,而「<code>foo</code>」軟體包則可以指定「<code>Requires: bar</code>」。你也可以使用 [http://dailypackage.fedorabook.com/index.php?/archives/6-Wednesday-Why-The-Alternatives-System.html "alternatives" 系統],但是若同個系統中有多位使用者,不同人可能希望使用不同的預設值,此時請避免使用它,畢竟這些設定屬於系統全域設定。請用「<code>rpm -q --provides PACKAGENAME</code>」來查看指定的軟體包提供那些東西。一些 Fedora 中虛擬軟體包的範例:
** MTA: Used for mail transport agents, such as sendmail.
** MTA:用作郵件傳輸代理 (mail transport agent, MTA),例如 sendmail。
** tex(latex): Used for latex
** tex(latex): 用作 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.
* '''Obsoletes''':當這個軟體包安裝時移除另一個指名的軟體包。當軟體包名稱更換之時,或是用該軟體包完全取代另一個不同的軟體包之時可以使用。
* '''Conflicts''': state what other packages cannot be installed simultaneously to this one. Avoid this if you can. See [[Packaging/Conflicts]].
* '''Conflicts''':表示無法與此軟體包同時安裝的其他軟體包。如果可以請避免使用這個標籤。請見 [[Packaging/Conflicts]]
* '''BuildConflicts''': state what packages cannot be installed when building this package. Avoid this if you can.
* '''BuildConflicts''':表示在建置此軟體包之時無法安裝的軟體包。如果可以請避免使用這個標籤。


To manage different architectures, there are two tags:
若要處理不同的系統架構,有兩種標籤可以使用:
* '''ExcludeArch''': to exclude an architecture on which the package doesn't build. For example:
* '''ExcludeArch''':排除此軟體包無法建置的系統架構。例如:
  ExcludeArch: ppc
  ExcludeArch: ppc
* '''ExclusiveArch''': to include only the specified architecture. Avoid this unless absolutely correct.
* '''ExclusiveArch''':僅納入指定的系統架構。除非絕對正確,否則請避免使用。
Valid architectures are listed at [[Architectures]].
可用的系統架構列在 [[Architectures]] 中。


=== Subpackages ===
=== 子軟體包 (或稱細分包,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.
一份 SPEC 檔可以定義多份二進位檔軟體包。換句話說,一個內含一份 SPEC 檔的 SRPM 檔可能製作出許多 RPM 檔來。請注意到這依然只會有一道製作 (%prep、%build、%install ) 程序。 <code>name-doc</code> <code>name-devel</code> 為常見的文件檔和開發檔子軟體包。


Use the <code>%package</code> directive to start defining a subpackage:
請使用 <code>%package</code> 巨集指令來定義子軟體包:
  %package subpackage_name
  %package subpackage_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:
在每個 <code>%package</code> 指令之後,請列出該子軟體包的數個標籤 (tag)。這應該至少包括 Summary Group 標籤、以及 <code>%description subpackage_name</code> <code>%files subpackage_name</code> 指令:


Anything not specified by the subpackage will be inherited from its parent.
任何子軟體包中未特別指定到的東西,都會從其親代沿襲下來。


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):
預設情況下,如果該軟體包的名稱為「<code>foo</code>」而子軟體包名稱為「<code>bar</code>」,則子軟體包成果則會是「<code>foo-bar</code>」。你可以利用「<code>-n</code>」選項 (但如果你在這裡特別指定的話,你也需要在所有其他的指令中用到這道指令) 來凌駕原先的規則:
  %package -n new_subpackage_name
  %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.
[http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch10s04.html 請見 RPM Guide 針對子軟體包所寫的小節]瞭解更多資訊。


=== Conditionals ===
=== 條件判斷 (Conditional) ===


You can insert conditional statements, for example to test if you are creating a binary for a certain architecture:
你可以插入條件判斷陳述,例如測試你是否會為特定系統架構製作二進位檔:
  %ifarch ARCHITECTURE_NAME
  %ifarch ARCHITECTURE_NAME
the negated version with:
反面 (negated) 的論述版本為:
  %ifnarch ARCHITECTURE_NAME
  %ifnarch ARCHITECTURE_NAME
or the more general conditional:
或更一般的條件判斷式:
  %if TRUE_OR_FALSE
  %if TRUE_OR_FALSE


There is an optional "<code>%else</code>" section; all of these are closed with "<code>%endif</code>".
也有個可選擇性使用的「<code>%else</code>」區段;以上這些全都必須以「<code>%endif</code>」作結尾。


=== 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
有許多應用程式專門規約可以協助你 (例:專門的程式語言、應用程式、函式庫、建置系統等)。大多都列在
[[Packaging/Guidelines#Application_Specific_Guidelines|Application Specific Guidelines of Packaging/Guidelines]].  Examples of application-specific guidelines are those for:
[[Packaging/Guidelines#Application_Specific_Guidelines|應用程式專用打包規約/規約 (英)]] 之中。一些應用程式專門規約的例子有:
* [[Packaging:Cmake|Cmake]]
* [[Packaging:Cmake|Cmake]]
* [[Packaging:Emacs|Emacs]]
* [[Packaging:Emacs|Emacs]]


Failing that, some other ways of finding application-specific help are:
如果上述的資訊都沒有涵括到,還有一些可以幫助你找到應用程式專用協助的方法:
* The 'SEARCH' command on Fedoraproject.org.
* Fedoraproject.rog 上的「SEARCH」指令。
* [[PackagingDrafts]]
* [[PackagingDrafts]]
* A [[SIGs|Special Interest Group (SIG)]]
* [[SIGs|Special Interest Group (SIG)]]
* [http://fedoraproject.org/wiki/Special:PrefixIndex/Packaging Wiki pages prefixed with 'Packaging']
* [[Special:PrefixIndex/Packaging|名稱以「Packaging」起頭的 Wiki 頁面]]


=== Miscellaneous hints ===
=== 其他注意事項 (Miscellaneous hints) ===


[[Packaging/FrequentlyMadeMistakes]] has information on frequently-made mistakes. There are also some recommendations and controversial tricks on
[[Packaging/FrequentlyMadeMistakes]] 有列出常見錯誤的相關資訊。[[PackageMaintainers/Packaging Tricks]] 則有列出一些建議、以及具爭議性的技巧。
[[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
請試著撰寫你的 SPEC 檔,盡可能讓上游發行新版本時一切都能水到渠成,使你除了要改版本號並刷新來源檔案外,都不必做任何其他修改。舉例來說,如果要替 *.txt 檔設執行位元,請不要用
   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:
而是考慮用以下這種方式來處理,可以直接處理使用相同命名規則的新檔名:
   chmod a-x *.txt
   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
   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.
請不要嘗試和使用者互動;RPM 是以支援批量安裝為設計核心。如果有個程式需要顯示 EULA 終端使用者授權協議,則該動作應是初次執行時才做,而非安裝之時做。


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.
建議你不要試圖啟動服務,因為在大量安裝的過程中可能會讓一切變得緩慢。若你有安裝 init systemd 指令稿,請考慮用 <code>chkconfig</code> <code>systemctl</code> 來安排服務在下次重新開機之時啟動/停止該項服務。在解除安裝之前,如果這些服務還在跑,一般而言你應該先嘗試停止這些服務。


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 <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:
一般而言,如果有二進位執行檔,則一般二進位軟體包應該剝離除錯用符號 (debugging symbols),並放到 <code>name-debug</code> 子軟體包中。如果不應發生這樣的事,你可以在你的 SPEC 檔頂端放入停用剝離動作:
  %global _enable_debug_package 0
  %global _enable_debug_package 0
  %global debug_package %{nil}
  %global debug_package %{nil}
  %global __os_install_post /usr/lib/rpm/brp-compress %{nil}
  %global __os_install_post /usr/lib/rpm/brp-compress %{nil}


To prevent stripping you may also need to do this in the <code>%install</code> section:
若想避免剝離動作,你也需要在 <code>%install</code> 區段中做以下動作:
  export DONT_STRIP=1
  export DONT_STRIP=1


A way to check for the version of Fedora in a SPEC file for conditional builds is:
在 SPEC 檔中檢查 Fedora 版本作條件判斷式建置的方法:A way to check for the version of Fedora in a SPEC file for conditional builds is:
  %if 0%{?fedora} <= <version>
  %if 0%{?fedora} <= <version>
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.)
<code>?</code> 會讓巨集在 <code>%fedora</code> 未定義之時評斷為空白。這樣會讓結果成為 <code>0</code> (數字零,所以很好),而 <code>%fedora</code> 若真的有個數值時也不會有所干擾。(請注意這種做法在 Koji 的「scratch」建置中沒有作用,<code>%fedora</code> 的值會在 SRPM 製作之時就設定好。)


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].
GUI 程式必須有桌面條目 (desktop entry),這樣用戶才能從圖形化桌面選單中喚起這些程式。對於 <code>.desktop</code> 檔案,請見 [[Packaging/Guidelines#Desktop_files|Fedora packaging guidelines for desktop files]] [http://standards.freedesktop.org/desktop-entry-spec/latest/ desktop entry spec];至於 <code>/usr/share/icons</code>,請見 [http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html icon theme spec]


== Building the binary package ==
== 建置二進位軟體包 ==


=== Test with rpmlint ===
=== 利用 rpmlint 作測試 ===


To catch many common errors early, run <code>rpmlint</code> on your SPEC file before trying to build anything from it:
若要在早期捕捉個種常見錯誤,請在嘗試用 SPEC 檔建置任何軟體包之前先對它執行 <code>rpmlint</code>
  $ rpmlint program.spec
  $ rpmlint program.spec
If the reported error doesn't make sense, run it again with the "<code>-i</code>" option for longer messages.
如果回報的錯誤看起來不怎麼合理,請重新以「<code>-i</code>」選項執行以取得更詳細的訊息。


Aim to have no errors, but sometimes <code>rpmlint</code> reports false positives. The [[Packaging/Guidelines#Use_rpmlint|Fedora packaging guidelines]]
請以無報錯為目標,不過有時 <code>rpmlint</code> 會有誤報的情況發生。[[Packaging/Guidelines#Use_rpmlint|Fedora 打包規約]] 中有解釋到那些錯誤可以忽略。
explains which ones to ignore.


=== Create binary RPMS from the SPEC file ===
=== SPEC 檔製作二進位 RPM 包 ===


Once you've created your SPEC file, build the SRPM and binary RPMS by running this:
一旦你做好 SPEC 檔之後,請執行以下指令來建置 SRPM 與二進位 RPM:
  $ rpmbuild -ba program.spec
  $ rpmbuild -ba program.spec


If successful, RPMS will be created within <code>~/rpmbuild/RPMS</code> and SRPMS will be created within <code>~/rpmbuild/SRPMS</code>.
如果製作成功,RPM 會放到 <code>~/rpmbuild/RPMS</code> 裡面,而 SRPM 會放到 <code>~/rpmbuild/SRPMS</code> 之內。


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:
如果製作失敗,請前往對應的資料夾來看看留下了什麼。若想取得除錯協助,你可以用「<code>--short-circuit</code>」選項來略過早期的成功階段。例如:若想要 (略過更早期階段) 重新從 <code>%install</code> 階段開始,請執行:
  $ rpmbuild -bi --short-circuit program.spec
  $ rpmbuild -bi --short-circuit program.spec


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:
若你只想要製作 SRPM (不會執行 <code>%prep</code> <code>%build</code> 或其他階段),請執行:
  rpmbuild -bs program.spec
  rpmbuild -bs program.spec


=== Testing binary RPMS with rpmlint ===
=== 利用 rpmlint 來測試二進位 RPM 檔 ===


<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:
<code>rpmlint</code> 可以對 SPEC 檔、RPM 檔、SRPM 檔執行來檢查是否存在錯誤。你需要在發佈軟體包之前解除或糾正發出的警告。[[Common_Rpmlint_issues|這個網頁]]提供一些常見問題的解釋。如果你位於 SPEC 目錄中,請執行:
  $ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm
  $ rpmlint ''NAME''.spec ../RPMS/*/''NAME''*.rpm ../SRPMS/''NAME''*.rpm


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:
請進入 <code>~/rpmbuild/RPMS</code> 目錄,再進入系統架構子目錄中。你會看到一些二進位檔 RPM。請用以下指令快速查看這些檔案和權限 (來檢查看看是否正確)
  $ rpmls *.rpm
  $ rpmls *.rpm


If they look fine, install them as root:
如果一切看起都很好,請以 root 身份安裝:
  # rpm -ivp package1.rpm package2.rpm package3.rpm ...
  # 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 <code>.desktop</code> entry is wrong.
請以不同的方式來測試程式看是否全部都正常運作。如果它是 GUI 工具,請確認有出現在桌面選單中,否則代表 <code>.desktop</code> 條目可能有錯。


Uninstall packages later by doing:
稍後可以利用以下指令來解除安裝軟體包:
  # rpm -e package1 package2 package3
  # rpm -e package1 package2 package3


== Mock and Koji ==
== Mock Koji ==


[[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:
[[Projects/Mock|Mock]] 是在近乎空白的環境下,運用你剛製作的 SRPM 來建置二進位軟體包的強大工具。這可以揭露你實際的建置依賴關係。如果建置失敗,則代表你忘記在 BuildRequires 中列出其中一些東西。請參見 [[Using Mock to test package builds]]。一旦你的帳號屬於「<code>mock</code>」群組的成員之一,你可以執行這樣的指令來做本地端測試:
  $ mock -r fedora-9-i386 rebuild path_to_source_RPM
  $ mock -r fedora-9-i386 rebuild path_to_source_RPM


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:
你可以利用 Koji (會運用 <code>mock</code>) 在各種不同的系統上執行建置,包括那些你沒有的系統架構。[[PackageMaintainers/Join]] [[PackageMaintainers/UsingKoji]] 上面有更多有關 Koji 的資訊。一旦設定完成,你就可以在各種平臺上使用以下指令來測試你的 SRPM:
  $ koji build --scratch dist-f9 path_to_source_RPM
  $ koji build --scratch dist-f9 path_to_source_RPM


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.
請將 <code>dist-f9</code> 以任意近期 Fedora 發行版本替換,但別使用 <code>dist-rawhide</code>。請記住,<code>%fedora</code><code>%fc9</code>、等這類的值都不會在 scratch build 中得到修正,所以如果你的 SPEC 檔會依據上述值來做不同的事,則無法作用。


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.]
你的 Koji 建置僅能依賴 TARGET 散佈版軟體庫中實際存在的軟體包。所以,如果你的軟體包依賴 Bodhi 尚未發行的其他軟體包,就無法用 Koji 來為已發行的散佈版作建置。如果你需要對尚未成為穩定版的發行更新建置軟體包,請透過 Bodhi 提交 Koji 建置根基凌駕請求 (Koji buildroot override requet)。如果它並非你的軟體包依賴,請聯絡其維護者。[Bodhi 可以處理 Koji 建置根基凌駕請求之前,以前的舊方法是在此處對 rel-eng 提交請票 (ticket):https://fedorahosted.org/rel-eng/newticket ,並請求將該軟體包加入成為建置根基凌駕之一。]


== Helpful tools ==
== 有用的工具 ==


The <code>rpmdevtools</code> package has a number of helpful tools; "<code>rpm -qil rpmdevtools</code>" will show you what it installs.
<code>rpmdevtools</code> 軟體包有各種好用工具;「<code>rpm -qil rpmdevtools</code>」會展示給你看它會安裝哪些東西。
* <code>rpmdev-bumpspec</code> : bump the release tag in the spec file and add a changelog comment with the right date and version format:
* <code>rpmdev-bumpspec</code>:增進 SPEC 檔中的發行版本標籤,並以當下時間與版本格式加入 changelog 評註:
  rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
  rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES


The <code>yum-utils</code> package also has some useful tools:
<code>yum-utils</code> 軟體包也提供一些好用工具:
* <code>yumdownloader</code> : download the SRPM of the package by running:
* <code>yumdownloader</code>:請執行以下指令下載該軟體包的 SRPM:
  yumdownloader --source PACKAGENAME
  yumdownloader --source PACKAGENAME


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.
<code>auto-buildrequires</code> 軟體包有一對優質工具可以幫助我們找出適當的 BuildRequires 條目。在安裝這個軟體包之後,請用「<code>auto-br-rpmbuild</code>」替換 「<code>rpmbuild</code>」,你就會看見自動產生的 BuildRequires 清單。


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.
你可能發現到 [http://rust.sourceforge.net/ RUST] 滿好用的 (GPL),但是它無法製作出符合 Fedora 軟體包品質的 SPEC 檔。[http://kitenet.net/~joey/code/alien/ Alien] 則可以在軟體包格式之間轉換;它無法製作出乾淨的 SRPM,但是從既有的軟體包轉換程式或許能提供一些有用的資訊。


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'''.
最後,[https://github.com/alanfranz/docker-rpm-builder docker-rpm-builder] (APL 2.0) 使用 [http://www.docker.com Docker] 來建置 RPM 軟體包;想用 rpmbuild 建置的目標架構需要與主控散佈版相同,至於 mock 則對於任何目標架構的 Fedora/Centos/RHEL 散佈版都能良好處理,'''這是無論 Docker 是否能跑都能運用的最後工作'''


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].
若你想要為你的軟體包建置出不同的散佈版與系統架構,並且公開存取 yum 軟體庫,你可以提交你的 src.rpm [https://copr.fedoraproject.org Copr]


== Guidelines and rules ==
== 規約與規則 ==


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]]
* [[Join the package collection maintainers|如何成為 Fedora 軟體包集合的維護者]]
* [[Packaging:Guidelines|Packaging Guidelines]]
* [[Packaging:Guidelines|打包規約]]
* [[Packaging:NamingGuidelines|Package Naming Guidelines]]
* [[Packaging:NamingGuidelines|軟體包名稱規約]]
* [[Packaging:LicensingGuidelines|Package Licensing Guidelines]]
* [[Packaging:LicensingGuidelines|軟體包授權規約]]
* [[Packaging:DistTag|Dist Tag Guidelines]]  
* [[Packaging:DistTag|散佈版標籤規約]]  
* [[Packaging:ReviewGuidelines|Package Review Guidelines]]
* [[Packaging:ReviewGuidelines|軟體包校閱規約]]


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.
有許多官方規約可以引導你處理一些特定情況 (例:Java 程式、OCaml 程式、GNOME 程式等)。你也可以從 [[SIGs|SIG]] 瞭解更多資訊,與 [[:Category:Package Maintainers|軟體包維護者]] 小節。


[https://fedoraproject.org/wiki/Special:Prefixindex/Packaging You can also see the list of all Wiki pages about Packaging] to see if any apply.
[[Special:Prefixindex/Packaging|你也可以查看所有關於打包的 Wiki 頁面]]來看是否有適用的。


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]].
如果找不到,你可能想要找一些非官方的好用建議,例如 [[Special:Search?ns0=1&search=PackagingDrafts%2F&searchx=Search|Packaging Drafts]] 和 [[PackagingDrafts|Packaging Drafts To Do]]


You might find ideas from [http://en.opensuse.org/Packaging SuSE],
你也可以從 [http://en.opensuse.org/Packaging SuSE]
[http://www.debian.org/doc/debian-policy/ Debian], but
[http://www.debian.org/doc/debian-policy/ Debian] 的資料中找到一些想法,但是
[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 各個散佈版所用的規則會不同],所以不要直接想說他們的東西可以直接拿來用。


'''The .spec files that you create must be open source software, as noted in the [[Legal:Fedora_Project_Contributor_Agreement|FPCA]].'''
'''你製作的 .spec 檔必須是開源軟體,如 [[Legal:Fedora_Project_Contributor_Agreement|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.
一旦你的軟體包被接受,你和你的共同維護者會需要維護這份軟體包。請見 [[Package update HOWTO]] [[Package update guidelines]]。如果你在多個 Fedora 發行版中更新了它的版本,請即時往前做 (例:為 Fedora N 發行新版,一旦被接受,就做 Fedora N-1)。系統會假定新的 Fedora 版本會有相同版本或更後續版本的程式。


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] (簡明摘要)
* [http://www.gnu.org/prep/standards/html_node/Managing-Releases.html GNU Coding Standards release process]
* [http://www.gnu.org/prep/standards/html_node/Managing-Releases.html GNU Coding Standards release process]
* [http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/ Software Release Practice HOWTO]
* [http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/ Software Release Practice HOWTO]
Line 773: Line 777:
* [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 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:
若想瞭解更多資訊,在 Fedora Wiki 以外的地方,可以看看下面這些:
* [http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/ How to build RPM packages on Fedora] - very brief run-through
* [http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/ How to build RPM packages on Fedora] - very brief run-through
* Packaging software with RPM (developerWorks) [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3]
* Packaging software with RPM (developerWorks) [http://www.ibm.com/developerworks/library/l-rpm1/ Part 1], [http://www.ibm.com/developerworks/library/l-rpm2/ Part 2], and [http://www.ibm.com/developerworks/library/l-rpm3.html Part 3]
Line 798: Line 802:
* The [http://wiki.rpm.org/ rpm.org Wiki] has some useful information, such as the [http://wiki.rpm.org/Problems list of known RPM problems]
* The [http://wiki.rpm.org/ rpm.org Wiki] has some useful information, such as the [http://wiki.rpm.org/Problems list of known RPM problems]


Note: The [http://rpm5.org/ 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 [http://www.rpm.org rpm.org].
註:[http://rpm5.org/ rpm5.org] 網站也有提供一些文件,但是請不要依靠裡面的內容;那是 Jeff Johnson 維護的 RPM「分支」,也就是 ''fork''。Fedora (Novell/SuSE) 所用的 RPM 則是基於 [http://www.rpm.org rpm.org]
[http://lwn.net/Articles/236029/ lwn.net has a brief article] about this.
[http://lwn.net/Articles/236029/ lwn.net 有個簡要的文章]報導這件事。


[[Category:Package Maintainers]]
[[Category:Package Maintainers]]
[[Category:How to]]
[[Category:How to]]
[[Category:Zh]]
[[Category:Zh]]
[[Category:Zh/Translation]]
[[Category:Zh/Translation]]

Latest revision as of 21:00, 19 September 2016

翻譯: 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),以避免建置程序出錯摧毀你的檔案,或將私人金鑰傳給全世界。

你「永遠」都不該以 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/41/Everything/source/SRPMS 目錄取得源碼軟體包。請將「41」替換成你想要使用的 Fedora 發行版本,接著下載該軟體的 .src.rpm 軟體包。

一旦你下載好 SRPM,請將它安裝到 ~/rpmbuild

$ rpm -ivh sourcepackage-name*.src.rpm

你也可以用 rpm2cpio 將 SRPM 包解開放到目錄中:

$ mkdir PROGRAMNAME_src_rpm
$ cd PROGRAMNAME_src_rpm
$ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i

有時候利用既有的軟體包作為開始是最簡單的方式,只要稍微清理一下就能讓 Fedora 使用。RPM 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),但請注意有些應用程式若沒有某功能相關的依賴項目時,會永久停用該功能;這些情況中你可能需要納入額外的軟體包。 auto-buildrequires 軟體包可能會有所用處。
  • 'Requires:當程式安裝之時所需要的軟體包清單,請以半形逗號隔開各個項目。請注意 BuildRequires 標籤應列出的是建置二進位檔 RPM 的項目清單,而 Requires 標籤列出的是安裝/執行該程式所需的項目清單;一個軟體包可以放在其中一個清單,或同時兩個清單中。在許多情況下,rpmbuild 會自動偵測依賴項目,所以不見得需要 Requires 標籤。然而,你可能會希望特別標明那些軟體包是需要的,或是哪些軟體包沒自動偵測到而你需要手動標明。
  • %description:長篇的、跨多列的程式描述。請使用美式英文。每一列都必須小於等於 80 個字元。空白列表示新段落的開始。有些圖形使用者介面安裝程式會重新格式化段落;以空白起頭的列會被視為已預先格式化過的格式,會如其所述表現,顯示時一般採用等寬字型。請見 RPM Guide.
  • %prep:「準備」程式的指令稿指令 (例如:將之解壓縮),這樣才能建置程式。一般這只是「%autosetup」。如果源碼檔案要解開放到 NAME 的話,常見的變化形式是「%autosetup -n NAME」。請見下方的 %prep 小節瞭解更多資訊。
  • %build:「建置」程式的指令稿指令 (例如:編譯它),準備完成以便後續安裝。程式應該有附上如何執行此步驟的指示。請見下方 %build 小節來瞭解更多資訊。
  • %install:「安裝」程式的指令稿指令。指令應該要將檔案從 BUILD 目錄 %{_builddir} 複製到建置根基目錄 %{buildroot} 中。請見下方的 %install 小節瞭解更多細節。
  • %check:「測試」程式的指令稿指令。這是在 %install 程序後執行,所以如果你需要此區段的話,請將它放在該處。通常它僅包含「make test」或「make check」。這要和 %build 分開,這樣人們才能在需要的時候略過自我測試。
  • %clean: 清理建置根基目錄的指令。請注意這個區段目前在 Fedora 中是多餘的,並且只有 EPEL 需要。一般這只包含:
rm -rf %{buildroot}
  • %files:會安裝的檔案清單。請見下方 %files 小節以瞭解更多細節。
  • %changelog:軟體包的變動。請使用上述格式。請「不要」把軟體的變更記錄放在這裡。這裡是 RPM 自身的變更記錄。
  • ExcludeArch:如果軟體包無法在某特定架構上成功編譯、建置或運作,請在此標籤下列出這些架構。* 你可以加入些代碼區段,這樣代碼會在軟體包於真實系統上安裝或移除時執行 (與之相反的是只執行 %install 指令稿,它只會作虛擬安裝 (pseudo-install),安裝到建置根基目錄中)。這些代碼稱之為「scriptlet」指令稿片段,他們通常以軟體包中的資訊更新執行中的系統。請見下方的「scriptlet」瞭解更多細節。

RPM 也支援從單一 SPEC 檔製作出多個軟體包 (稱為 子軟體包) 的功能,例如 name-libsname-devel 等軟體包。

「不要」使用這些標籤
  • Packager
  • Vendor
  • Copyright

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

SPEC 檔區段詳解

%prep 區段

%prep 區段描述的是如何解開壓縮後軟體包的方法,這樣才能拿來建置。一般而言,這包含「%autosetup」指令。另外,你可以使用「%setup」和「%patch」指令搭配參照 Source0 (與 Source1 等) 條目。請見 Maximum RPM 一文中的 %setup and %patch 小節 瞭解更多細節。

自 RPM 4.4.2 起可以使用 %{patches} 和 %{source} 巨集,若你有大量補丁或來源清單,以及 %autosetup 效果並非你所想要的話會很好用,例如你可以這樣做:

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

然而請記住,使用上述功能,會讓你的 SPEC 和 RHEL 以及其他 RPM 散布版中所使用的 RPMS 不相容。

%prep 區段:%autosetup 指令

%autosetup」指令會解開來源軟體包。可用選項包括:

  • -n name :如果 Source tarball 所要解開成的目錄名稱與 RPM 名稱不同,這個切換開關用來指定正確的目錄名稱。舉例來說,如果 tarball 要解開成 FOO 目錄,則使用「%autosetup -n FOO」。
  • -c name :如果 Source tarball 需要解開成多個目錄,而非單一個目錄時,這個切換開關可以用來建立名為 name 的目錄,然後將內容解開放在裡面。

如我你改用「%setup」指令,則通常使用 -q' 來抑止不必要的輸出。

如果你打算解開多份檔案,有更多 %spec 選項可以用,這在你製作子軟體包時會很有用 (請見下方)。比較重要的有:

-a number 在切入目錄後,只解開指定數字的 Source 目錄 (例:「–a 0」代表 Source0)。
-b number 在切入目錄前,只解開指定數字的 Source 目錄 (例:「–b 0」代表 Source0)。
-D 在解開之前不要刪除目錄。
-T 停用自動解開封存檔。

%prep 區段:%patch 指令

如果你用的是「%autosetup」指令,就不需要下列的手動補丁管理程序。如果你的需求很複雜,或是需要和 EPEL 相容,還是可能需要用到。「%patch0」指令會套用 Patch0 (而 %patch1 會套用 Patch1,依此類推)。補丁是對來源程式碼做出必要修改使之符合打包規約的正常作法。常用的「-pNUMBER」選項會傳遞引數給 patch 程式來套用對應補丁。

補丁的檔名通常看起來像是「telnet-0.17-env.patch」這樣,命名格式依循「%{name} - %{version} - REASON.patch」(不過有時候會省略 version 版本)。補丁檔通常是「diff -u」的成果;如果你是從if you do this from the subdirectory of ~/rpmbuild/BUILD 的子目錄執行這個指令的,那麼你之後便不必指定 -p 層級。

這是為單一檔案製作補丁的典型程序:

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

如果需要修改許多檔案,有個簡單的方法,就是複製 BUILD 下的整個子目錄,然後執行子目錄的 diff。在你切入「~rpmbuild/BUILD/NAME」目錄後,執行以下指令:

cp -pr ./ ../PACKAGENAME.orig/
... 修改許多檔案 ...
diff -ur ../PACKAGENAME.orig . > ~/rpmbuild/SOURCES/NAME.REASON.patch

如果你想在一個補丁中編輯多重檔案,你也可以在編輯之前用同樣的檔名結尾「.orig」來複製原始檔案。然後,你可以用「gendiff」(在 rpm-build 軟體包中) 製作檔案差異的補丁檔。


試著確保你的路徑完全符合情境。預設的「fuzz」值是「0」,代表比對要求完全相同。你可以加入「%global _default_patch_fuzz 2」來轉換成舊版 Fedora RPM 版本所採用的值,但我們建議你應盡量避免這樣做。


Packaging/PatchUpstreamStatus 所詳述的,SPEC 檔中所有的補丁上方都要有個註解描述它的目前上游狀態為何。如果這是 Fedora 特別需要的補丁,你應該提及為何它如此特別。Fedora 專案致力不與上游分歧;請見 PackageMaintainers/WhyUpstream 瞭解此事的重要性。

%prep 區段:未修改的檔案

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

cp -p %SOURCE1 .

%build 區段

「%build」區段偶爾會有點複雜;在這個區段中你設置組態,並編譯/建置用來安裝的檔案。

許多程式採用 GNU configure 的方法 (或據此變化)。預設情況下,檔案會安裝到前綴為「/usr/local」的路徑下,這對解開檔案的存放來說相當合理;但是,現在你是要打包程式,所以請將路徑前綴改成「/usr」。函式庫則應該視架構而定,安裝到 /usr/lib/usr/lib64 中。

由於 GNU configure 非常常見,可以自動使用「%configure」巨集來喚起正確的選項 (例如,將前綴路徑改成 /usr)。有些變化也多能作用:

 %configure
 make %{?_smp_mflags}

若要凌駕 makefile 變數,請將它作為參數傳遞給 make

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

至於其他深入資訊,請參見 "GNU autoconf, automake, and libtool" 以及 "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer

也有些程式使用 cmake。請參見 Packaging/cmake

%install 區段

本區段內含「安裝」該程式用的指令稿指令,即從 %{_builddir} 資料夾複製相關檔案到 %{buildroot} 中 (通常代表從 ~/rpmbuild/BUILD 複製到 ~/rpmbuild/BUILDROOT),並且根據需要在 %{buildroot} 中新建資料夾。

有些術語的名稱可能讓人會錯意:

  • 「建置目錄 build directory」,也稱為 %{_builddir},實際上和「建置根基 build root」,又稱為 %{buildroot},是不一樣的資料夾。我們會在前者中編譯,而要打包的檔案則從前者複製到後者去。
  • 在 %build 區段中,目前的目錄起始於 %{buildsubdir},是 %prep 階段中在 %{_builddir} 下建立的子資料夾。這個資料夾名稱通常會是 ~/rpmbuild/BUILD/%{name}-%{version} 這樣。
  • %install 區段在終端使用者安裝二進位 RPM 軟體包時並 不會 執行 ;事實上 %install 區段只有在製作軟體包時才會執行。

一般來說,這裡執行的是「make install」之類的:

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

理想上您應該使用 %make_install,對於支援的程式來說,它等同於 DESTDIR=%{buildroot},因為它會重新導引檔案安裝到指定的目錄中,也就是我們在 %install 區段中預期發生的事。

如果程式不支援 DESTDIR(且僅在有此情況之下),您有許多 (下方所列) 方式可以避開問題:

  • 修補 makefile 來讓它支援 DESTDIR。在 DESTDIR 中視需要建立目錄,並提交該 patch 補丁給上游。
  • 使用「%makeinstall」巨集。這個方法可能有效,但也可能導致些微失敗。該巨集會展開成「make prefix=%{buildroot}%{_prefix} bindir=%{buildroot}%{_bindir} ... install」,而可能導致有些程式無法正常運作。請在 %{buildroot} 下視需要建立目錄。
  • 考慮使用 auto-destdir 軟體包。它需要「BuildRequires: auto-destdir」、並將「make install」修改成「make-redir DESTDIR=%{buildroot} install」。這只在安裝僅使用到特定常用指令來安裝檔案時才能作用,例如 cpinstall
  • 手動執行安裝。這可能牽涉到在 %{buildroot} 下建立必要的目錄,並從 %{_builddir} 複製檔案到 %{buildroot} 裡去。要特別注意更新,通常會有新檔名或修改過檔名。此程序的範例:
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{_bindir}/
cp -p mycommand %{buildroot}%{_bindir}/

%check 區段

如果可以自我測試的話,將它們納入其中的話會是個好主意。他們應該放在 %check 區段中 (緊接在 %install 區段之後,因為應該測試 %buildroot 中的檔案) 而不是放在 %build 區段中,這樣才能在必要時刻輕易略過。

通常,此區段包含:

make test

有時候也可以用:

make check

請探索一下 Makefile 的用法,並選擇適當的方式。

%files 區段

此區段宣告哪些檔案與目錄是由該軟體包擁有,還有哪些檔案與目錄會放到二進位檔 RPM 中。

%files 基礎

%defattr 會設定預設的檔案權限,通常可以在 %files 區段的開頭看到使用。請注意到,如果不需要修改權限的話,那就不再需要用到它。它的使用格式為:

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

第四個參數通常會省略。通常我們會這樣用 %defattr(-,root,root,-),其中「-」代表預設權限。

您應該列出該軟體包擁有的所有檔案和目錄。請盡量用巨集來取代目錄名稱,您可以到 Packaging:RPMMacros (舉例:使用 %{_bindir}/mycommand 取代 /usr/bin/mycommand) 來查看巨集表。如果起頭樣式為「/」(或從巨集擴展而來),則從 %{buildroot} 目錄取用。否則,將假定檔案位在目前的目錄中 (例如:在 %{_builddir} 內部,例如您想要納入的文件檔)。若您的軟體包僅安裝單一檔案如 /usr/sbin/mycommand,則 %files 區段可以像這樣簡單:

%files
%{_sbindir}/mycommand

若要讓您的軟體包較不受上游改動而影響,請依這種樣式比對來宣告該軟體包擁有的目錄下所有檔案:

%{_bindir}/*

若要納入單一目錄:

%{_datadir}/%{name}/

請注意,%{_bindir}/* 並不會宣稱此軟體包擁有 /usr/bin 目錄,而只有包含其下的檔案。如果您列出一個目錄,則您正試圖宣稱該軟體包擁有這個目錄,以及該目錄內的所有檔案與子目錄。所以,請 不要 列出 %{_bindir},而且要小心處理那些可能和其他軟體包共享的目錄。

如果有下列情形可能引發錯誤:

  • 試圖樣式比對,卻沒比對到任何檔案或目錄
  • 重複列出或重複比對到某個檔案或目錄
  • 沒有列出 %{buildroot} 下的某個檔案或目錄

您也可以使用 %exclude glob 來從前個比對中排除檔案。這對於想用不同的樣式比對來將幾乎全部檔案納入其中時會很有用,但是請注意如果沒有比對到任何東西也會造成失敗。

%files 前綴字

您可能需要在 %files 區段的內容中加入一個或多個前綴字;請用空格隔開。請見 Max RPM section on %files directives

通常,「%doc」用來列出 %{_builddir} 內,但未複製到 %{buildroot} 中的文件檔。通常包括 READMEINSTALL 檔。它們會放到 /usr/share/doc 下適當的目錄中,而 /usr/share/doc 的擁有權不必宣告。

注意: 如果有指定 %doc 條目,rpmbuild < 4.9.1 在安裝之前會將檔案安裝到其中的 doc 文件目錄移除。這代表已經放到裡面去的檔案,例如,在 %install 區段中安裝的檔案,會被移除,因此最終不會出現在軟體包中。如果您想要在 %install 區段中安裝一些檔案,請將它們安裝到建置目錄 (是 build dir,而不是建置根基 build root) 內的暫時鄰架目錄 (temporary staging directory) 中,例如 _docs_staging,接著將之納入 %files 列表中,如 %doc _docs_staging/* 這樣。

組態檔應該要放在 /etc 中,一般會這樣指定 (可以確保使用者所作的更動不會在更新時被覆蓋):

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

如果更新程序用的是無法向前相容的組態格式 (non-backwards-compatible configuration format),則應這樣指定:

%config %{_sysconfdir}/foo.conf

%attr(mode, user, group)」可以用來指派更精細的權限控制,而「-」代表是用預設值:

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

如果檔案是以特定的自然語言撰寫,請使用 %lang 來標註:

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

使用到區域語言 (Locale) 檔案的程式應該遵循 處理 i18n 檔的建議方法 (英)

  • %install 步驟中找出檔名: %find_lang ${name}
  • 加入必要的建置依賴: BuildRequires: gettext
  • 使用找到的檔名: %files -f ${name}.lang

以下前綴字在 Fedora 中 無效%license%readme

%files 與檔案系統階層標準 (Filesystem Hierarchy Standard, FHS)

您應該遵守 檔案系統階層標準 (FHS)。執行檔應放在 /usr/bin,全域組態檔放進 /etc,函式庫放到 /usr/lib (或 /usr/lib64) 等等。只有一項例外:一般不該給使用者或管理員執行的執行檔,應該放到 /usr/libexec 中的子資料夾中,資料夾名稱為 %{_libexecdir}/%{name}.

不要 把檔案安裝到 /opt/usr/local 中。

不幸地,許多程式預設情況下並不遵守 FHS。尤其是,系統架構獨立的函式庫被放到 /usr/lib 而非 /usr/share 之中。前者是給系統架構依賴的函式庫使用,後者才是給系統架構獨立的函式庫運用;這代表不同 CPU 架構的系統都能共享 /usr/share 資料夾。Fedora 中也是有一些例外 (例如 Python 和 Perl),然而 Fedora 比起其他散佈版來說更嚴格遵守標準規範,rpmlint 一般會在你將 ELF 以外的檔案放進 /usr/lib 內時提出抱怨。

%files 範例

以下為 %files 區段的簡單範例:

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

找出重複檔案

您可以列出任兩個二進位軟體包的重複檔案,做法爲:

cd ~/rpmbuild/RPMS/ARCH # 請將 "ARCH" 替換為您的系統架構
rpm -qlp PACKAGE1.*.rpm | sort > ,1
rpm -qlp PACKAGE2.*.rpm | sort > ,2
comm -12 ,1 ,2

小指令稿 (Scriptlet)

當終端使用者在安裝 RPM 時,您可能想要執行一些指令。這可以透過小指令稿完成。請見 Packaging/ScriptletSnippets

小指令稿可以:

  • 在軟體包安裝之前 (%pre) 或之後 (%post) 執行
  • 在軟體包移除之前 (%preun) 或之後 (%postun) 執行
  • 在處理事項的開頭 (%pretrans) 或結尾 (%posttrans) 執行

舉例來說,每一會在任何 dinamic linker 預設路徑中儲存共享函式庫檔案的二進位檔 RPM 軟體包,都必須在 %post%postun 中呼叫 ldconfig。如果該軟體包有多個附帶函式庫的子軟體包,則每個軟體包也都應該執行相同的動作。

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

如果僅執行單一指令,則「-p」選項會執行相接的指令但不會喚起 shell。然而,若有許多指令時,請省去這個選項,並在其下納入 shell 指令。

如果你在小指令稿中有執行任何程式,你就必須以「Requires(CONTEXT)」(例: Requires(post)) 的形式來列出所有的執行需求。

%pre%post%preun、和 %postun 提供了 $1 引數,表示動作完成之後系統上留下的此名稱之軟體包有幾個。請不要拿這個值來比較是否等於 2,而是比較是否大於或等於 2。至於 %pretrans%posttrans$1 的值則恆為 0

舉例來說,如果軟體包安裝了一份 info manual (資訊手冊),那麼可以用 info 軟體包提供的 install-info 來更新資訊手冊索引。首先,我們不保證 info 軟體包總會存在,除非我們明確宣告它是必備的部分;再來,我們不想要在 install-info 失敗之時讓軟體包的執行動作完全失敗:

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

還有一件安裝資訊手冊時相關的小瑕疵。install-info 指令會更新資訊目錄,所以我們應該要在 %install 區段中刪掉 %{buildroot} 中無用的空目錄:

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

另一個類似小指令稿的能力是「triggers」(觸發器),可以在其他軟體包已安裝或已移除之時,為你的軟體包執行一些動作。請見 RPM Triggers

巨集 (Macro)

巨集是 %{string} 這類寫法的文字。典型的巨集有:

巨集 典型擴展 意義
%{_bindir} /usr/bin 二進位檔資料夾 (Binary directory):執行檔通常存放的位置。
%{_builddir} ~/rpmbuild/BUILD 建置資料夾 (Build directory):檔案放在建置目錄下的子目錄中編譯。請見 %buildsubdir
%{buildroot} ~/rpmbuild/BUILDROOT 建置根基 (Build root):在 %install 階段中的檔案「安裝」之處,會將 %{_builddir} 子目錄下的檔案複製到 %{buildroot} 的子目錄之下。(過去,%{buildroot} 所採用的位置是「/var/tmp/」。)
%{buildsubdir} %{_builddir}/%{name} 建置子資料夾 (Build subdirectory):在 %build 階段中檔案會在 %{_builddir} 的子目錄中編譯。這個位置會在 %autosetup 後設置。
%{_datadir} /usr/share 共用資料夾。
%{_defaultdocdir} /usr/share/doc 預設文件資料夾。
%{dist} .fcNUMBER 散佈版+版本短名 (例:「.fc41」)
%{fedora} NUMBER fedora 發行版號 (例:「41」)
%{_includedir} /usr/include
%{_infodir} /usr/share/info
%{_initrddir} /etc/rc.d/init.d
%{_libdir} /usr/lib
%{_libexecdir} /usr/libexec
%{_localstatedir} /var
%{_mandir} /usr/share/man
%{name} 軟體包的名稱,由 Name: tag 決定
%{_sbindir} /usr/sbin
%{_sharedstatedir} /var/lib
%{_sysconfdir} /etc
%{version} 軟體包版本,由 Version: tag 決定

您可以查看 /etc/rpm/*/usr/lib/rpm、甚至是 /usr/lib/rpm/macros 以進一步瞭解巨集。或是用 rpm --showrc 來顯示 RPM 運用這些巨集時所採用的值 (會根據 rpmrc 與巨集組態檔而有所變動)。

您可以利用 %global 來定義自己的巨集值,但是請確定在使用巨集之前先已定義過。(巨集在定義之時也可以指涉 (refer to) 其他巨集。) 範例:

%global date 2012-02-08

請用 rpmbuild 的「-E」選項來尋找巨集在 SPEC 檔中代表的值:

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

也請參見 Packaging/RPMMacrosRPM Guide chapter 9

其他標籤 (tag)

除了 Requires 和 BuildRequires 標籤之外,你還可以使用以下這些控制依賴關係:

  • Provides:列出此軟體包提供的虛擬軟體包名稱。例如,可能有個 foo 軟體包需要來自其他程式的「bar」功能;若有許多軟體包可以滿足該需求,則這些軟體包可以指定「Provides: bar」,而「foo」軟體包則可以指定「Requires: bar」。你也可以使用 "alternatives" 系統,但是若同個系統中有多位使用者,不同人可能希望使用不同的預設值,此時請避免使用它,畢竟這些設定屬於系統全域設定。請用「rpm -q --provides PACKAGENAME」來查看指定的軟體包提供那些東西。一些 Fedora 中虛擬軟體包的範例:
    • MTA:用作郵件傳輸代理 (mail transport agent, MTA),例如 sendmail。
    • tex(latex): 用作 latex
  • Obsoletes:當這個軟體包安裝時移除另一個指名的軟體包。當軟體包名稱更換之時,或是用該軟體包完全取代另一個不同的軟體包之時可以使用。
  • Conflicts:表示無法與此軟體包同時安裝的其他軟體包。如果可以請避免使用這個標籤。請見 Packaging/Conflicts
  • BuildConflicts:表示在建置此軟體包之時無法安裝的軟體包。如果可以請避免使用這個標籤。

若要處理不同的系統架構,有兩種標籤可以使用:

  • ExcludeArch:排除此軟體包無法建置的系統架構。例如:
ExcludeArch: ppc
  • ExclusiveArch:僅納入指定的系統架構。除非絕對正確,否則請避免使用。

可用的系統架構列在 Architectures 中。

子軟體包 (或稱細分包,Subpackage)

一份 SPEC 檔可以定義多份二進位檔軟體包。換句話說,一個內含一份 SPEC 檔的 SRPM 檔可能製作出許多 RPM 檔來。請注意到這依然只會有一道製作 (%prep、%build、%install 等) 程序。 name-docname-devel 為常見的文件檔和開發檔子軟體包。

請使用 %package 巨集指令來定義子軟體包:

%package subpackage_name

在每個 %package 指令之後,請列出該子軟體包的數個標籤 (tag)。這應該至少包括 Summary 和 Group 標籤、以及 %description subpackage_name%files subpackage_name 指令:

任何子軟體包中未特別指定到的東西,都會從其親代沿襲下來。

預設情況下,如果該軟體包的名稱為「foo」而子軟體包名稱為「bar」,則子軟體包成果則會是「foo-bar」。你可以利用「-n」選項 (但如果你在這裡特別指定的話,你也需要在所有其他的指令中用到這道指令) 來凌駕原先的規則:

%package -n new_subpackage_name

請見 RPM Guide 針對子軟體包所寫的小節瞭解更多資訊。

條件判斷 (Conditional)

你可以插入條件判斷陳述,例如測試你是否會為特定系統架構製作二進位檔:

%ifarch ARCHITECTURE_NAME

反面 (negated) 的論述版本為:

%ifnarch ARCHITECTURE_NAME

或更一般的條件判斷式:

%if TRUE_OR_FALSE

也有個可選擇性使用的「%else」區段;以上這些全都必須以「%endif」作結尾。

應用程式專門規約

有許多應用程式專門規約可以協助你 (例:專門的程式語言、應用程式、函式庫、建置系統等)。大多都列在 應用程式專用打包規約/規約 (英) 之中。一些應用程式專門規約的例子有:

如果上述的資訊都沒有涵括到,還有一些可以幫助你找到應用程式專用協助的方法:

其他注意事項 (Miscellaneous hints)

Packaging/FrequentlyMadeMistakes 有列出常見錯誤的相關資訊。PackageMaintainers/Packaging Tricks 則有列出一些建議、以及具爭議性的技巧。

請試著撰寫你的 SPEC 檔,盡可能讓上游發行新版本時一切都能水到渠成,使你除了要改版本號並刷新來源檔案外,都不必做任何其他修改。舉例來說,如果要替 *.txt 檔設執行位元,請不要用

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

而是考慮用以下這種方式來處理,可以直接處理使用相同命名規則的新檔名:

 chmod a-x *.txt

如果你想要查看大量的小指令稿範例,你可以利用下列指令來顯示所有已安裝程式的小指令稿:

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

請不要嘗試和使用者互動;RPM 是以支援批量安裝為設計核心。如果有個程式需要顯示 EULA 終端使用者授權協議,則該動作應是初次執行時才做,而非安裝之時做。

建議你不要試圖啟動服務,因為在大量安裝的過程中可能會讓一切變得緩慢。若你有安裝 init 或 systemd 指令稿,請考慮用 chkconfigsystemctl 來安排服務在下次重新開機之時啟動/停止該項服務。在解除安裝之前,如果這些服務還在跑,一般而言你應該先嘗試停止這些服務。

解除安裝應該要盡可能還原安裝階段中所做過的改變,但是不要移除任何使用自行建立的檔案。

一般而言,如果有二進位執行檔,則一般二進位軟體包應該剝離除錯用符號 (debugging symbols),並放到 name-debug 子軟體包中。如果不應發生這樣的事,你可以在你的 SPEC 檔頂端放入停用剝離動作:

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

若想避免剝離動作,你也需要在 %install 區段中做以下動作:

export DONT_STRIP=1

在 SPEC 檔中檢查 Fedora 版本作條件判斷式建置的方法:A way to check for the version of Fedora in a SPEC file for conditional builds is:

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

? 會讓巨集在 %fedora 未定義之時評斷為空白。這樣會讓結果成為 0 (數字零,所以很好),而 %fedora 若真的有個數值時也不會有所干擾。(請注意這種做法在 Koji 的「scratch」建置中沒有作用,%fedora 的值會在 SRPM 製作之時就設定好。)

GUI 程式必須有桌面條目 (desktop entry),這樣用戶才能從圖形化桌面選單中喚起這些程式。對於 .desktop 檔案,請見 Fedora packaging guidelines for desktop filesdesktop entry spec;至於 /usr/share/icons,請見 icon theme spec

建置二進位軟體包

利用 rpmlint 作測試

若要在早期捕捉個種常見錯誤,請在嘗試用 SPEC 檔建置任何軟體包之前先對它執行 rpmlint

$ rpmlint program.spec

如果回報的錯誤看起來不怎麼合理,請重新以「-i」選項執行以取得更詳細的訊息。

請以無報錯為目標,不過有時 rpmlint 會有誤報的情況發生。Fedora 打包規約 中有解釋到那些錯誤可以忽略。

以 SPEC 檔製作二進位 RPM 包

一旦你做好 SPEC 檔之後,請執行以下指令來建置 SRPM 與二進位 RPM:

$ rpmbuild -ba program.spec

如果製作成功,RPM 會放到 ~/rpmbuild/RPMS 裡面,而 SRPM 會放到 ~/rpmbuild/SRPMS 之內。

如果製作失敗,請前往對應的資料夾來看看留下了什麼。若想取得除錯協助,你可以用「--short-circuit」選項來略過早期的成功階段。例如:若想要 (略過更早期階段) 重新從 %install 階段開始,請執行:

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

若你只想要製作 SRPM 檔 (不會執行 %prep%build 或其他階段),請執行:

rpmbuild -bs program.spec

利用 rpmlint 來測試二進位 RPM 檔

rpmlint 可以對 SPEC 檔、RPM 檔、SRPM 檔執行來檢查是否存在錯誤。你需要在發佈軟體包之前解除或糾正發出的警告。這個網頁提供一些常見問題的解釋。如果你位於 SPEC 目錄中,請執行:

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

請進入 ~/rpmbuild/RPMS 目錄,再進入系統架構子目錄中。你會看到一些二進位檔 RPM。請用以下指令快速查看這些檔案和權限 (來檢查看看是否正確):

$ rpmls *.rpm

如果一切看起都很好,請以 root 身份安裝:

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

請以不同的方式來測試程式看是否全部都正常運作。如果它是 GUI 工具,請確認有出現在桌面選單中,否則代表 .desktop 條目可能有錯。

稍後可以利用以下指令來解除安裝軟體包:

# rpm -e package1 package2 package3

Mock 和 Koji

Mock 是在近乎空白的環境下,運用你剛製作的 SRPM 來建置二進位軟體包的強大工具。這可以揭露你實際的建置依賴關係。如果建置失敗,則代表你忘記在 BuildRequires 中列出其中一些東西。請參見 Using Mock to test package builds。一旦你的帳號屬於「mock」群組的成員之一,你可以執行這樣的指令來做本地端測試:

$ mock -r fedora-9-i386 rebuild path_to_source_RPM

你可以利用 Koji (會運用 mock) 在各種不同的系統上執行建置,包括那些你沒有的系統架構。PackageMaintainers/JoinPackageMaintainers/UsingKoji 上面有更多有關 Koji 的資訊。一旦設定完成,你就可以在各種平臺上使用以下指令來測試你的 SRPM:

$ koji build --scratch dist-f9 path_to_source_RPM

請將 dist-f9 以任意近期 Fedora 發行版本替換,但別使用 dist-rawhide。請記住,%fedora%fc9、等這類的值都不會在 scratch build 中得到修正,所以如果你的 SPEC 檔會依據上述值來做不同的事,則無法作用。

你的 Koji 建置僅能依賴 TARGET 散佈版軟體庫中實際存在的軟體包。所以,如果你的軟體包依賴 Bodhi 尚未發行的其他軟體包,就無法用 Koji 來為已發行的散佈版作建置。如果你需要對尚未成為穩定版的發行更新建置軟體包,請透過 Bodhi 提交 Koji 建置根基凌駕請求 (Koji buildroot override requet)。如果它並非你的軟體包依賴,請聯絡其維護者。[在 Bodhi 可以處理 Koji 建置根基凌駕請求之前,以前的舊方法是在此處對 rel-eng 提交請票 (ticket):https://fedorahosted.org/rel-eng/newticket ,並請求將該軟體包加入成為建置根基凌駕之一。]

有用的工具

rpmdevtools 軟體包有各種好用工具;「rpm -qil rpmdevtools」會展示給你看它會安裝哪些東西。

  • rpmdev-bumpspec:增進 SPEC 檔中的發行版本標籤,並以當下時間與版本格式加入 changelog 評註:
rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES

yum-utils 軟體包也提供一些好用工具:

  • yumdownloader:請執行以下指令下載該軟體包的 SRPM:
yumdownloader --source PACKAGENAME

auto-buildrequires 軟體包有一對優質工具可以幫助我們找出適當的 BuildRequires 條目。在安裝這個軟體包之後,請用「auto-br-rpmbuild」替換 「rpmbuild」,你就會看見自動產生的 BuildRequires 清單。

你可能發現到 RUST 滿好用的 (GPL),但是它無法製作出符合 Fedora 軟體包品質的 SPEC 檔。Alien 則可以在軟體包格式之間轉換;它無法製作出乾淨的 SRPM,但是從既有的軟體包轉換程式或許能提供一些有用的資訊。

最後,docker-rpm-builder (APL 2.0) 使用 Docker 來建置 RPM 軟體包;想用 rpmbuild 建置的目標架構需要與主控散佈版相同,至於 mock 則對於任何目標架構的 Fedora/Centos/RHEL 散佈版都能良好處理,這是無論 Docker 是否能跑都能運用的最後工作

若你想要為你的軟體包建置出不同的散佈版與系統架構,並且公開存取 yum 軟體庫,你可以提交你的 src.rpm 到 Copr

規約與規則

當你製作軟體包之時,你需要遵守下列規則與規約:

有許多官方規約可以引導你處理一些特定情況 (例:Java 程式、OCaml 程式、GNOME 程式等)。你也可以從 SIG 瞭解更多資訊,與 軟體包維護者 小節。

你也可以查看所有關於打包的 Wiki 頁面來看是否有適用的。

如果找不到,你可能想要找一些非官方的好用建議,例如 Packaging DraftsPackaging Drafts To Do

你也可以從 SuSEDebian 的資料中找到一些想法,但是 各個散佈版所用的規則會不同,所以不要直接想說他們的東西可以直接拿來用。

你製作的 .spec 檔必須是開源軟體,如 FPCA 中所提及。

維護軟體包

一旦你的軟體包被接受,你和你的共同維護者會需要維護這份軟體包。請見 Package update HOWTOPackage update guidelines。如果你在多個 Fedora 發行版中更新了它的版本,請即時往前做 (例:為 Fedora N 發行新版,一旦被接受,就做 Fedora N-1)。系統會假定新的 Fedora 版本會有相同版本或更後續版本的程式。

請鼓勵上游開發者使用標準源碼發行慣例。請使用標準慣例以便讓打包流程更輕鬆。若想要瞭解更多資訊,請見:

更多資訊

Package Maintainers 頁面連結到許多其他有用的網頁去,而 Package update HOWTO 則描述了如何更新你已經在 Fedora 中維護的既有軟體包。

若想瞭解更多資訊,在 Fedora Wiki 以外的地方,可以看看下面這些:

註:rpm5.org 網站也有提供一些文件,但是請不要依靠裡面的內容;那是 Jeff Johnson 維護的 RPM「分支」,也就是 fork。Fedora (和 Novell/SuSE) 所用的 RPM 則是基於 rpm.orglwn.net 有個簡要的文章報導這件事。