PKGBUILD
本文讨论了维护者可在 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
等提供了一个 语言服务器。
请参阅 /usr/share/pacman/
目录中的 .proto 文件作为示例。
软件包名称
pkgbase
在构建常规软件包时,不应在 PKGBUILD
中显式声明此变量:其值默认为 #pkgname 的值。
在构建拆分软件包时,此变量可用于显式指定名称,该名称将用于指代 makepkg 输出和仅源 tarball 命名中的软件包组。该值不允许以连字符开头。如果未指定,则该值将默认为 pkgname
数组中的第一个元素。
拆分软件包的所有选项和指令都默认为 PKGBUILD
中给出的全局值。但是,以下选项可以在每个拆分软件包的打包函数中被覆盖:#pkgdesc、#arch、#url、#license、#groups、#depends、#optdepends、#provides、#conflicts、#replaces、#backup、#options、#install 和 #changelog。
pkgname
软件包的名称,例如 pkgname=foo
,或者对于拆分软件包,名称数组,例如 pkgname=(foo bar)
。软件包名称应仅包含小写字母数字字符以及以下字符:@._+-
(at 符号、点、下划线、加号、连字符)。名称不允许以连字符或点开头。为了保持一致性,pkgname
应与软件的源 tarball 的名称匹配:例如,如果软件在 foobar-2.5.tar.gz
中,则使用 pkgname=foobar
。
版本
pkgver
软件包的版本。这应与上游软件作者发布的版本相同。它可以包含字母、数字、句点和下划线,但不能包含连字符 (-
)。如果软件作者使用连字符,请将其替换为下划线 (_
)。如果 pkgver
变量稍后在 PKGBUILD
中使用,则下划线可以很容易地替换为连字符,例如 source=("${pkgname}-${pkgver//_/-}.tar.gz")
。
- 可以使用 vercmp(8) 测试非常见值的排序,该命令由 pacman 软件包提供。
- makepkg 可以通过在
PKGBUILD
中定义pkgver()
函数来自动更新此变量。有关详细信息,请参阅 VCS 软件包指南#pkgver() 函数。
pkgrel
发布版本号。这通常是一个正整数,用于区分同一软件包版本的连续构建。当对影响生成软件包的 PKGBUILD
添加修复和附加功能时,pkgrel
应递增 1。当发布新版本的软件时,此值必须重置为 1。在特殊情况下,可能会发现使用其他格式,例如 major.minor。
epoch
epoch
仅应在绝对必要时使用。用于强制软件包被视为比任何先前版本的软件包更新,且 epoch 值更低。此值必须为非负整数;默认值为 0。当软件包的版本编号方案更改(或为字母数字)时,会使用此值,从而破坏正常的版本比较逻辑。例如
pkgver=5.13 pkgrel=2 epoch=1
1:5.13-2
有关版本比较的更多信息,请参阅 pacman(8)。
通用
pkgdesc
软件包的描述。建议长度不超过 80 个字符,并且不应以自引用的方式包含软件包名称,除非应用程序名称与软件包名称不同。例如,使用 pkgdesc='X11 文本编辑器'
而不是 pkgdesc='Nedit 是 X11 文本编辑器'
。
此外,明智地使用关键字以增加出现在相关搜索查询中的机会也很重要。
arch
PKGBUILD
旨在构建并在其上运行的架构数组。Arch 官方仅支持 x86_64
,但其他项目可能支持其他架构。例如,Arch Linux 32 提供对 i686
和 pentium4
的支持,Arch Linux ARM 提供对 armv7h
(armv7 hardfloat) 和 aarch64
(armv8 64 位) 的支持。
数组可以使用两种类型的值
arch=(any)
表示软件包可以在任何架构上构建,并且一旦构建,其编译状态与架构无关(通常是 shell 脚本、字体、主题、多种类型的扩展、Java 程序等)。arch=(...)
,其中一个或多个架构(但不是any
)表示软件包可以为任何指定的架构编译,但在编译后是特定于架构的。对于这些软件包,请指定PKGBUILD
官方支持的所有架构。对于官方仓库和 AUR 软件包,这意味着arch=('x86_64')
。可选地,AUR 软件包可以选择额外支持其他已知的工作架构。
在构建期间,可以使用变量 CARCH
访问目标架构。
url
被打包软件的官方网站 URL。
license
软件分发的许可证。Arch Linux 使用 SPDX 许可证标识符。每个许可证都必须在 /usr/share/licenses/
中具有相应的条目。
对于常见许可证(例如 GPL-3.0-or-later
),软件包 licenses 提供了所有相应的文件。该软件包默认安装,因为它是 base 元软件包的依赖项,这些文件可能在 /usr/share/licenses/spdx/
中找到。只需使用 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 条款发布一部分,根据 GNU/LGPL 2.1 发布另一部分,根据 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
中目录的名称)是可以接受的。
另请参阅 非自由应用程序软件包指南。
有关自由和开源软件许可证的更多信息和观点,请参见以下页面
- 维基百科:自由软件许可证
- 维基百科:自由及开放源代码软件许可证比较
- 开源和自由软件项目的法律问题入门
- 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,并且 foo 将在运行时崩溃或以其他方式行为不端。
在某些情况下,这并非必要,并且可以列出或不列出,例如 glibc 无法卸载,因为每个系统都需要一些 C 库,或者 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
来检查特定软件包是否是 base-devel 的直接依赖项(需要 pacman-contrib)。checkdepends
软件运行其测试套件所依赖的软件包数组,但在运行时不需要。此列表中的软件包遵循与 depends
相同的格式。仅当 check() 函数存在并且要由 makepkg 运行时,才考虑这些依赖项。
checkdepends
数组中。optdepends
软件运行不需要但提供附加功能的软件包数组。这可能意味着并非软件包提供的所有可执行文件都可以在没有各自 optdepends 的情况下运行。[3] 如果软件在多个备选依赖项上工作,则可以将它们全部列在此处,而不是 depends
数组中。
还应注明每个 optdepend 提供的额外功能的简短描述
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)和 所有外部共享库。提供相同项目的软件包可以并排安装,除非至少其中一个软件包使用 conflicts
数组。
- 应提及软件包提供的版本(
pkgver
和可能的pkgrel
),以防引用该软件的软件包需要版本。例如,修改后的 qt 软件包版本 3.3.8,命名为 qt-foobar,应使用provides=('qt=3.3.8')
;省略版本号将导致需要特定版本 qt 的依赖项失败。 - 不要将
pkgname
添加到provides
数组,因为它会自动完成。
conflicts
如果安装了软件包,则与软件包冲突或导致软件包出现问题的软件包数组。所有这些软件包和提供此项目的软件包都需要删除。也可以使用与 depends
数组相同的格式指定冲突软件包的版本属性。
请注意,冲突会针对 pkgname
以及 provides
数组中指定的名称进行检查。因此,如果您的软件包 provides
一个 foo
功能,则在 conflicts
数组中指定 foo
将导致您的软件包与所有其他在其 provides
数组中包含 foo
的软件包之间发生冲突(即,您无需在 conflicts
数组中指定所有这些冲突的软件包名称)。让我们看一个具体的例子
- netbeans 隐式地将
netbeans
作为pkgname
本身提供 - 假设的 netbeans-cpp 软件包将提供
netbeans
并与netbeans
冲突 - 假设的 netbeans-php 软件包将提供
netbeans
并与netbeans
冲突,但不需要显式地与 netbeans-cpp 冲突,因为提供相同功能的软件包隐式地存在冲突。
当软件包通过 provides
数组提供相同的功能时,显式地将备用软件包添加到 conflicts
数组与不添加它之间存在差异。如果显式声明了 conflicts
数组,则提供相同功能的两个软件包将被视为备选;如果缺少 conflicts
数组,则提供相同功能的两个软件包将被视为可能共存。打包者在决定是否声明 conflicts
变量时应始终忽略 provides
变量的内容。
replaces
被软件包替换的过时软件包数组,例如 wireshark-qt 使用 replaces=('wireshark')
。同步时,pacman 会在存储库中遇到另一个具有匹配 replaces
的软件包时立即替换已安装的软件包。如果提供现有软件包的备用版本或上传到 AUR,请使用 conflicts
和 provides
数组,这些数组仅在实际安装冲突软件包时评估。
其他
backup
可能包含用户所做更改的文件数组,应在软件包升级或删除期间保留,主要用于 /etc
中的配置文件。如果这些文件与软件包附带的文件相比未更改,则将在升级或删除期间作为普通文件删除或替换。
此数组中的文件应使用相对路径,不带前导斜杠 (/
)(例如 etc/pacman.conf
,而不是 /etc/pacman.conf
)。backup
数组不支持空目录或通配符(例如“*”)。
更新时,新版本可能会另存为 file.pacnew
,以避免覆盖已存在且先前被用户修改的文件。同样,当软件包被删除时,除非使用 pacman -Rn
命令删除软件包,否则用户修改的文件将保留为 file.pacsave
。
另请参阅 Pacnew 和 Pacsave 文件。
options
此数组允许覆盖 makepkg 的某些默认行为,这些行为在 /etc/makepkg.conf
中定义。要设置选项,请将名称包含在数组中。要禁用选项,请在其前面放置一个 !
。
可用选项的完整列表可以在 PKGBUILD(5) § OPTIONS AND DIRECTIVES 中找到。
install
要包含在软件包中的 .install 脚本的名称。
pacman 能够在安装、删除或升级软件包时存储和执行特定于软件包的脚本。该脚本包含以下在不同时间运行的函数
pre_install
— 在提取文件之前立即运行的脚本。传递一个参数:新软件包版本。post_install
— 在提取文件之后立即运行的脚本。安装软件包后应打印的任何其他注释都应位于此处。传递一个参数:新软件包版本。pre_upgrade
— 在提取文件之前立即运行的脚本。按以下顺序传递两个参数:新软件包版本、旧软件包版本。post_upgrade
— 在提取文件之后立即运行的脚本。按以下顺序传递两个参数:新软件包版本、旧软件包版本。pre_remove
— 在删除文件之前立即运行的脚本。传递一个参数:旧软件包版本。post_remove
— 脚本在文件移除后立即运行。传递一个参数:旧软件包版本。
每个函数都在 pacman 安装目录内以 chroot 环境运行。参见 此帖。
- 原型 .install 文件位于 /usr/share/pacman/proto.install。
- pacman#Hooks 提供类似的功能。
exit
结束脚本。这会阻止包含的函数执行。changelog
软件包更新日志的名称。要查看已安装软件包的更新日志(如果它们有此文件)
$ pacman -Qc pkgname
Sources
source
构建软件包所需的文件数组。它必须包含软件源的位置,在大多数情况下是一个完整的 HTTP 或 FTP URL。之前设置的变量 pkgname
和 pkgver
可以有效地在此处使用;例如 source=("https://example.com/${pkgname}-${pkgver}.tar.gz")
。
文件也可以放在与 PKGBUILD
相同的目录中,并将其名称添加到此数组。在实际构建过程开始之前,将下载或检查此数组中引用的所有文件是否存在,如果任何文件缺失,makepkg 将不会继续。
.install 文件会被 makepkg 自动识别,不应包含在 source
数组中。source
数组中扩展名为 .sig、.sign 或 .asc 的文件会被 makepkg 识别为 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"
。 - 可以使用 transmission-dlagentAUR 作为
DLAGENT
并使用magnet://
URI 前缀而不是规范的magnet:?
来添加 Magnet 链接支持。 - 请参阅 PKGBUILD(5) § USING VCS SOURCES 和 VCS package guidelines#VCS sources 以了解有关 VCS 特定选项的详细信息,例如定位特定的 Git 分支或提交。
noextract
source
下列出的文件数组,这些文件不应被 makepkg 从其存档格式中提取出来。这可以用于 /usr/bin/bsdtar
无法处理的存档,或者那些需要按原样安装的存档。如果使用了替代的解压缩工具(例如 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#签名检查 以获取更多信息。
Integrity
这些变量是数组,其项是校验和字符串,将用于验证 source 数组中相应文件的完整性。你也可以为特定文件插入 SKIP
,其校验和将不会被测试。
校验和类型和值应始终是上游提供的那些,例如在发布公告中。当有多种类型可用时,应首选最强的校验和(从最首选到最不首选的顺序):b2
、sha512
、sha384
、sha256
、sha224
、sha1
、md5
、ck
。这最好地确保了下载文件的完整性,从上游公告到软件包构建。
这些变量的值可以由 makepkg 的 -g
/--geninteg
选项自动生成,然后通常使用 makepkg -g >> PKGBUILD
附加。来自 pacman-contrib 的 updpkgsums(8) 命令能够更新 PKGBUILD
中任何位置的变量。这两个工具都将使用 PKGBUILD
中已设置的变量,或者在未设置任何变量的情况下回退到 md5sums
。
要使用的文件完整性检查可以使用 /etc/makepkg.conf
中的 INTEGRITY_CHECK
选项进行设置。参见 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 校验和数组。
cksums
source
数组中列出的文件的 CRC32 校验和数组(来自 UNIX 标准的 cksum
)。