PKGBUILD

出自 ArchWiki
(重定向自 Pkgver

本文讨论了维护者在 PKGBUILD 中可定义的变量。有关 PKGBUILD 函数和创建软件包的常规信息,请参阅创建软件包。另请阅读PKGBUILD(5)

PKGBUILD 是一个 Bash 脚本,其中包含 Arch Linux 软件包所需的构建信息。

Arch Linux 中的软件包使用 makepkg 实用程序构建。当运行 makepkg 时,它会在当前目录中搜索 PKGBUILD 文件,并按照其中的说明编译或以其他方式获取文件以构建软件包归档文件—pkgname.pkg.tar.zst。生成的软件包包含二进制文件和安装说明,可以使用 pacman 轻松安装。

强制变量为 pkgnamepkgverpkgrelarchlicense 不是构建软件包的严格必要条件,但建议任何与他人共享的 PKGBUILD 都应包含此变量,因为如果不存在,makepkg 将会产生警告。

通常的做法是在 PKGBUILD 中按照此处给出的顺序定义变量。但是,这不是强制性的。

提示
  • 使用 namcap 检查 PKGBUILD 中常见的软件包错误。
  • 使用 shellcheck(1) 检查 PKGBUILD 中常见的脚本错误,另请参阅 SC2034SC2154
shellcheck --shell=bash --exclude=SC2034,SC2154 PKGBUILD

请参阅 /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")

注意: 如果上游使用时间戳版本控制(例如 30102014),请确保使用反向日期,即 20141030ISO 8601 格式)。否则,它不会显示为较新版本。
提示

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 提供对 i686pentium4 的支持,而 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 软件包指南#licenses 合并。

注意: PKGBUILD 格式不强制执行打包策略。(在 Talk:PKGBUILD 中讨论)

本文或本章节需要扩充。

原因:[1] 添加更多详细信息。(在 Talk:PKGBUILD 中讨论)

软件分发的许可证。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-ClauseMIT)引用它们,但随后提供相应的文件,就好像它是自定义许可证一样。

对于自定义许可证,如果它们不属于上面提到的常见家族,则标识符应为 LicenseRef-license-namecustom:license-name。相应的许可证文本必须放在目录 /usr/share/licenses/pkgname 中。要在 package() 部分中使用以下代码片段安装文件

install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
注意: pkgdir 变量由 makepkg 定义,有关更多信息,请参阅 PKGBUILD(5) § 打包函数

组合多个许可证或添加例外情况应遵循 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 中目录的名称——是可以接受的。

另请参阅 非自由应用程序软件包指南

有关自由和开源软件许可的更多信息和观点,请参阅以下页面

groups

软件包所属的。例如,当安装 plasma 时,它会安装该组中的所有软件包。

Dependencies

注意: 可以通过附加下划线和架构名称来添加其他特定于架构的数组,例如 optdepends_x86_64=()

depends

一个软件包数组,软件构建运行都必须安装它们。在 package() 函数内部定义的依赖项仅是软件运行所必需的。

可以使用比较运算符指定版本限制,例如 depends=('foobar>=1.8.0');如果需要多个限制,则可以为每个限制重复依赖项,例如 depends=('foobar>=1.8.0' 'foobar<2.0.0')

本文或本节是与 Arch 软件包指南 合并的候选对象。

注意: PKGBUILD 格式不强制执行打包策略。(在 Talk:PKGBUILD 中讨论)

depends 数组应列出所有直接的第一级依赖项,即使其中一些已经通过传递方式声明。例如,如果软件包 foo 依赖于 barbaz,而 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 工具(gitsubversioncvs 等)。
提示: 您可以使用 pactree -rsud1 package | grep base-devel 来检查特定软件包是否是 base-devel 的直接依赖项(需要 pacman-contrib)。

checkdepends

