PKGBUILD

出自 Arch Linux 中文维基

本頁面討論 PKGBUILD 中使用的變量。若要獲取關於PKGBUILD中的函數和創建軟件包的基本信息,請參考創建軟件包PKGBUILD(5)

PKGBUILD 是一個 shell 腳本,包含 Arch Linux 在構建軟件包時需要的信息。

Arch Linux 用 makepkg 構建軟件包。當 makepkg 運行時,它會在當前目錄尋找 PKGBUILD 文件,並依照其中的指令編譯或獲取所需的文件,並生成 pkgname.pkg.tar.zst 軟件包。生成的包內有二進制文件和安裝指令,可以使用 pacman 進行安裝。

pkgnamepkgverpkgrelarch 是必須定義的變量。license在構建包時並不強制要求,但若要分享PKGBUILD文件給其他人,推薦加上該變量。此外,如果不定義該變量, makepkg 會警吿缺失此變量。

一般來説,建議按照下面的順序在PKGBUILD文件中定義這些變量。但這並不是強制性的,只要使用正確的 Bash 語法就行了。

提示:

軟件包名稱[編輯 | 編輯原始碼]

pkgbase[編輯 | 編輯原始碼]

在建立常規的軟件包時,這個變量不應該在 PKGBUILD 文件中顯式指出。這個值默認會與 #pkgname 的值相同。

構建拆分包時,這個變量 pkgbase 可以在 makepkg 的輸出和純原始碼包中指定軟件包組。此變量不允許以下劃線開頭。若該變量沒有明確定義,則會默認對應到 pkgname 序列的第一個元素。

拆分軟件包中的所有選項和指令都默認使用全局 PKGBUILD 設置的值。以下選項可以在拆分包的打包函數中覆寫:#pkgdesc, #arch, #url, #license, #groups, #depends, #optdepends, #provides, #conflicts, #replaces, #backup, #options, #install, 和 #changelog

pkgname[編輯 | 編輯原始碼]

對於常規的軟件包,這個變量設定軟件包的名稱,例如 pkgname='foo'。對於拆分包則是一個名稱的序列,例如pkgname=('foo' 'bar')。名稱只能由由小寫字母、數字和@ . _ + - (at 符號、英文句點、下劃線、加號、連字符)構成,且不能以連字符或英文句點開頭。為了保證一致性,pkgname 應該與軟件的原始碼文件相匹配。比如:源文件包名為 foobar-2.5.tar.gz,那麼應該使用 pkgname=foobar

版本[編輯 | 編輯原始碼]

pkgver[編輯 | 編輯原始碼]

軟件包的版本號,應該與軟件上游發佈的版本號一致。變量的值可以由字母、數字和英文句點 .,下劃線 _ 組成,但不能包含連字符(-)。如果上游版本號中使用了連字符,則應該用下劃線 _ 來替代。在之後的 PKGBUILD 指令中pkgver 中的下劃線可以用下面這個方法替換回連字符:source=("$pkgname-${pkgver//_/-}.tar.gz")

注意: 如果上游使用時間戳格式的版本號,例如 30102014,請修改為年份在前的格式 20141030 (ISO 8601 格式)。否則新版本可能無法被系統識別出來是新的。
提示:

pkgrel[編輯 | 編輯原始碼]

軟件的發佈號。這通常是一個正整數,用來區分同一版本軟件的多次構建。當軟件包的補丁和附加功能被添加進入 PKGBUILD,從而導致生成的軟件包發生變化時,pkgrel 應該增加 1。而當這個軟件包發佈一個新版本時,發佈號重置為 1。在個別情況下,也會有其他的發佈號形式。比如 主版本號.次要版本號

epoch[編輯 | 編輯原始碼]

警吿: 除了特別、絕對、顯式要求需要這樣做,否則不允許使用 epoch 變量。

