PKGBUILD (简体中文)

From ArchWiki
Jump to: navigation, search
翻译状态: 本文是英文页面 PKGBUILD翻译,最后翻译时间:2016-06-29,点击这里可以查看翻译后英文页面的改动。

PKGBUILD是一个shell脚本,包含 Arch Linux 在构建软件包时需要的信息。本页面讨论PKGUILD中使用的变量。若要获取PKGBUILD中函数的信息,请参考创建软件包man PKGBUILD.

Arch Linux 用 makepkg 创建软件包。当 makepkg 运行时,它会在当前目录寻找 PKGBUILD 文件,并依照其中的指令去获取依赖文件,编译出 pkgname.pkg.tar.xz 文件。生成的包内有二进制文件和安装指令,可以使用 pacman 进行安装。

pkgnamepkgverpkgrelarch是必须包含的变量。license在构建包时并不强制要求,但若要分享 PKGBUILD文件,推荐加上该变量,否则 makepkg 会有警告。

一般来说,这些变量按下面的顺序出现在 PKGBUILD 文件中,但这并不是强制性的,只要使用正确的 Bash 语法就行了。

软件包名称

pkgbase

构建拆分包时,可以使用一个可选的全局参考值。pkgbase可以在 makepkg 输出和纯源代码包中指定软件包组。若该变量未被设置,则用pkgname数组的第一个元素充当。此变量不允许以下划线开头。拆分软件包中的所有变量都默认使用全局 PKGBUILD 设置的值。除了makedepends,source variables, integrity variables, 其他变量都可以在拆分包的 package() 函数中进行额外设置。

pkgname

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

拆分包中应该使用数组:pkgname=('foo' 'bar').

版本

pkgver

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

source=("$pkgname-${pkgver//_/-}.tar.gz")
注意: 如果上游使用时间戳格式的版本,例如 05102014,请修改为年份在前的格式 20141005 (ISO 8601). 否则新版本判断会失效。
Tip:

pkgrel

发布号,一个正整数,用来区分同一版本软件的多次构建。当软件包随着 PKGBUILD 的调整与优化变化时,释出号递增 1。而当这个软件包发布一个新版本时,释出号重置为 1。个别软件会使用 major.minor 的发布号。

epoch

注意: 若非必要,不要使用此变量

当一个软件的版本编号方式改变,打破正常的版本比较逻辑时, 使用此数值进行强制升级。只要此数值比安装的版本大,就会视作新版本进行升级。

示例:

pkgver=5.13
pkgrel=2
epoch=1
1:5.13-2

更多信息参见pacman(8)

一般变量

pkgdesc

软件包描述,建议最多80个字符,不要重复软件的名字,除非软件包名和程序名不相同。合理使用关键字以方便搜索。

比如:"Nedit is a text editor for X11"应该写成"A text editor for X11"。

arch

一个架构数组,表示 PKGBUILD 可以编译和使用的架构。Arch 官方仅支持 i686x86_64, 但是 Arch Linux ARM 项目提供了其它架构支持,arm - armv5, armv6h - armv6 hardfloat, armv7h - armv7 hardfloat, aarch64 - armv8 64bit.

如果软件包编译后和架构无关(shell脚本、字体、主题、各种扩展等),请使用 arch=('any'). 请注意这个值意味着软件仅需编译一次,然后可以在所有架构上使用。软件包会以 -any 为后缀,而不是 -i686, -x86_64 等.

如果软件包可以在任何架构上编译,但是编译后只能在一个架构中运行,请列出所有支持的架构例如 arch=('i686' 'x86_64').

url

软件官方站点的网址

license

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

  1. 许可证安装到: /usr/share/licenses/pkgname/ 目录下,例如:/usr/share/licenses/foobar/LICENSE
  2. 如果许可证的内容仅保存在网站上,那么你需要单独保存一个版本。
  3. custom 添加到 license 列表。或者你可以用 custom:name of license 替代 custom。一旦某个许可证被官方仓库用于两个以上软件包(包括 [community]),它将成为 licenses 的一个组成部分。
  • BSDMITzlib/pngPython 是几个例外的情况,它们不能加入 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[broken link: package not found] 组里的所有包。

依赖关系

注意: 架构相关的变量可以通过下划线加架构的方式指定:depends_i686=(), optdepends_x86_64=().

depends

软件的运行时依赖列表。可以使用比较运算符来描述版本限制,如:depends=('foobar>=1.8.0')。如有多重限制,你可以重复设置它们[1],像这样:depends=('foobar>=1.8.0' 'foobar<2.0.0')

