創建軟件包

出自 Arch Linux 中文维基

本文旨在幫助用户利用 Arch Linux 的類似 ports 的軟件包構建系統創建自己的軟件包。包含了創建 PKGBUILD – 一個包創建描述文件,由 makepkg 使用來從原始碼創建二進制包。Arch 軟件包標準包含當前規則和提高軟件包質量的方法。如果已經有了 PKGBUILD 文件,請參考 makepkg.

概述[編輯 | 編輯原始碼]

Arch Linux 中的軟件包是通過 makepkg 工具以及存儲在 PKGBUILD 文件中的信息編譯的。運行makepkg時,系統將自動在當前目錄下搜索 PKGBUILD文件,然後根據PKGBUILD把軟件源碼重新打包。成功編譯後得到的二進制文件和可以得到的其他信息如包的版本信息和依賴關係等,都將被打包到一個文件叫name.pkg.tar.zst 裡,可以通過pacman -Up <package file>進行安裝。

一個 Arch 軟件包僅僅是一個使用 zstd(1) 壓縮的 tar 壓縮包,或者叫 'tarball'。它包含了以下由 makepkg 生成的文件:

  • 要安裝的二進制文件
  • .PKGINFO: 包含所有 pacman 處理軟件包的元數據,依賴等等。
  • .BUILDINFO: 包含可復現編譯需要的信息,僅在 pacman 5.1 及之後編譯的軟件包中。請參閱 BUILDINFO(5).
  • .MTREE: 包含了文件的哈希值與時間戳. pacman 能夠根據這些儲存在本地數據庫的信息校驗軟件包的完整性.
  • .INSTALL: 可選的文件,可以用來在安裝/升級/刪除操作之後運行命令。(本文件只有在 PKGBUILD 中制定才會存在。)
  • .Changelog: 一個可選的文件,保存了包管理員描述軟件更新的日誌。(不是所有包中都存在。)

準備工作[編輯 | 編輯原始碼]

必需的軟件包[編輯 | 編輯原始碼]

首先,確定你已安裝必須的工具包。安裝 base-devel 元軟件包 應該足夠了;它會引入 make 和其它一些編譯源碼時需要的工具。

創建包的一個很重要的工具是makepkg(由pacman提供),它主要做以下工作:

  1. 檢查相關依賴是否安裝。
  2. 從指定的伺服器下載源文件。
  3. 解壓源文件。
  4. 編譯軟件並將它安裝於偽root環境下。
  5. 刪除二進制文件和庫文件的符號連接。
  6. 生成包的meta文件。
  7. 將偽root環境壓縮成一個包文件
  8. 將生成的包文件保存到配置的文件夾中(默認為當前工作目錄)。

下載並測試安裝[編輯 | 編輯原始碼]

下載你想打包的軟件的原始碼壓縮包,解壓,按照作者所説的步驟安裝它。記錄下在編譯和安裝軟件過程中需要的所有命令或步驟。你將要在PKGBUILD文件中重複這些命令和步驟。

大多數軟件作者遵循三步走的安裝慣例:

./configure
make
make install

這是一個能確保程序正常運行的好時機。

創建PKGBUILD[編輯 | 編輯原始碼]

當你運行makepkg時,它會在當前工作目錄尋找一個PKGBUILD文件。如果找到PKGBUILD文件,它會下載該軟件的原始碼,根據PKGBUILD文件中的指令編譯它。PKGBUILD中的指令必須能完全被Bash解釋。成功完成後,最後的二進制文件和包的元信息(即包的版本、依賴)被一起打包在pkgname.pkg.tar.zst文件包中,這個文件包可以使用pacman -U <package file>來安裝。

要開始製作一個包,你應該先創建一個空工作目錄,進入該目錄,創建一個PKGBUILD文件。你可以複製PKGBUILD模板(位於/usr/share/pacman/)到工作目錄,或者複製一個類似包的PKGBUILD也可以。如果你只想在別人的基礎上更改一些選項的話,後一種方法比較方便。

定義PKGBUILD變量[編輯 | 編輯原始碼]

PKGBUILD文件的編寫例子可以在/usr/share/pacman/處找到。PKGBUILD文件中可能用到的一些變量意義的解釋可以在PKGBUILD中找到。

makepkg 定義了兩個變量,你應該在編譯和安裝的過程中使用它們:

srcdir
makepkg將會把源文件解壓到此文件夾或在此文件夾中生成指向 PKGBUILD 裡 source 數組中文件的軟連接。
pkgdir
makepkg會把該文件夾當成系統根目錄,並將軟件安裝在此文件夾下。

