PKGBUILD (简体中文) - ArchWiki

# PKGBUILD (简体中文)

相关文章

- Arch packaging standards (简体中文)
- Arch Build System (简体中文)
- Creating packages (简体中文)
- Category:Package development
- Pacman tips (简体中文)
- AUR
- makepkg
- pacman

翻译状态： 本文是英文页面 PKGBUILD 的翻译，最后翻译时间：2014-12-06，点击这里可以查看翻译后英文页面的改动。

PKGBUILD是一种 Arch Linux 在 创建软件包时使用的包构建描述文件。其本质是一个shell脚本。

在 Arch Linux 中，创建包时要用到 makepkg 和放在 PKGBUILD 文件里的描述信息。当 makepkg 运行时，它会在当前目录寻找 `PKGBUILD` 文件，并依照其中的指令去获取依赖文件，之后编译出 `pkgname.pkg.tar.xz` 文件。生成的包内有二进制文件和安装指令，可以使用 pacman 指令安装它了。

本页面讨论PKGUILD中使用的变量。若要获取PKGBUILD中函数的信息，请参考Creating packages#PKGBUILD_Functions.

## 变量

下面是一些在 PKGBUILD 文件里使用的变量。`pkgname`，`pkgver`，`pkgrel`和`arch`是必须出现的。`license`在构建包时并不强制要求，但若您想要将PKGBUILD文件和他人分享，推荐您加上该变量。若该变量未设置，`makepkg`会警告您。 一般来说，这些变量按下面的顺序出现在 PKGBUILD 文件中，但这并不是强制性的，只要使用正确的 Bash 语法就行了。

### pkgname

软件包的名称，名称由小写字母、数字和任意以下字符组成：@ . _ + - (at 符号, 点, 下划线, 加号, 连字符)。字母均为小写且不能以连字符开头。为了保证一致性，`pkgname` 应该匹配源文件 tar 包的名称，比如：源文件包名为 `foobar-2.5.tar.gz`，那么 `pkgname` 的值应该是 foobar。除此之处，`PKGBUILD` 文件所在工作目录也应该与 `pkgname` 想匹配。

### pkgver

软件包的版本号，应该与软件原作者发布的版本号一致。它由字母、数字和'.'组成，但不能包含连字符'-'，如果原作者在他的版本号中使用了连字符'-'，那么用下划线'_'来替代。举个例子：原版本号“0.99-10”，改写成“0.99_10”。在之后的 PKGBUILD 指令中 `pkgver` 中的下划线可以用下面这个方法替代为连接符：

    source=("$pkgname-${pkgver//_/-}.tar.gz")

警告: 如果上游使用时间戳格式的版本，例如 05102014，请修改为年份在前的格式 20141005 (ISO 8601). 否则新版本判断会失效。

### pkgrel

软件包对 Arch Linux 的释出号。这个值可以用来区分同一版本软件的多次构建。当软件包第一次发布时，释出号为1，随着 `PKGBUILD` 的调整与优化，软件包再次发布，释出号递增 1。而当这个软件包发布一个新版本时，释出号重置为 1。

### pkgdir

该变量展示（设置）包中文件的根目录。它经常在`make DESTDIR="$pkgdir" install`中使用。PKGBUILD (`prepare()`, `build()`, `check()`, etc.) 的任何方法都不应该修改此值。

### epoch

这是一个针对 Arch Linux 的特别的整型值，用于比较软件的生命周期和版本号。这个值允许使用一般性的版本区分规则重写那些因降级，改变版本编号方式等因素而前后不一致的版本编号。默认情况下，软件包会假定这个值为 0。除非你明白自己在做什么，否则不要使用此变量。

用来强制使软件包被视为更新版本。该值越小，软件包版本就会被视为越新——即使软件版本号并不表现为更新。该值必须为一个正整数（若留空，则设置为0）。当一个软件的版本编号方式改变，打破正常的版本比较逻辑时，该变量尤其有用。参见pacman(8)来获取关于版本号比较的更多信息。

注意: 除非你完全明白自己在做什么，否则不要使用此变量

### pkgbase

当构建分开的包时可以使用一个可选的全局参考值。pkgbase用来指向软件包组，它们在makepkg的输出及纯源代码的包名中。若该变量未被设置，则用pkgname数组的第一个元素充当。PKGBUILD中的本全局变量是分包的所有选项和参考值的默认值。然而，一些参数可以在每个包的打包函数中被覆盖，它们是：pkgver，pkgrel，epoch，pkgdesc，arch，url，license，groups，depends，optdepends，provides，conflicts，replaces，backup，options，install以及changelog。此变量不允许以下划线开头。

### pkgdesc

软件包描述，最多80个字符并且不能包含软件包自身的名称。比如："Nedit is a text editor for X11"应该写成"A text editor for X11"。

注意: 提交软件包到 AUR 时，不必完全按照上面示例描述。如果软件包名称与应用程序名不一样，在描述中使用程序全名是保证软件包能够搜索到的唯一方法。

### arch