用於強制升級軟件包。在判定邏輯中,不論版本號如何,只要 epoch 值較大,就會被視為更新的軟件包。這個值應為非負整數,且默認值為0。通常當一個軟件的版本編號方式改變(或者使用某些字母-數字混編的版本符號),導致正常的版本比較邏輯無法進行時,會使用這個變量來控制升級。比如:

pkgver=5.13
pkgrel=2
epoch=1
1:5.13-2

更多關於版本比較的信息,參見 pacman(8)

一般變量[編輯 | 編輯原始碼]

pkgdesc[編輯 | 編輯原始碼]

軟件包描述。建議最多 80 個字符,並不要自己引用自己的名字,除非軟件包名和程序名不相同。比如:pkgdesc="Nedit is a text editor for X11" 應該被寫成 pkgdesc="Text editor for X11"

合理地在描述中使用關鍵字,這樣可以使軟件包在相關的搜索中出現的可能性增加。

arch[編輯 | 編輯原始碼]

一個描述能夠生成並運行該軟件包的架構的數組。Arch 官方僅支持 x86_64, 但是其它項目提供了其它架構支持。比如説,Arch Linux 32 提供了 i686pentium4 支持;Arch Linux ARM 項目提供 armv7h (帶有硬件浮點運算模塊的 armv7)和 aarch64 (64 位 armv8) 的支持。

這個數組有兩種形式:

  • arch=('any') 表明軟件包可以在任意架構上生成,並且一旦編譯完成,編譯時的架構就不再有影響了(例如 shell 腳本、字體、主題、各種擴展等)。
  • arch=('...') 包含一個或更多架構(any除外),表明這個軟件包可以在上述的任意架構上生成,但生成產物只能在編譯它的架構上運行。對於這些軟件包,您必須在 PKGBUILD 文件中指定所有官方支持的架構。對於官方軟件源和 AUR 軟件包,這指的是 arch=('x86_64')。不過,AUR 軟件包可以選擇添加一些已知的兼容架構的支持。

在生成過程中可以通過 $CARCH 變量來獲知目標架構。

url[編輯 | 編輯原始碼]

待打包軟件官方站點的網址。

license[編輯 | 編輯原始碼]

軟件分發所使用的許可證。軟件包 licenses(這個包是 base 的依賴項)中包含了許多常用的許可證協議,可以在 /usr/share/licenses/common 中找到。如果軟件包使用的是其中之一,這個值應該被設定成許可證的目錄名,比如 license=('GPL')。如果許可證不在上述文件夾中,則需要完成以下幾個步驟:

  1. custom 添加到 license 數組中。也可以用 custom:許可證名稱 來替代 custom。當一個許可證被兩個以上的官方倉庫的軟件包使用,它就會被添加到 licenses 軟件包中。
  2. 將許可證安裝到 /usr/share/licenses/pkgname/ 目錄下,例如 /usr/share/licenses/foobar/LICENSE。可以使用下面命令
    install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
    來實現。
  3. 如果許可證的內容僅保存在網站上,那麼你需要單獨保存一個版本。
  • BSDISCMITzlib/pngPythonOFL 是幾個例外的情況,它們不能加入 licenses 包,因為它們包含版權聲明[1]。在 license 序列中,可以按照常見許可證的方式來添加他們 (就是説,按照 license=('BSD'), license=('ISC'), license=('MIT'), license=('ZLIB'), license=('Python')license=('OFL') 來添加),但是技術上來講,這些都是自定義的許可證,因為這些許可證中都包含各自特定的版權聲明。任何以這五個許可協議分發的軟件包都應該在 /usr/share/licenses/pkgname 下存放它們的許可證文件。
  • 一些軟件包可能不止一個許可證,這種情況下,在 license 數組中置入多個值,比如説,license=('GPL' 'custom:name of license')
  • (L)GPL 許可證有很多版本和變種版本。對於一個 (L)GPL 軟件,約定如下:
    • (L)GPL - 指代 (L)GPLv2 或之後的任意版本
    • (L)GPL2 - 僅指代 (L)GPL2
    • (L)GPL3 - 指代 (L)GPL3 或之後的任意版本
  • 如果最終無法決定使用哪種許可證,PKGBUILD.proto 建議使用 unknown。但是這種情況下,應該聯繫上游的軟件發佈者,來確定這個軟件在哪些情況下是可以使用的。