這些變量都是絕對路徑, 即意味着, 如果你合適地使用這些變量, 就不用擔心當前工作目錄的影響.

注意: build()package()函數在運行過程中都應當是非交互的。在這些函數中調用交互工具或腳本可能會中斷makepkg的運行。(參考FS#13214
注意: 如果你是接手別人的包,除了把你的名字列為包維護者(Maintainers)外,你還應當把之前的維護者列為貢獻者(Contributors)。

PKGBUILD 函數[編輯 | 編輯原始碼]

一共有五個函數, 以下按照它們執行的先後順序列出。package() 函數是每個 PKGBUILD 中必須的函數,其餘不存在的函數可以跳過。

prepare()[編輯 | 編輯原始碼]

此函數會執行用於預處理源文件以進行構建的命令, 例如 patching. 此函數執行在 build() 之前, 軟件包解壓之後. 如果解壓過程被跳過 (makepkg -e), 那麼 prepare() 函數就不會被執行.

注意: (從 PKGBUILD(5)) 中可以知道, 該函數運行在 bash -e 模式下, 意味着任何以非零狀態退出的命令都會造成該函數中止.

不清楚應該放到 prepare() 還是 build(), 只需要記得 prepare() 中的步驟僅在解壓後執行一次,而 build() 中的步驟會在每次編輯後都執行一次。

pkgver()[編輯 | 編輯原始碼]

pkgver() 會在抓取並解壓源文件,執行 prepare() 後後執行此函數。

為使用 git/svn/hg 等工具的項目打包時,由於它們的構建過程相同, 但源文件可能每天甚至每小時更新一次,這一特性將會十分有用。過去的方法是把日期寫入到 pkgver 變量中, 但這樣一來 makepkg 會在即使軟件沒有更新的情況下依然重新構建軟件包, 因為它會認為軟件包的版本改變了. 其他與此有關的命令有 git describe, hg identify -ni 等等. 請在提交 PKGBUILD 前做好測試, 因為如果 pkgver() 執行失敗, 整個構建過程都會終止.

注意: pkgver 不能含有空格或連接符 (-). 通常都會用 sed 來進行修改.

build()[編輯 | 編輯原始碼]

現在你需要編寫PKGBUILD文件中的build()函數。這個函數使用通用的shell命令來自動編譯軟件並創建軟件的安裝目錄。這允許makepkg無需詳查你的文件系統就可以打包你的軟件。

build()函數中第一步就是進入由解壓源碼包所生成的目錄。 makepkg 會在執行 build() 函數之前更改當前目錄為 $srcdir; 因此, 大多數情況下第一條命令是這樣的(參考示例文件/usr/share/pacman/PKGBUILD.proto):

cd "$srcdir/$pkgname-$pkgver"

現在,你需要把你當時手動編譯軟件時用到的命令一一列上。build()基本上會自動運行你當時手動輸入的命令並在偽root環境下編譯該軟件。如果你要打包的軟件使用了一個配置腳本,最好在配置中加上--prefix=/usr。許多軟件都將自己安裝到/usr/local下,我們僅僅推薦當你手動從源碼安裝時這麼做。所有的Arch Linux軟件包都應當使用/usr目錄。

./configure --prefix=/usr
make
注意: 如果你的軟件不需要構建任何東西, 請不要使用 build() 函數. 但package() 函數依然是必須的.

check()[編輯 | 編輯原始碼]

用來執行make check和其他一些例行測試的地方。如果不需要可以通過在 PKGBUILD/makepkg.conf 中使用 BUILDENV+=('!check') 或者給 makepkg 傳入參數 --nocheck 來禁用它。

package()[編輯 | 編輯原始碼]

最後一步就是把編譯好的文件放到pkg文件夾——一個簡單的偽root環境。pkg目錄複製了根目錄下軟件安裝路徑的繼承關係。如果你需要手動把文件放到根目錄下,那麼在這裏你需要把文件放在pkg下相同的文件層級結構中。比如,你想把一個文件安裝到/usr/bin,那麼在偽root環境中對應的路徑為$pkgdir/usr/bin。極少情況下的安裝步驟需要用户手動複製大量的文件到某個地方。大部分軟件安裝時只需要調用make install即可。為了將軟件安裝到正確的路徑,最後一行一般應該這樣寫:

make DESTDIR="$pkgdir/" install
注意: 有時候在Makefile裡沒有使用DESTDIR;你可能需要使用prefix來替代。如果軟件包是用autoconf/automake來創建的,那就使用DESTDIR;如果DESTDIR不起作用,試試make prefix="$pkgdir/usr/" install。如果這還不起作用的話,你就需要深入檢查軟件的安裝命令了。

makepkg --repackage 命令只運行package()函數,它只是將文件打包成軟件包,並不運行編譯過程。如果你只是更改了PKGBUILD中的依賴,用這個命令來打包可以節省很多時間。

測試PKGBUILD文件[編輯 | 編輯原始碼]

你在寫PKGBUILDbuild()方法時,會想頻繁的測試你所做的改動以確保沒有bug。你可以在包含 PKGBUILD的目錄下運行makepkg命令來確保沒有問題。如果PKGBUILD沒有錯誤,將會生成一個包,但是如果PKGBUILD被破壞或未完成,它將拋出一個錯誤。

如果運行makepkg 成功,在你工作的目錄下將會生成一個名為$pkgname-$pkgver.pkg.tar.gz的新文件。這個文件可以使用pacman -Upacman -A安裝,你也可以將它加到本地或網上的軟件倉庫中。注意,一個包被構建並不代表你的工作就完成了!只有當所有文件的結構都正確才能確保完成,例如你給了一個不正確的前綴就不行。你可以使用pacman的查詢功能顯示軟件包包含的文件及依賴的文件,然後將它於你認為正確的對比。"pacman -Qlp <package file>" 和"pacman -Qip <package file>" 可以完成這項工作。

如果包看起來是正確的,那你的工作就完成了。但是如果你打算發佈這個包或PKGBUILD,你就需要確認確認再確認包的依賴關係。

同樣要確保安裝的軟件確實很完美的運行!如果你釋放了一個包括所有必需文件的包,但是由於一些配置選項使它不能很好的工作,這真是讓人惱火。如果你只是為你自己的系統安裝這個軟件,你就不必做這個質量保證了,因為只有你一個人需要忍受這些錯誤。

檢查包的邏輯性[編輯 | 編輯原始碼]

確定包可以正常使用後,再使用namcap英語namcap來檢查錯誤:

$ namcap PKGBUILD
$ namcap <package file name>.pkg.tar.zst

Namcap將會做以下工作:

  1. 檢查PKGBUILD文件裡的一些常見錯誤
  2. ldd掃描包中所有的ELF文件,自動報吿缺失或可去除的依賴。
  3. 啟發式搜尋缺失或冗餘的依賴。

要養成用namcap檢查包的習慣,以避免提交包後再做修復的麻煩。

把包提交給AUR[編輯 | 編輯原始碼]

請參考AUR submission guidelines,裏面詳細介紹了提交流程。

總結[編輯 | 編輯原始碼]

  • 下載你希望打包的軟件原始碼
  • 試着編譯安裝包到任意目錄
  • 複製PKGBUILD的文件模板 /usr/share/pacman/PKGBUILD.proto到一個臨時的目錄並重命名為 PKGBUILD
  • 根據具體情況修改 PKGBUILD 文件
  • 運行 makepkg 看看輸出的打包結果是否正確
  • 如果不正確,重複前兩個步驟

注意事項[編輯 | 編輯原始碼]

  • 在開始自動打包之前,請確保你至少已成功手動打包一次,除非你「很清楚」你正在做什麼。不幸的是,雖然大多數軟件作者遵循了三步走的安裝慣例:./configure; make; make install,但事情並不都是這樣的,有時候你不得不自己打補丁才能安裝成功。經驗是:如果你手動無法編譯成功或者無法將軟件安裝到指定子目錄下,那你就不必費心打包了。makepkg沒有任何魔力能消除原始碼的問題讓你編譯成功。
  • 在一些情況下,你可能無法直接得到包的源碼,可能需要使用sh installer.run這樣的東西來工作。這時就需要你自己做很多工作了(比如讀READMEs,安裝指導,手冊,或者Gentoo的ebuilds等等)。在一些很變態的情況下,你需要自己編輯源碼才能正常安裝。但是,makepkg需要完全自主運行,不能有用户的干預。因此,如果你想修改makefiles,你需要隨PKGBUILD附上一個定製的補丁,然後在prepare()函數裏安裝這個補丁;或者你可以在prepare()函數裏通過sed來修改。

更詳細的規則[編輯 | 編輯原始碼]

Arch 打包準則

32 位CLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine

PKGBUILD 生成器[編輯 | 編輯原始碼]

某些軟件包的 PKGBUILD 可以通過工具自動生成。

注意: 用户需要在提交文件到 AUR 前確保軟件包滿足高質量標準。

參考[編輯 | 編輯原始碼]