主机架构数组。当前，它应该包含 `i686`、`x86_64` 两者或其中之一，`arch=('i686' 'x86_64')`。值 `any` 用于不依赖架构的软件包。

在构建过程中，甚至是定义其它变量时都可以使用变量 `$CARCH` 来取得当前主机架构。另请参考FS#16352。例：

    depends=('foobar')
    if test "$CARCH" == x86_64; then
         depends+=('lib32-glibc')
    fi

### url

软件官方站点的网址

### license

软件发布许可证。软件包仓库 `[core]` 中的 licenses 包存放了通用的许可证协议，安装后能在 `/usr/share/licenses/common` 中找到这些许可证协议，比如 `/usr/share/licenses/common/GPL`。如果软件包是发布在这些许可证中的任何一个，这个值应该被设定成许可证的目录名，比如：`license=('GPL')`。如果官方 licenses 包中没有适用的许可证，可以按下的方法做：

1. 许可证文件应当放到 `/usr/share/licenses/pkgname/` 目录下，例如：`/usr/share/licenses/foobar/LICENSE`。
2. 如果源文件中没有包含证书的内容，而是保存在其它地方，比如说一个网站上，那么你需要把许可证内容拷贝到一个文件并在软件包中包含它。
3. 把 `custom` 添加到 `license` 列表。或者你可以用 `custom:name of license` 替代 `custom`。一旦某个许可证被官方仓库用于两个以上软件包（包括 `[community]`），它将成为 licenses 的一个组成部分。

- BSD、MIT、zlib/png 和 Python 是几个例外的情况，它们不能加入 licenses 包。在 `license` 列表中还是把它们当成通用协议来对待(`license=('BSD')`, `license=('MIT')`, `license=('ZLIB')` and `license=('Python')`)，但是实际上它们都是私有协议，因为它们都包括了各自的版权条款。任何发布于这四个许可协议的软件包都应该在 `/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`.

### groups

软件包所在的组。例如：当你安装 kdebase，它会安装属于 kde 组里的所有包。

### depends