一个软件包数组,软件依赖它们来运行其测试套件,但在运行时不需要它们。此列表中的软件包遵循与 depends 相同的格式。只有当 check() 函数存在并且要由 makepkg 运行时,才会考虑这些依赖项。

注意: 使用 makepkg 构建时,假定已安装 base-devel 软件包。此软件包的依赖项不应包含在 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

一个附加软件包数组,软件提供这些软件包的功能,包括 虚拟软件包,例如 cronsh,以及 所有外部共享库。提供相同项目的软件包可以并排安装,除非至少其中一个软件包使用 conflicts 数组。

注意
  • 应提及软件包提供的版本(pkgver 以及可能的 pkgrel),以防引用该软件的软件包需要版本。例如,修改后的 qt 软件包版本 3.3.8,名为 qt-foobar,应使用 provides=('qt=3.3.8');省略版本号将导致需要特定版本 qt 的依赖项失败。
  • 不要将 pkgname 添加到 provides 数组,因为它会自动完成。

conflicts

一个软件包数组,如果安装了这些软件包,则它们会与该软件包冲突或导致问题。所有这些软件包和提供此项目的软件包都需要删除。冲突软件包的版本属性也可以使用与 depends 数组相同的格式指定。

请注意,冲突会针对 pkgname 以及 provides 数组中指定的名称进行检查。因此,如果您的软件包 providesfoo 功能,在 conflicts 数组中指定 foo 将导致您的软件包与所有其他在其 provides 数组中包含 foo 的软件包之间发生冲突(即,您不需要在 conflicts 数组中指定所有这些冲突软件包的名称)。让我们举一个具体的例子

  • netbeans 隐式地将其自身 pkgname 作为 netbeans 提供
  • 一个假设的 netbeans-cpp 软件包将提供 netbeans 并与 netbeans 冲突
  • 一个假设的 netbeans-php 软件包将提供 netbeans 并与 netbeans 冲突,但不需要显式地与 netbeans-cpp 冲突,因为提供相同功能的软件包隐式地存在冲突。

当软件包通过 provides 数组提供相同的功能时,显式地将备选软件包添加到 conflicts 数组和不添加它之间存在差异。如果显式声明了 conflicts 数组,则提供相同功能的两个软件包将被视为备选;如果缺少 conflicts 数组,则提供相同功能的两个软件包将被视为可能共存。封装者应始终忽略 provides 变量的内容,以决定是否声明 conflicts 变量。

replaces

一个已过时的软件包数组,这些软件包被此软件包替换,例如 wireshark-qt 使用 replaces=('wireshark')。同步时,pacman 在存储库中遇到另一个具有匹配 replaces 的软件包时,将立即替换已安装的软件包。如果提供已存在软件包的备用版本或上传到 AUR,请使用 conflictsprovides 数组,它们仅在实际安装冲突软件包时评估。

Others

backup

一个文件数组,这些文件可能包含用户所做的更改,应在软件包升级或删除期间保留,主要用于 /etc 中的配置文件。如果这些文件与软件包附带的文件相比未更改,则在升级或删除期间,它们将作为普通文件被删除或替换。

此数组中的文件应使用相对路径,不带前导斜杠 (/)(例如 etc/pacman.conf,而不是 /etc/pacman.conf)。backup 数组 不支持空目录或通配符,例如 "*"

更新时,新版本可能会另存为 file.pacnew,以避免覆盖已存在且先前由用户修改的文件。同样,删除软件包时,用户修改的文件将保留为 file.pacsave,除非使用 pacman -Rn 命令删除软件包。

另请参阅 Pacnew 和 Pacsave 文件

options

此数组允许覆盖 /etc/makepkg.conf 中定义的 makepkg 的某些默认行为。要设置选项,请在数组中包含名称。要禁用选项,请在其前面放置一个 !

可在 PKGBUILD(5) § OPTIONS AND DIRECTIVES 中找到可用选项的完整列表。

install

要包含在软件包中的 .install 脚本的名称。

