- Home
- Packages
- Forums
- Wiki
- Bugs
- AUR
- Download

# PKGBUILD (简体中文)

From ArchWiki

摘要
这篇文章详细说明了创建软件包时用到的 PKGBUILD 变量的含义。PKGBUILD 文件是描述软件如何编译及打包的一系列脚本。创建软件包和软件包开发分类中的文章介绍了安装函数和软件包常规信息。
概述
在 Arch Linux 中，软件包使用 makepkg 和一个自定义构建脚本（即PKGBUID)来创建。软件打包好后，就可以使用 pacman 安装与管理了。在官方软件仓库中PKGBUILD 可以从 ABS 树得到；更多的可以从 AUR 获取。
相关文章
Arch Packaging Standards (简体中文)
Creating Packages (简体中文)
Custom local repository (简体中文)
pacman Tips (简体中文)
PKGBUILD Templates
其它资源
PKGBUILD(5) Manual Page

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

PKGBUILD是一种 Arch Linux 在 创建软件包时使用的包构建描述文件。

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

## 变量

下面是一些在 PKGBUILD 文件里使用的变量。一般来说，这些变量按下面的顺序出现在 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)

### pkgrel

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

### epoch

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

### 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')`。并不需要列出那些你的软件包所依赖的二次依赖（原文：You do not need to list packages that your software depends on if other packages your software depends on already have those packages listed in their dependency.），比如说：gtk2 依赖 glib2 和 glibc，但是呢 glib2 已经依赖于 glibc，那么在 gtk2 中就不需要把 glibc 加入 depends 列表。

### makedepends

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

注意: 不需要指定`depends`中已经存在的依赖。
警告: 使用 makepkg 编译时 base-devel 组被视为已安装。"base-devel" 组的成员包 不应该 被包含在 `makedepends` 列表中。

### checkdepends

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

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

### 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 中的 `replaces=('ethereal')`。`pacman -Sy` 同步软件数据库后，会立刻用软件库中的另一个包替换掉 replaces 中已安装的包。如果你只是更新了已经存在的包，使用 `conflicts` 变量。

### backup

当包被卸载时的备份文件名。通用 `/etc` 放置配置文件。应该使用相对路径(如 `etc/pacman.conf`)，而不用绝对路径(如 `/etc/pacman.conf`)。

### options

这个变量允许你重置一些 makepkg 的默认行为。要设置一个选项必须指定选项名。要反转一个默认行为，在选项前加上 ! 。下面有几个可能使用到的选项名：

- strip - 建立二进制文件与库文件的符号连接。
- docs - 保存 /doc 目录。
- libtool - 保留 libtool (.la)。
- emptydirs - 保留软件包内的空目录。
- zipman - 用 gzip 格式压缩man 和 info 页。
- purge - 删除 `PURGE_TARGETS` 变量指定的软件包。
- upx - 使用 UPX 压缩二进制包。更多选项可以通过 `UPXFLAGS` 传给 UPX。
- ccache - 在构建时允许使用 ccache。 当为选定的包使用 ccache 出问题时，用!ccache 取消这个选项。
- distcc - 在构建时允许使用 distcc。 当为选定的包使用 distcc 出问题时，用 !distcc 取消这个选项。
- buildflags - 在构建时允许使用用户指定的 buildflags (CFLAGS, CXXFLAGS, LDFLAGS)。 当为选定的包使用自定义 buildflags 出问题时，使用 !buildflags 选项。
- makeflags - 在构建时允许使用用户指定的 makeflags 。 当为选定的包使用自定义 makeflags 出问题时，用 !makeflags 选项。

### install

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

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

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

小贴士: 一个原型 `.install` 文件可以在 `/usr/share/pacman/proto.install`查看。

### changelog

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

    pacman -Qc pkgname

Tip: `/usr/share/pacman/ChangeLog.proto` 提供了 changelog 的一个原型。

### source

构建软件包时需要的文件列表。它必须包含软件源的位置信息，大多数情况下是一个完整的 HTTP 或 FTP 地址。可以在软件源信息中很好的调用前面提到的变量 `pkgname` 和 `pkgver`(如 `source=(http://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

这是一个文件列表，这些文件不需要在执行 `makepkg` 时从 `source` 列表的软件压缩格式中提取出来。这种情况经常发生在解压某些不能被 `/usr/bin/bsdtar` 处理 zip 文件，因为 libarchive 是以流方式来处理所有文件，而不是像 unzip 那样随机访问。在这种情况下 `unzip` 应该加入 `makedepends` 序列，并且 `build()` 函数的第一行应该是：

    cd $srcdir/$pkgname-$pkgver
    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` 文件的目录下，使用指令 `makepkg -g` 简单而快速生成 MD5 序列。 需要注意的是 MD5 算法并不高明，所以你可以考虑使用一种很强大的替代方法。

### sha1sums

SHA-1 160位较验和序列。它是 md5sums 之处的另一个选择，但同样存在弱点。为了启用sha-1，请在 `/etc/makepkg.conf` 设置 `INTEGRITY_CHECK` 选项。参看 `man makepkg.conf`。

### sha256sums, sha384sums, sha512sums

SHA-2 较验和列表，有256，384 和 512位。它们都可以替代 md5sums，并且一般都认为它们更强大。为了启用这些算法，在 `/etc/makepkg.conf` 开启 `INTEGRITY_CHECK` 选项。详情请看 `man makepkg.conf`。

## 更多信息

- PKGBUILD 示例
- .install 示例

Retrieved from "https://wiki.archlinux.org/index.php?title=PKGBUILD_(简体中文)&oldid=247482"
Category:

- Package development (简体中文)

## Navigation menu