软件的运行时依赖列表。可以使用比较运算符来描述版本限制，如：`depends=('foobar>=1.8.0')`。如有多重限制，你可以重复设置它们[1]，像这样：`depends=('foobar>=1.8.0' 'foobar<2.0.0')` 你并不一定要限制依赖包的版本。且并不需要列出你的软件包的二次依赖——你的软件及它所依赖的软件共同依赖的软件包。比如说：gtk2依赖{{pkg|glib2}和glibc；然而glib2本就依赖于glibc，那么在gtk2中就不需要把glibc加入 depends 列表。

### optdepends

一组不影响软件正常工作，但能提供额外特性的软件包。应该简要说明每个包所能提供的额外特性。`optdepends`看起来像这样：

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

### makedepends

软件编译时需要，但运行时并不依赖的包序列。可以像`depends`序列里提到的一样指定最小版本依赖。

注意: 不需要指定`depends`中已经存在的依赖。
警告: 在使用makepkg构建软件包时，base-devel组被视为已安装。该组的成员不应该出现在`makedepends`列表中。

### checkdepends

运行测试组件时需要，而运行时不需要的包列表。该列表中的包遵循和`depends`相同的格式。这些依赖只在check()函数存在且被makepkg运行时被考虑。

警告: 在使用makepkg构建软件包时，base-devel组被视为已安装。该组的成员不应该出现在`checkdepends`列表中。

### provides

这个变量说明当前包能替代的其它软件包（或者像 cron、sh 这样的虚拟包）。

如果你使用这个变量，应当加上所替代软件的版本号（`pkgver`，可能的话还有`pkgrel`）。举例来说，如果你提供一个修改过的 qt 包其版本号为 3.3.8，命名为 qt-foobar，那么 `provides` 应该写成 `provides=('qt=3.3.8')`。只写成 `provides=('qt')` 会使对 qt 有版本依赖的包编译失败。不要把 `pkgname` 加入 provides 序列，它会自动完成的。

### conflicts

与当前软件包发生冲突的包列表。可以像 depends 那样指定冲突包的版本号。

### replaces

会因安装当前包而取代的包列表，比如：wireshark-gtk中的`replaces=('wireshark')`。`pacman -Sy` 同步软件数据库后，会立刻用软件库中的另一个包替换掉 `replaces`中已安装的包。如果你只是提供已存在包的一个替代品，使用`conflicts`变量——该变量仅在安装冲突包时被检查。

### backup

当包被升级或卸载时，应当备份的文件（的名字）。这些文件一般是用户会更改的文件，如（主要是）放置在`/etc`中的配置文件。 在升级时，新版本会被命名为`file.pacnew`以避免覆盖旧有且被用户修改过的文件。类似地，当卸载包时，用户修改过的文件会以`file.pacsave`为名而保留下来——除非用`pacman -Rn`命令卸载。

列表中的文件应该使用相对路径(如 `etc/pacman.conf`)，而不是绝对路径(如 `/etc/pacman.conf`)。参见Pacnew and Pacsave files获取更多信息。

### options

这个变量允许你重置`makepkg`的部分默认（定义在`/etc/makepkg.conf`中的）行为。要设置一个选项必须指定选项名。要反转一个默认行为，在选项前加上`!` 。 参见`man PKGBUILD`以获取所有可用选项。

### install

`.install` 脚本的名称。pacman 可以在安装、卸载或升级一个软件包时存储及执行一些特定的脚本。在不同的情况下，脚本会执行下面几个函数。

- pre_install - 安装前运行的脚本，可以传递版本号为参数。
- post_install - 安装后运行的脚本，可以传递版本号为参数。
- pre_upgrade - 升级前运行的脚本，可以按`新版本号`，`旧版本号`的顺序传递参数。
- post_upgrade - 升级后运行的脚本，可以按`新版本号`，`旧版本号`的顺序传递参数。
- pre_remove - 卸载前运行的脚本，可以传递版本号为参数。
- post_remove - 卸载后运行的脚本，可以传递版本号为参数。

每一个函数都是在 pacman 安装目录下通过 chroot 运行。参见这个帖子.

小贴士: 一个 `.install` 文件模板（原型）可以在 `/usr/share/pacman/proto.install`查看。另有一个在线模板，参见pacman's gitweb page

### changelog

软件包 changelog 的名称，要查看安装软件的 changelog：

    pacman -Qc pkgname

小贴士: `/usr/share/pacman/ChangeLog.proto` 提供了一个 changelog 模板（原型）。

### source

构建软件包时需要的文件列表。它必须包含软件源的位置信息，大多数情况下是一个完整的 HTTP 或 FTP 地址。可以在软件源信息中很好的调用前面提到的变量 `pkgname` 和 `pkgver`(如 `source=("https://example.com/$pkgname-$pkgver.tar.gz")`)。

注意: 如果你想要提供不可以在线下载的文件(例如自己生成的补丁)，你只需要吧这些文件放到与 `PKGBUILD` 相同目录中，然后把文件名添加到这个列表中。任何路径都是以相对 `PKGBUILD` 的路径被解析。在实际的编译过程开始之前，所有该列表中引用的文件都会被下载或检查是否存在，如果有文件丢失 `makepkg` 就不会继续。
小贴士: 你可以为下载的文件指定不同的文件名（如将下载的文件出于某些原因有不同的文件名，像 URL 有一个 GET 参数时）。使用如下语法：`filename::fileuri`。

例如：

`$pkgname-$pkgver.zip::http://199.91.152.193/7pd0l2tpkidg/jg2e1cynwii/Warez_collection_16.4.exe`

### noextract

一些列举于 `source` 中，但不需要在运行`makepkg`时解包的文件。这种情况常发生在不能被`/usr/bin/bsdtar`处理的文件上——libarchive以流方式来处理所有文件，而不像unzip一样随机访问。在这些情况下，额外的解包工具（如`unzip`、`p7zip`等）应该加入 `makedepends` 序列，并且用prepare()函数手动解包。例如：

    unzip [source].zip

注意当 `source` 是一些 URL 时，`noextract` 仅仅取文件名部分。举例说明：可能像下面这样（截取自 grub2's PKGBUILD）：

    source=("https://ftp.archlinux.org/other/grub2/grub2_extras_lua_r20.tar.xz")
    noextract=('grub2_extras_lua_r20.tar.xz')

不提取任何东西时，可以像这样(截取自firefox-i18n)：

    noextract=("${source[@]%%::*}")

注意: 较保守的 Bash 替换应该包括调用 `basename` 的循环。如果你曾经读到过此内容，你应当明白在说什么。

### md5sums

`source` 列表中文的 MD5 校验和。一旦 `source` 序列中的所有文件都存在了，每个文件的 MD5 哈希值会自动的计算出来，并与对应 `source` 列表位置的 MD5 值相比较。源文件本身的顺序并不重要，重要的是要能与这个列表相匹配，因为 `makepkg` 并不能猜出哪个较验和虽于哪个源文件。你可以在包含 `PKGBUILD` 文件的目录下，使用指令 `updpkgsums` 简单而快速生成 MD5 序列。

注意: MD5 算法已被发现有弱点。你应当考虑从 SHA-2 家族中挑选一种更强大的替代方案——例如SHA-256。

### sha1sums

SHA-1 160位校验和序列。它是上面所说的 md5sums 之外的一个选择。为了启用sha-1，请在 `/etc/makepkg.conf` 设置 `INTEGRITY_CHECK` 选项。参见 `man makepkg.conf`。

注意: SHA-1算法已被发现有弱点。你应当考虑从 SHA-2 家族中挑选一种更强大的替代方案——例如SHA-256。

### sha256sums, sha384sums, sha512sums

SHA-2 校验和列表，有256，384 和 512位。它们都可以替代上述的 `md5sums` 和 `sha1sums`，并且有更少的已知弱点。为了启用这些算法，在 `/etc/makepkg.conf` 开启 `INTEGRITY_CHECK` 选项。详情请看 `man makepkg.conf`。

## 更多信息

- PKGBUILD(5) 手册页
- PKGBUILD 示例

Category:

- Package development (简体中文)