pacman 能够在安装、删除或升级软件包时存储和执行软件包特定的脚本。该脚本包含以下在不同时间运行的函数

  • pre_install — 脚本在提取文件之前立即运行。传递一个参数:新软件包版本。
  • post_install — 脚本在提取文件之后立即运行。安装软件包后应打印的任何其他注释都应位于此处。传递一个参数:新软件包版本。
  • pre_upgrade — 脚本在提取文件之前立即运行。按以下顺序传递两个参数:新软件包版本、旧软件包版本。
  • post_upgrade — 脚本在提取文件之后立即运行。按以下顺序传递两个参数:新软件包版本、旧软件包版本。
  • pre_remove — 脚本在删除文件之前立即运行。传递一个参数:旧软件包版本。
  • post_remove — 脚本在删除文件之后立即运行。传递一个参数:旧软件包版本。

每个函数都在 pacman 安装目录内 chroot 环境中运行。请参阅 此线程

提示
注意: 不要以 exit 结束脚本。这将阻止包含的函数执行。

changelog

软件包变更日志的名称。要查看已安装软件包(具有此文件)的变更日志

$ pacman -Qc pkgname

Sources

source

构建软件包所需的文件数组。它必须包含软件源的位置,在大多数情况下是完整的 HTTP 或 FTP URL。先前设置的变量 pkgnamepkgver 可以在此处有效地使用;例如 source=("https://example.com/${pkgname}-${pkgver}.tar.gz")

文件也可以在 PKGBUILD 所在的同一目录中提供,并将其名称添加到此数组中。在实际构建过程开始之前,将下载或检查此数组中引用的所有文件是否存在,如果缺少任何文件,makepkg 将不会继续。

.install 文件会被 makepkg 自动识别,不应包含在 source 数组中。source 数组中扩展名为 .sig.sign.asc 的文件会被 makepkg 识别为 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 来规避。
  • 您可以使用 file:// URL 指向计算机文件系统中的目录或文件。例如,本地 Git 仓库可以指定为 "${pkgname}::git+file:///path/to/repository"
  • 可以使用 transmission-dlagentAUR 作为 DLAGENT 并使用 magnet:// URI 前缀而不是规范的 magnet:? 来添加 Magnet 链接支持。
  • 有关 VCS 特定选项的详细信息,例如定位特定的 Git 分支或提交,请参阅 PKGBUILD(5) § USING VCS SOURCESVCS package guidelines#VCS sources

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#签名检查 以获取更多信息。

完整性

这些变量是数组,其项是校验和字符串,将用于验证 source 数组中相应文件的完整性。您还可以为特定文件插入 SKIP,其校验和将不会被测试。

校验和类型和值应始终是上游提供的那些,例如在发布公告中。当有多种类型可用时,最好选择最强的校验和(从最优先到最不优先的顺序):b2sha512sha384sha256sha224sha1md5ck。这最好地确保了下载文件的完整性,从上游公告到软件包构建。

注意: 此外,当上游提供 数字签名 时,应将签名文件添加到 source 数组,并将 PGP 密钥指纹添加到 validpgpkeys 数组。这允许在构建时验证文件的真实性。

这些变量的值可以通过 makepkg-g/--geninteg 选项自动生成,然后通常使用 makepkg -g >> PKGBUILD 附加。来自 pacman-contribupdpkgsums(8) 命令能够更新 PKGBUILD 中任何位置的变量。这两个工具都将使用 PKGBUILD 中已设置的变量,或者在未设置任何变量的情况下回退到 md5sums

要使用的文件完整性检查可以通过 /etc/makepkg.conf 中的 INTEGRITY_CHECK 选项进行设置。请参阅 makepkg.conf(5)

注意: 可以通过附加下划线和架构名称来添加额外的特定于架构的数组,例如 sha256sums_x86_64=()

b2sums

具有 512 位摘要大小的 BLAKE2 校验和数组。

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)。