提示:有些軟件作者沒有提供單獨的版權文件,而是在 ReadMe.txt 中聲明。可以在 build() 時將這些聲明提取為單獨文件,比如通過這條命令:sed -n '/This software/,/ thereof./p' ReadMe.txt > LICENSE

更多信息,請參考非自由軟件打包指引英語Nonfree applications package guidelines

關於自由/開源軟件協議的更多信息請參考:

groups[編輯 | 編輯原始碼]

軟件包所在的包組。例如:當你安裝 fcitx5-im包組,它會安裝 fcitx5-im包組裡的所有包。

依賴關係[編輯 | 編輯原始碼]

注意: 架構相關的額外依賴可以通過在名稱後添加下劃線和架構的方式指定。例如optdepends_x86_64=()

depends[編輯 | 編輯原始碼]

為了生成和運行軟件,而必須安裝的包列表。如果是只在運行時才依賴的包,請在 package() 函數中定義。

可以使用比較運算符來描述版本限制。例如 depends=('foobar>=1.8.0')。如有多重限制,你可以添加多條,例如 depends=('foobar>=1.8.0' 'foobar<2.0.0')

本文或本章節可能需要合併到Arch package guidelines

附註: PKGBUILD 格式並沒有強制執行某種打包標準。(在 Talk:PKGBUILD 中討論)

depends 應該列出所有的直接依賴,即使某個依賴項已經因為直接依賴的需要被間接引入時也應該如此。如果不這樣做,那麼會發生以下可能:如果一個軟件包 foo 依賴 barbaz 兩個軟件包,而 bar 軟件包也依賴於 baz 軟件包,當 bar 軟件包不再依賴於 baz 就極有可能會導致意外行為——pacman 不會在安裝 foo 軟件包時安裝 baz 軟件包,也會在清除孤兒軟件包時把 baz 清理掉。由於 baz 軟件包被依賴卻沒有被安裝,foo 可能崩潰或者發生運行錯誤。

但在一些情況下,上面所述的某些依賴是沒有必要或者不應該被列出的。比如説glibc,每個作業系統都需要 C 運行庫,因此它是不能夠被卸載的。又比如,當軟件包已經依賴於一個以 python- 開頭的模塊,就不需要再單獨依賴 python——因為 python- 開頭的模塊必定依賴於 python 軟件包,而且不允許從依賴列表中刪除。

通常的依賴應該包括生成所有可選功能所需的依賴。否則,對於任何依賴於額外軟件包的可選功能,應提供配置選項,並且默認禁用這些可選功能。如果不這樣做,會給軟件包添加了所謂"自動魔法依賴":一些生成時可選功能因為生成軟件包的機器上安裝的一些傳遞依賴或者不相關的軟件被意外啟用了,但是沒有表現在包的依賴中。

如果依賴的名稱寫成了庫的名稱(例如 depends=('libfoobar.so')),makepkg 會在編譯完成的包中嘗試尋找依賴這個庫的二進制文件,並添加二進制文件所需的 soname 版本號到依賴列表中。可以自己加上版本號來停用自動檢測,比如説 depends=('libfoobar.so=2')

makedepends[編輯 | 編輯原始碼]

僅在軟件生成時需要的軟件包列表。可以像depends序列裡提到的一樣指定依賴的版本限制。depends 序列裏面的軟件包默認也是生成時需要的,此處不應該重複。

