PKGBUILD (简体中文)

翻译状态: 本文是英文页面 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 文件里使用的变量。pkgnamepkgverpkgrelarch是必须出现的。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

主机架构数组。当前,它应该包含 i686x86_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 的一个组成部分。
  • 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 组里的所有包。

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 地址。可以在软件源信息中很好的调用前面提到的变量 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

noextract

一些列举于 source 中,但不需要在运行makepkg时解包的文件。这种情况常发生在不能被/usr/bin/bsdtar处理的文件上——libarchive以流方式来处理所有文件,而不像unzip一样随机访问。在这些情况下,额外的解包工具(如unzipp7zip等)应该加入 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位。它们都可以替代上述的 md5sumssha1sums,并且有更少的已知弱点。为了启用这些算法,在 /etc/makepkg.conf 开启 INTEGRITY_CHECK 选项。详情请看 man makepkg.conf


更多信息