本頁面討論 PKGBUILD
中可由維護者定義的變量。若要獲取關於 PKGBUILD
中的函數和創建軟體包的基本信息,請參考創建軟體包和 PKGBUILD(5)。
PKGBUILD
是一個 Bash 腳本,包含在構建 Arch Linux 軟體包時需要的信息。
Arch Linux 使用 makepkg 構建軟體包。當 makepkg 運行時,它會在當前目錄尋找 PKGBUILD
文件,並依照其中的指令編譯或獲取所需的文件,並生成 pkgname.pkg.tar.zst
軟體包。生成的包內有二進制文件和安裝指令,可以使用 pacman 進行安裝。
必須定義的變量有 pkgname
,pkgver
,pkgrel
和 arch
。在構建軟體包時不強制要求定義 license
,但若要分享 PKGBUILD
文件給其他人,推薦加上該變量,否則 makepkg 會提示相關報錯。
一般來說,建議但不強制要求按照下面的順序在 PKGBUILD
文件中定義這些變量。
- 使用 namcap 來檢查
PKGBUILD
文件中的常見打包問題。 - 可以使用 shellcheck(1) 來檢查
PKGBUILD
中的常見語法錯誤,並排除 SC2034 和 SC2154:
shellcheck --shell=bash --exclude=SC2034,SC2154 PKGBUILD
-
termux-language-serverAUR 為
PKGBUILD
和makepkg.conf
等提供了一個語言伺服器。
軟體包名稱
pkgbase
在構建常規的軟體包時,不應該在 PKGBUILD
文件中顯式定義該變量,這個值默認會與 #pkgname 的值相同。
構建拆分包時,這個變量可用於在 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")
。
- 不常用變量的順序可以通過 pacman 軟體包提供的 vercmp(8) 進行測試。
- 在
PKGBUILD
中定義pkgver()
函數,makepkg 就可以自動更新此變量。詳情參閱 VCS 軟體打包準則#pkgver() 函數。
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 提供了 i686
和 pentium4
支持;Arch Linux ARM 項目提供 armv7h
(帶有硬體浮點運算模塊的 armv7)和 aarch64
(64 位 armv8) 的支持。
這個數組有兩種形式:
-
arch=('any')
表明軟體包可以在任意架構上生成,並且一旦編譯完成,編譯時的架構就不再有影響了(例如 shell 腳本、字體、主題、各種擴展、Java 程序等)。
-
arch=(...)
包含一個或更多架構(any
除外),表明這個軟體包可以在上述的任意架構上生成,但生成產物只能在編譯它的架構上運行。對於這些軟體包,您必須在PKGBUILD
文件中指定所有官方支持的架構。對於官方軟體源和 AUR 軟體包,這指的是arch=('x86_64')
。不過,AUR 軟體包可以選擇添加一些已知的兼容架構的支持。
在生成過程中可以通過 $CARCH
變量來獲知目標架構。
url
待打包軟體官方站點的網址。
license
軟體分發所使用的許可證。Arch Linux 使用 SPDX 許可證標識符,所有許可證都需在 /usr/share/licenses/
下有對應項。
licenses包 包含了常見許可證(例如 GPL-3.0-or-later
)的對應文件,默認已作為 base包 元軟體包的依賴之一安裝在 /usr/share/licenses/spdx/
目錄下,使用時只需引用 SPDX 標識符清單中的標識符。
類似 BSD 或 MIT 的許可證族嚴格來說不是特定的單個許可證,每個實例都需要獨立的許可證文件。對於這些許可證,需要在 license
中使用通用 SPDX 標識符(例如 BSD-3-Clause
或 MIT
),並像自定義許可證一樣提供對應的許可證文件。
對於自定義許可證,如果其不屬於常見許可證族,就需要使用 LicenseRef-license-name
或 custom:license-name
作為標識符。對應的許可證文件必須放置在 /usr/share/licenses/pkgname
目錄下。可以在 package()
中使用如下代碼安裝許可證文件:
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
pkgdir
變量由 makepkg 定義,具體信息請參考 PKGBUILD(5) § PACKAGING FUNCTIONS。如果要結合多個許可證或添加例外,需要遵循 SPDX 語法。例如,如果軟體包發布於 GNU/GPL 2.0 或 GNU/LGPL 2.1,需要使用 'GPL-2.0-or-later OR LGPL-2.1-or-later'
;如果軟體包發布於 Apache 2.0 並帶有 LLVM 例外,需要使用 'Apache-2.0 WITH LLVM-exception'
;如果軟體包部分發布於 BSD 3 clause,其它部分發布於 GNU/LGPL 2,還有一部分發布於 GNU/GPL 2.0,就需要使用 'BSD-3-Clause AND LGPL-2.1-or-later AND GPL-2.0-or-later'
[2]。注意,這需要是單個字符串,因此需要將整個表達式用引號括起來。截至 2023 年 11 月為止,SPDX 例外列表還非常有限,因此你通常還是需要遵循添加自定義許可證的方式。
如果在 SPDX 標識符方面遇到問題,可以在過渡期間使用舊標識符(/usr/share/licenses/common
中的目錄名稱)。
另請參考 Nonfree applications package guidelines。
有關自由和開放源碼軟體許可證的更多信息和觀點,請參閱以下網頁:
- Wikipedia:Free software licence
- zhwp:自由及開放原始碼軟體許可協議比較
- 開源和自由軟體項目法律問題入門指南
- GNU 項目 - 各類許可證及其評論
- Debian - 許可證信息
- 開放原始碼促進會 - 許可證清單
groups
軟體包所在的軟體包組。例如:當你安裝 plasma包組,它會安裝組裡的所有包。
依賴關係
optdepends_x86_64=()
。depends
為了生成和運行軟體,而必須安裝的包列表。如果是只在運行時才依賴的包,請在 package()
函數中定義。
可以使用比較運算符來描述版本限制。例如 depends=('foobar>=1.8.0')
。如有多重限制,你可以添加多條,例如 depends=('foobar>=1.8.0' 'foobar<2.0.0')
。
depends
應該列出所有的直接依賴,即使已由某個依賴項間接引入時也應該如此。如果不這樣做,那可能會發生以下情況:如果一個軟體包 foo 依賴 bar 和 baz 兩個軟體包,而 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包 等等)加進去。
pactree -rsud1 package | grep base-devel
(需要安裝 pacman-contrib包)。checkdepends
運行軟體的測試組件時需要,而運行時不需要的包列表。該列表中的包遵循 depends
相同的格式。這些依賴只在 check() 函數存在,且被 makepkg 執行時會被處理。
checkdepends
列表中。optdepends
可選軟體包序列。這些可選軟體包不影響軟體主要功能,但能提供額外特性。這通常意味著除非安裝了對應的可選軟體包,該軟體包所提供的個別可執行文件可能無法正常使用[3]。如果軟體有一些替代依賴,您可以將其在此處全部列出,而不是 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
,而是使用 conflicts
和 provides
兩個變量 —— 它們僅在安裝衝突軟體包時被檢查。
其它
backup
當包被升級或卸載時,應當保留的文件(的路徑)序列。這些文件一般是用戶會更改的文件,如主要放置在 /etc
中的配置文件。如果在安裝軟體包後這些文件沒有被修改過,那麼它們會隨升級和移除軟體包時一同被替換或刪除。
列表中的文件應該使用相對路徑,即不是以斜槓(/
)開頭的路徑(如 etc/pacman.conf
而不是 /etc/pacman.conf
)。backup
數組不支持空目錄和類似「*」的通配符。
在升級時,新版本會被命名為 file.pacnew
以避免覆蓋原來的被用戶修改過的文件。當卸載包時,用戶修改過的文件會以 file.pacsave
為名而保留下來 —— 除非用 pacman -Rn
命令卸載。
參見 pacnew 和 pacsave 文件獲取更多信息。
options
參見 PKGBUILD(5) § OPTIONS AND DIRECTIVES 以獲取所有可用選項。
install
需要包含在包中的 .install 腳本的名稱。
pacman 可以在安裝、卸載或升級一個軟體包時存儲及執行一些特定的腳本。腳本包含了下面幾個函數,並且在特定時刻執行它們:
-
pre_install
- 提取包中文件前運行的腳本。會傳遞一個參數:新版本號。 -
post_install
- 提取包中文件後運行的腳本。安裝軟體包後輸出的提示信息需放置於該函數內。會傳遞一個參數:新版本號。 -
pre_upgrade
- 提取包中文件前運行的腳本。兩個參數會按以下順序傳遞:新版本號,舊版本號。 -
post_upgrade
- 提取包中文件後運行的腳本。兩個參數會按以下順序傳遞:新版本號,舊版本號。 -
pre_remove
- 文件被刪除前運行的腳本,會傳遞一個參數:舊版本號。 -
post_remove
- 文件被刪除後運行的腳本,會傳遞一個參數:舊版本號。
每一個函數都是 chroot 到 pacman 安裝目錄下運行的。參見這個帖子.
- 可以在 /usr/share/pacman/proto.install 這裡找到一個
.install
文件的模板(原型)。 - Pacman 鉤子也提供相似的功能。
exit
結束,否則包含該腳本的函數無法執行。changelog
軟體包的更新日誌的文件名。要查看安裝軟體的更新日誌(如果有):
$ pacman -Qc pkgname
源碼
source
構建軟體包時需要的文件列表。它必須包含軟體源的位置,大多數情況下是一個完整的 HTTP 或 FTP 地址。您可以在此處調用前面提到的變量 pkgname
和 pkgver
,來實現高效的命名(如 source=("https://example.com/${pkgname}-${pkgver}.tar.gz")
)。
文件也可以放到與 PKGBUILD
文件相同目錄,並將文件名添加到這個列表。在實際的編譯過程開始之前,所有該列表中引用的文件都會被下載或檢查是否存在,如果有文件丟失 makepkg 就不會繼續。
.install 文件會被 makepkg 自動識別,而不應該被包含在這個列表中。makepkg 會自動把 source
中 .sig,.sign 或 .asc 結尾的文件當成 PGP 簽名,並自動驗證對應的源文件的完整性。
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 規避。
- 可以使用
file://
URL 來指向本地目錄或文件,例如指定本地 Git 倉庫:"${pkgname}::git+file:///path/to/repository"
。 - Magnet link support can be added using transmission-dlagentAUR as
DLAGENT
and using themagnet://
URI prefix instead of the canonicalmagnet:?
. - See PKGBUILD(5) § USING VCS SOURCES and VCS 軟體打包準則#VCS 原始碼 for details on VCS specific options, such as targeting a specific Git branch or commit.
noextract
一個在 source
中列出,但不應該由 makepkg 解包的文件列表。這通常包括那些不能被 /usr/bin/bsdtar
處理的壓縮文件,或者本來就不需要解壓、按照原樣提供的文件。對於前者,需要將額外的解包工具(如 unzip
,p7zip
,lrzip包 等)加入 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[@]##*/}")
- 如果
source
只包含了帶自定義文件名的項,將內容從分隔符::
之前像這樣從source
序列中提出來(這是從舊版 firefox-i18n 的 PKGBUILD 中找到的):
noextract=("${source[@]%%::*}")
validpgpkeys
PGP 指紋列表。如果使用,makepkg 僅接受這裡定義的簽名,並且忽略密鑰環中的值。如果原始碼用子密鑰簽名,makepkg 仍然會使用主密鑰進行比較。
此處僅接受完整的指紋。它們必須是大寫字母而且不能有空白字符。
gpg --list-keys --fingerprint KEYID
查找密鑰的指紋。請參閱 makepkg#驗證簽名了解簽名驗證過程的詳細信息。
完整性檢驗
下面描述的這些序列中的變量是 source 序列中對應文件的校驗和。可以插入 SKIP
跳過某個不需要檢驗的文件。
校驗和的類型和數值應該始終使用上游提供的數值(比如在新版本公告中的)。當存在多種類型的時候,最好選用最強的校驗類型。類型按照從強到弱的順序如下:b2
> sha512
> sha384
> sha256
> sha224
> sha1
> md5
> ck
,這樣可以最大限度地保證從上游的公告到軟體包的生成整個流程中下載文件的完整性。
makepkg 的 -g
/--geninteg
選項可以自動生成校驗值,通常可以通過 makepkg -g >> PKGBUILD
命令寫入。pacman-contrib包 提供的 updpkgsums(8) 命令也可以更新 PKGBUILD
中的變量。兩個工具都會自動檢測 PKGBUILD 中的算法, 如果沒找到就回滾到 md5sums
。
The file integrity checks to use can be set up with the INTEGRITY_CHECK
option in /etc/makepkg.conf
. See makepkg.conf(5).
sha256sums_x86_64=()
。b2sums
BLAKE2 校驗和數組,大小為 512 位。
sha512sums,sha384sums,sha256sums,sha224sums
SHA-2 校驗和數組,大小分別為 512,384,256 和 224 位。最常見的是 sha256sums
。
sha1sums
source
數組中文件的 160 位 SHA-1 校驗和數組。
md5sums
source
數組中文件的 128 位 MD5 校驗和數組。