注意:
  • 在使用 makepkg 構建軟件包時,默認 base-devel 已安裝。該包的依賴項不應該出現在 makedepends 列表中。
  • 如果使用VCS 源,記得要把對應的VCS工具(git, subversion, cvs等等)加進去
提示:用以下命令查看某個依賴項是否已經被 base-devel 直接依賴:pactree -rsud1 package | grep base-devel(需要安裝pacman-contrib)。

checkdepends[編輯 | 編輯原始碼]

運行軟件的測試組件時需要,而運行時不需要的包列表。該列表中的包遵循 depends 相同的格式。這些依賴只在 check() 函數存在,且被 makepkg 執行時會被處理。

注意: 在使用 makepkg 構建軟件包時,默認 base-devel 已安裝。該包的依賴項不應該出現在 checkdepends 列表中。

optdepends[編輯 | 編輯原始碼]

可選軟件包序列。這些可選軟件包不影響軟件主要功能,但能提供額外特性。這通常意味着除非安裝了對應的可選軟件包,該軟件包所提供的個別可執行文件可能無法正常使用[2]。如果軟件有一些替代依賴,您可以將其在此處全部列出,而不是 depends 列表中列出。

應該簡要説明每個包所能提供的額外功能,例如:

optdepends=('cups: printing support'
            'sane: scanners support'
            'libgphoto2: digital cameras support'
            'alsa-lib: sound support'
            'giflib: GIF images support'
            'libjpeg: JPEG images support'
            'libpng: PNG images support')

包關係[編輯 | 編輯原始碼]

注意: 架構相關的附加列表可以通過在變量名稱後添加下劃線和架構名字的方式指定。例如conflicts_x86_64=()

provides[編輯 | 編輯原始碼]

該列表説明的是本軟件包能夠提供列表中的包(或者像 cron、sh 這樣的虛擬包)所提供的功能。只要provides列表中的包都沒有聲明 conflicts,提供相同功能的軟件包就可以同時安裝。

注意: 如果需要使用這個變量,應當加上版本號(pkgver,可能的話還有pkgrel),特別是當依賴該軟件包的其他軟件對版本號特別敏感的時候。就是説,如果一個修改過的 qt 包其版本號為 3.3.8,命名為 qt-foobar,那麼 provides 應該寫成 provides=('qt=3.3.8')。如果忽略了版本號,會導致所有依賴於 qt 的某個特定版本的包編譯失敗。不要把 pkgname 加入 provides 序列。這個操作會自動進行。

conflicts[編輯 | 編輯原始碼]

這個列表描述的是與當前軟件包衝突的包,或者與該包同時存在會產生問題的包。安裝此軟件時,所有這個列表中的軟件包和提供這個功能的軟件包都會被刪除。可以像 depends 那樣指定衝突包的版本號。

需要注意的是,衝突檢查的對象是 pkgname 以及 provides 中的名字。因此,如果你的包 provides foo 功能,在 conflicts 中指定 foo 就會導致你的包和所有其他在 provides 中包含了 foo 的包衝突(也就是説,你不需要一個一個地指定所有衝突的包的名字)。例子是:

  • netbeans 提供 netbeans(因為 pkgname 就是如此)。
  • netbeans-cppAUR 提供 netbeans 功能,並和 netbeans 衝突。
  • netbeans-phpAUR 提供 netbeans 功能,而且和 netbeans 衝突,但是不需要再説明它與netbeans-cppAUR衝突,因為提供相同功能的包隱含了衝突關係。

當不同的包通過在provides列表中聲明的方式提供相同的功能,那麼是否特意在conflicts列表中添加可替換的包會產生不同的結果。特意説明的話,兩個包就會被認為是可相互替代的;如果conflicts列表不存在,那麼兩個包會被認為是「可能可以同時存在」。在決定是否需要聲明conflicts列表的時候,請忽略provides列表的內容,獨立決策。

replaces[編輯 | 編輯原始碼]