不需要列出你的软件包的二次依赖,比如说:gtk2依赖glib2glibc;然而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列表中。用下面程序查看一个依赖关系是否已经包含在 base-devel 中:

$ LC_ALL=C pacman -Si $(pactree -rl ''package'') 2>/dev/null | grep -q "^Groups *:.*base-devel"

checkdepends

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

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

软件相关性

注意: 架构相关的变量可以通过下划线加架构的方式指定:provides_x86_64=(), conflicts_x86_64=().

provides

这个变量说明当前包能提供的功能(或者像 cron、sh 这样的虚拟包)。只要没有标记为 conflicts,提供相同功能的软件包可以同时安装,

如果你使用这个变量,应当加上所替代软件的版本号(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中已安装的包。如果你只是提供已存在包的一个替代品,或者上传到 AUR, 使用conflictsprovides变量——它们仅在安装冲突包时被检查。

其它

backup

当包被升级或卸载时,应当备份的文件(的名字)。这些文件一般是用户会更改的文件,如(主要是)放置在/etc中的配置文件。

列表中的文件应该使用相对路径(如 etc/pacman.conf),而不是绝对路径(如 /etc/pacman.conf)。

在升级时,新版本会被命名为file.pacnew以避免覆盖旧有且被用户修改过的文件。类似地,当卸载包时,用户修改过的文件会以file.pacsave为名而保留下来——除非用pacman -Rn命令卸载。

参见Pacnew and Pacsave files获取更多信息。

options

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

install

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

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

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

提示: 一个 .install 文件模板(原型)位于/usr/share/pacman/proto.install 这里
Note: 脚本不要以 exit 结束,否则包含的函数无法被执行。

changelog

软件包 changelog 的名称,要查看安装软件的 changelog:

$ pacman -Qc pkgname

源码

注意: 架构相关的变量可以通过下划线加架构的方式指定:source_i686=(). 记得要同时提供对应的校验和:sha256sums_x86_64=()

source

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

makepkg 会自动把 .sig, .sign.asc 结尾的文件当成 PGP 签名,并自动验证源代码文件的完整性。

noextract

一些列举于 source 中,但不需要在运行makepkg时解包的文件。在碰到不能被/usr/bin/bsdtar处理的文件或不需要解压的文件时使用。在这些情况下,额外的解包工具(如unzipp7ziplrzip等)应该加入 makedepends 序列,并且用prepare()[broken link: invalid section]函数手动解包。例如:

  prepare() {
  lrzip -d source.tar.lrz
}

注意当 source 是一些 URL 时,noextract 仅仅取文件名部分:

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

不提取任何东西时,可以像这样:

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

validpgpkeys

PGP 指纹列表。如果使用,makepkg 仅接受这里定义的签名,并且忽略密钥环中的值。如果源代码用子密钥加密,makepkg 会使用主键进行比较。

仅接受完整签名,必须是大写字母而且不能有空白字符。


Note: 可以使用 gpg --list-keys --fingerprint <KEYID> 查找 key 的指纹.

完整性

注意: 架构相关的变量可以通过下划线加架构的方式指定:depends_i686=(), optdepends_x86_64=().

数组中的变量是 #source 数组中对应文件的校验和。可以插入 SKIP 跳过某个未测试文件的校验。

Checksums 仅是为了验证下载文件的 完整性,而不是 它们的 真实性: 所以虽然 MD5 算法有 漏洞,不能在其它地方使用。在这里却是推荐使用的,因为它的速度比其它算法例如 SHA-2 要快很多。尤其是 source 数组中的文件很大时. 如果可能,请尽量在 source 数组中加入它们的签名信息。这时就可以跳过完整性校验。

makepkg-g/--geninteg 选项可以自动生成校验值,可以通过 makepkg -g >> PKGBUILD 命令写入. updpkgsums 也可以自动更新 PKGBUILD 中的数值. 两个工具都会自动检测 PKGBUILD 中的算法, 如果没找到就使用 md5sums

要使用的校验算法可以通过 /etc/makepkg.conf 中的 INTEGRITY_CHECK 选项设置,参考 makepkg.conf(5).

md5sums

source 列表文件中的 128 位 MD5 校验和。

sha1sums

source 列表文件中 SHA-1 160位校验和。

sha256sums

256 位 SHA-2 校验和。

sha224sums, sha384sums, sha512sums

SHA-2 校验和列表,有224,384 和 512位。它们都可以替代上述的 sha256sums

参阅