會因安裝當前包而取代的過時的包的列表。比如:wireshark-qt 中的 replaces=('wireshark')。在同步軟件數據庫後,pacman 會立刻用軟件庫中的另一個包替換掉 replaces 中已安裝的包。如果你只是提供已存在包的一個替代品,或者上傳到 AUR, 請不要使用 replace,而是使用 conflictsprovides 兩個變量——它們僅在安裝衝突軟件包時被檢查。

其它[編輯 | 編輯原始碼]

backup[編輯 | 編輯原始碼]

當包被升級或卸載時,應當備份的文件(的路徑)序列。這些文件一般是用户會更改的文件,如主要放置在 /etc 中的配置文件。

列表中的文件應該使用相對路徑,即不是以斜槓(/)開頭的(如 etc/pacman.conf 而不是 /etc/pacman.conf)。

在升級時,新版本會被命名為 file.pacnew 以避免覆蓋原來的被用户修改過的文件。當卸載包時,用户修改過的文件會以 file.pacsave 為名而保留下來——除非用 pacman -Rn 命令卸載。

參見 pacnew 和 pacsave 文件獲取更多信息。

options[編輯 | 編輯原始碼]

這個序列允許你重載 makepkg 的部分定義在 /etc/makepkg.conf 中的默認行為。要設置一個選項,請在序列中指定選項名。要禁用一個默認行為,則還需要在前面加上!

參見 PKGBUILD(5) 以獲取所有可用選項。

install[編輯 | 編輯原始碼]

需要包含在包中的 .install 腳本的名稱。

pacman 可以在安裝、卸載或升級一個軟件包時存儲及執行一些特定的腳本。腳本包含了下面幾個函數,並且在特定時刻執行它們:

  • pre_install - 釋放包中文件前運行的腳本。傳遞一個參數:新版本號。
  • post_install - 釋放包中文件後運行的腳本。傳遞一個參數:新版本號。
  • pre_upgrade - 釋放包中文件前運行的腳本。兩個參數按以下順序傳遞:新版本號,舊版本號。
  • post_upgrade - 釋放包中文件後運行的腳本。兩個參數按以下順序傳遞:新版本號,舊版本號。
  • pre_remove - 文件被刪除前運行的腳本,傳遞一個參數:舊版本號。
  • post_remove - 文件被刪除後運行的腳本,傳遞一個參數:舊版本號。

每一個函數都是 chrootpacman 安裝目錄下運行的。參見這個帖子.

提示:
注意: 腳本不要以 exit 結束,否則包含該腳本的函數無法執行。

changelog[編輯 | 編輯原始碼]

軟件包的更新日誌的文件名。要查看安裝軟件的更新日誌(如果有):

$ pacman -Qc pkgname

源碼[編輯 | 編輯原始碼]

source[編輯 | 編輯原始碼]

構建軟件包時需要的文件列表。它必須包含軟件源的位置,大多數情況下是一個完整的 HTTP 或 FTP 地址。您可以在此處調用前面提到的變量 pkgnamepkgver,來實現高效的命名。(如 source=("https://example.com/$pkgname-$pkgver.tar.gz"))。

文件也可以放到與 PKGBUILD 文件相同目錄,並將文件名添加到這個列表。在實際的編譯過程開始之前,所有該列表中引用的文件都會被下載或檢查是否存在,如果有文件丟失 makepkg 就不會繼續。

.install 文件會被 makepkg 自動識別,而不應該被包含在這個列表中。makepkg 會自動把 .sig, .sign.asc 結尾的文件當成 PGP 簽名,並自動驗證對應的源文件的完整性。

警吿: 因為所有包的 SRCDEST[損壞的連結:無效的章節] 的值可能相同,所以下載的文件的文件名需要唯一。比如説,如果一個項目只用版本號來命名,可能會與其他有相同版本號的不同項目衝突。在這種情況下,你可以為下載的文件指定不同的文件名:source=('unique_package_name::file_uri')。例如source=("$pkgname-$pkgver.tar.gz::https://github.com/coder/program/archive/v$pkgver.tar.gz")
注意:
  • 架構相關的額外相關性可以通過在名稱後添加下劃線和架構的方式指定。例如 source_x86_64=()。必須提供對應的完整性校驗和序列,例如 sha256sums_x86_64=()
  • 有些伺服器通過 User-Agent 來篩選並限制下載。這個限制可以通過 DLAGENTS 規避。

noextract[編輯 | 編輯原始碼]

一個在 source 中列出,但不應該在運行 makepkg 時被解包的文件列表。這通常包括那些壓縮文件不能被 /usr/bin/bsdtar 處理,或者本來就不需要解壓、按照原樣提供的文件。對於前者,需要將額外的解包工具(如unzipp7ziplrzip等)加入 makedepends 序列,並用 prepare() 函數手動解壓。例如:

prepare() {
  lrzip -d source.tar.lrz
}

注意當 source 是一些 URL 時,noextract 僅僅取文件名部分:

source=("http://foo.org/bar/foobar.tar.xz")
noextract=('foobar.tar.xz')

不提取任何東西時,可以像這樣:

  • 如果 source 只包含了純 URL,而沒有自定義的文件名是,將內容從最後一個斜槓之前像這樣從 source 序列中提出來:
noextract=("${source[@]##*/}")
noextract=("${source[@]%%::*}")

validpgpkeys[編輯 | 編輯原始碼]

PGP 指紋列表。如果使用,makepkg 僅接受這裏定義的簽名,並且忽略密鑰環中的值。如果原始碼用子密鑰簽名,makepkg 仍然會使用主密鑰進行比較。

此處僅接受完整的指紋。它們必須是大寫字母而且不能有空白字符。

注意: 可以使用 gpg --list-keys --fingerprint <KEYID> 查找 key 的合適指紋。

請參閱 Makepkg 驗證簽名了解簽名驗證過程的詳細信息。

完整性檢驗[編輯 | 編輯原始碼]

下面描述的這些序列中的變量是 source 序列中對應文件的校驗和。可以插入 SKIP 跳過某個不需要檢驗的文件。

校驗和的數值和版本應該始終使用上游,比如在新版本公吿中,提供的數值。當存在多種版本的時候,最好選用最強的校驗版本,也就是説,按照如下從強到弱的順序:sha256 > sha1 > md5。這樣可以最大限度地保證從上游的公吿到軟件包的生成整個流程中下載文件的完整性。

注意: 另外,當上游具備數字簽名文件時,這個簽名文件應該被添加到 source 序列中,PGP 密鑰添加到 validpgpkeys 序列中。這樣允許在生成軟件包時進行驗證。

makepkg-g/--geninteg 選項可以自動生成校驗值,通常可以通過 makepkg -g >> PKGBUILD 命令寫入。updpkgsums 也可以自動更新 PKGBUILD 中的數值。兩個工具都會自動檢測 PKGBUILD 中的算法, 如果兩個都沒找到就回滾到 md5sums

注意: 架構相關的額外完整性檢驗可以通過在名稱後添加下劃線和架構的方式指定。例如sha256sums_x86_64=()

md5sums[編輯 | 編輯原始碼]

source 列表文件中的 128 位 MD5 校驗和。

sha1sums[編輯 | 編輯原始碼]

source 列表文件中 SHA-1 160 位校驗和。

sha256sums[編輯 | 編輯原始碼]

256 位 SHA-2 校驗和。

sha224sums, sha384sums, sha512sums[編輯 | 編輯原始碼]

SHA-2 校驗和列表,分別對應224,384 和 512 位。這些是較為不常見的 sha256sums 替代品。

b2sums[編輯 | 編輯原始碼]

512 位 BLAKE2 校驗和。

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