最近几天在尝试弄一个aur包,在此记录一下aur软件包的一些要求和规范。

aur的简单介绍

Arch 用户软件仓库(Arch User Repository,AUR)是为用户而建、由用户主导的 Arch 软件仓库。AUR 中的软件包以软件包生成脚本(PKGBUILD)的形式提供.用户自己通过 makepkg 生成包,再由 pacman 安装。创建 AUR 的初衷是方便用户维护和分享新软件包,并由官方定期从中挑选软件包进入 community 仓库。1

正如官方文档所述,aur是一个由用户主导的软件仓库,用户会编写一个叫做PKGBUILD的软件包生成脚本,并将这个脚本和一些其他有必要的文件上传到aur软件仓库,上传之后,其他人就能从aur仓库搜索到这个软件包。

获取PKGBUILD打包脚本和其需要的其他文件后,可以使用makepkg命令来打包为pacman包管理器所使用的软件包格式,并使用该包管理器安装到此系统之中。

对于安装aur软件包的方法,网络上教程很多,在此不再累述。此处仅介绍PKGBUILD的格式和aur的规则

PKGBUILD设定变量

PKGBUILD2是一个shell脚本,其预设了一些特殊的变量和特殊的函数的形式保存的软件包信息由makepkg处理或执行,本节只对其常见部分进行说明。

PKGBUILD的模板文件3可以在https://git.archlinux.org/pacman.git/plain/proto/PKGBUILD.proto此网站下载。

pkgname 变量

对于一般的软件包, pkgname 变量用于指定软件包的名称,对于拆分包则是一个名称的序列。这个变量只允许含有小写字母、数字、 @ 符号、 . 句点、 - 减号(连字符)、 + 号以及 _ 下划线,并且第一个字符不允许以减号和句点开头 。

虽然shell本身并没有禁止变量含有其他符号,但是,如果违反的话,makepkg打包时输出类似于 错误: pkgname 不允许以点号开始。 或者 错误: pkgname 包含无效字符: '^' 这样的错误。

1
2
pkgname=软件包名 #一般的情况
pkgname=('软件包1' '软件包2') #拆分包则提供每个包名字的序列和列表

pkgvar 变量

pkgvar 变量用于规定软件包的版本,该版本应当与上游软件包相同。这个变量的值允许包含字母,数字, . 句点和 _ 下划线,但是不允许含有 - 连字符。如果软件作者在版本编号中有使用连字符,则最好使用下划线替换。

pkgrel 变量

pkgrel 变量用于规定软件包的发布编号,通常是一个正整数。用于区分基于同一上游软件包版本的不同构建。

在为PKGBUILD更新了一些会影响其构建结果的变动的补丁或者功能的情况下,应该将pkgrel的值增加1。

发行新版本软件(pkgvar变量更新)时,该变量应当重置为1。(虽然不遵守也不会影响构建软件包,但是这样做不利于软件版本的控制和标识)

arch 变量

arch 变量用于设置软件包所允许运行的架构。

这个变量支持两种类型的值:

  1. arch=('any') 表示该软件包可以在任何体系架构构建,而且,构建的结果与其允许运行的体系架构无关(比如说脚本、插件、字体等)。
  2. arch=('x86_64' 'i686') 表示该软件包只能在特定的体系架构中构建,且一旦编译,结果就是特定于某个特定的体系架构,而不能在其他架构正常运行。

简单来说,arch的值等于any,打包架构和安装架构即使不同,也能正常安装;而arch的值是某几种特定架构,如果打包架构是x86_64,即使PKGBUILD支持i686架构,x86_64架构打包的也不能在i686架构系统运行。

在运行过程中可以通过 $CARCH 变量来获知目标架构。

depends变量

depends 变量用于指定软件运行时所依赖的软件包列表,该列表中的软件包将会在编译和安装时被makepkg和/或pacman检查。

可以使用比较运算符来描述版本限制。例如 depends=('foobar>=1.8.0') 。如有多重限制,可以重复设置它们。例如 depends=('foobar>=1.8.0' 'foobar<2.0.0')

makedepends变量

makedepends 变量用于指定编译生成时所依赖的软件列表,该列表中的软件包将会在编译时被makepkg检查。

provides

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

conflicts

conflicts 这个变量记录与当前软件包发生冲突的包与功能的列表。安装此软件时,所有这个列表中的软件包,和提供这个功能的软件包都会被删除。可以像 depends 那样指定冲突包的版本号。

source

source 变量序列记录所有构建软件包时所需要的文件列表,这里主要放源代码和补丁文件。

位于该序列的文件如果makepkg未找到,将会尝试从指定的网址下载,失败则停止执行。

source支持几种不同类型的定义方式

1
2
3
4
5
6
source=("test.sh" #打包时pkgbuild文件所在当前目录必须存在名为test.sh的文件
      "source.tar.gz::https://example.org/download/test.tar.gz"
      #打包时PKGBUILD文件所在目录需要存在source.tar.gz文件,如果缺少,则尝试从https://example.org/download/test.tar.gz下载,成功后重命名为source.tar.gz并解包
      "https://example.org/download/test.patch" #将会查找本地是否存在test.patch,如果没有则从网址下载
      "test::git+https://example.org/git/test" #将从网址克隆git存储库至本地
)

文件校验变量

下面描述的这些序列中的变量是 source 序列中对应文件的校验和。可以插入 SKIP 跳过某个不需要检验的文件。

下载后,可以设置文件校验值,校验失败不会继续执行,主要用于避免文件传输错误或遭到篡改劫持,PLGNBUILD支持很多的校验算法,如下所示

  • md5sums
    source 列表文件中的 128 位 MD5 校验和。可以通过 md5sum [文件名] 命令获取文件校验和值。
  • sha1sums
    source 列表文件中 SHA-1 160 位校验和。可以通过 sha1sum [文件名] 命令获取文件校验和值。
  • sha256sums
    256 位 SHA-2 校验和。 可以通过 sha256sum [文件名] 命令获取文件校验和值。
  • sha224sums, sha384sums, sha512sums
    SHA-2 校验和列表,分别对应224,384 和 512 位。这些是较为不常见的 sha256sums 替代品。可以分别通过 sha224sum [文件名]sha384 [文件名]sha512sum [文件名] 命令获取文件校验和值。
  • b2sums
    512 位 BLAKE2 校验和。 可以通过 b2sum [文件名] 命令获取文件校验和值。

以上面的source变量为例子:

1
2
3
4
5
sha256sums=("8e1a2a04509ae85a55001968a7f4b511efc2f3cd6a7cfac110c652f1da363cf4" #test.sh
	  "97f5a210ba875c5e72b91b0f304cae5ec6bc3523eb999df874bee93e05a989dc" #source.tar.gz
	  "2447000d4e8839e94ceba3cf8e8d44de2cdcf5f033699bc7e6f45275ef43ef84" #test.patch
	  "SKIP" #git仓库,跳过完整性校验
)

makepkg设定变量

makepkg设定了两个特殊变量,应当在脚本中使用

scrdir变量

makepkg会将压缩包解压至该 $scrdir 变量,或者在该文件夹下创建指向原始文件的软链接

pkgdir

makepkg会将 %pkgdir 文件夹当作系统根目录,并将软件安装在此文件夹下。

makepkg设定函数

makepkg设定了5个函数,代表着不同的步骤,除 package() 函数不能省略外,其余未定义则会被忽略,按执行顺序排列

prepare()

prepare() 函数,会在软件包解压后开始执行,用于预处理原始文件。比如如果声明不使用makepkg的解压某个文件的话,就应该在这一步对文件进行解压缩。

如果makepkg指定了-e选项,不解压而使用现存 $srcdir 的话,该函数将被跳过。

pkgver()

pkgver() 函数会在解压并执行 prepare() 函数完成后执行。该函数一般在以git等经常更新代码版本进行打包的情况下,在git代码更新后,更新软件包的 pkgver 变量。

build()

build() 函数会在以上函数执行后执行,该函数一般用于编译源码。如果软件不需要构建则不要使用该函数

check()

check() 函数用于测试编译结果,可以被 --nocheck 禁用

package()

package() 函数用于将 ${scrdir} 文件夹下的编译成品安装到 ${pkgdir} 文件夹下,以交由后续打包。

上传至aur所额外注意的一些变量

此处为上传aur所需要注明的变量

pkgbase 变量

pkgbase 变量用于定义软件包所在的包组——在构建拆分包时,不应该在构建一般的软件包中显式定义,这个变量默认会与 pkgname 变量的值相同。

epoch变量

epoch 变量用于强制将该版本视为比以前发行的任何以前版本都要更高。这个值默认为0,值必须是非负整数。一般在上游软件版本编号方案更改时使用。

注意,epoch只能在绝对有必要的时候才能使用

当上游版本编号方案更改导致正常的版本比较无法正常进行则使用此变量控制升级

关于版本控制的一些额外说明?

一个软件包的版本会由上述三个变量组成

1
${epoch}:${pkgvar}-${pkgrel}

越靠前的越先比较,前面的值相同则会比较后面的,值大的软件包版本更新。

pkgdesc 变量

pkgdesc 变量用于记录软件包的说明和描述,官方建议最好不要设置超过80个字符。

不过虽说如此也没有什么硬性要求就是了。而且自己用不上传的话,也没有什么设置必要。

license 变量

license 变量用于记录软件所使用的分发协议。一般来说,如果只是自己用,打包则不怎么需要注明,但是公开分享不注明则可能会遇到法律问题和风险而被下架什么的。

license包提供了很多许可证,如果软件所使用许可证是该包所提供的许可证范围内,则只需要设置为 /usr/share/licenses/common/ 下的的目录名称(也是协议名称),如 license=('GPL') ,关于具体所提供的协议可以参见下表:

1
2
echo 'license license license license license'
ls /usr/share/licenses/common/|xargs printf "%-15s%-15s%-15s%-15s%-15s\n"

如果没有在上述列表中找到软件的许可证,则一般需要一些额外工作。

  1. custom 或者 custom:协议名称 加入到PKGBUILD文件的licenes列表之中,比如说 linenes=('custom:TureCrypt')
  2. 在后续的打包过程中将许可证文件安装到 /usr/share/licenses/软件包名/ 文件夹下可以通过 install -Dm644 LICENSE "{pkgdir}/usr/share/licenses/${pkgname}/LICENSE 命令来实现这一点
  3. 如果许可证文件只在官网上找到,那么将需要在本地缓存一份许可证副本

group

groups 变量定义软件包所在的包组。例如:当你安装 base ,它会安装 base 组里的所有包。

上传之前的准备

arch提交软件包的准则4大致来说有以下几点,

  1. 检查PKGBUILD是否能够正常打包和运行
  2. 检查PKGBUILD是否符合打包规范5
  3. 检查官方存储库是否已经有该二进制包,任何提交的PKGBUILD都 不能提供已经存在于官方二进制库的软件 ,如果认为官方软件包过期或存在错误则应当通过bug报告来反馈。除非提供的软件包提供了额外功能或使用了不同补丁,这时应当修改 pkgname 变量以表示新增的功能,并同时为 provides 变量添加上原始软件包的包名以避免冲突。
  4. 检查aur是否有相同或类似的软件包,如果有,且有人维护,则请以评论的形式反馈给维护者。如果软件包无人维护或不存在,用户提交的软件包将被认领。不应当创建重复的包。
  5. 确保软件包是有人需要的,有人会用这个软件包吗?它非常特别吗?如果有一些人觉得它有用,就提交它。
  6. aur仓库应当避免提交二进制文件,aur不应当包含PKGBUILD创建的二进制包。
  7. 贡献者信息应当记录在PKGBUILD文件之中。

如果上传的软件包不符合提交软件包的规则4,上传的软件包可能会不经过警告而被直接删除

上传软件包至aur仓库

如果经过仔细检查认为符合的话,就可以提交了

配置aur的帐号

上传软件包至aur存储库需要一个aur账户,如果没有,则需到arch注册页面注册。

执行 ssh-keygen -f ~/.ssh/aur 以生成一个ssh密钥,用于登陆aur服务器。

在aur网站的设置界面或注册界面,将刚刚生成的公钥文件 ~/.ssh/aur.pub 的内容复制到 ssh公钥 一栏(下图红框部分),并保存。

~/ssh/config 文件中增加以下内容:

1
2
3
Host aur.archlinux.org
  IdentityFile ~/.ssh/aur
  User aur

执行 ssh aur.archlinux.org help 测试ssh配置是否正常。

准备git存储库,并提交

在PKGBUILD文件所在文件夹执行 git init 来将目录初始化为一个存储库。

执行 git remote add aur ssh://[email protected]/[软件包名].git ,增加git上游链接。

执行 git pull aurgit fetch 获取并合并远程存储库。(如果aur没有这个存储库的话,则不需要执行这一步,但是,有可能远端有同名存储库,则需要合并至本地)

合并完成后,执行 makepkg --printsrcinfo > .SRCINFO 生成.SRCINFO6索引文件,这一文件用于帮助aur网站提取关于软件包的信息,此步骤在后续每一次更新PKGBUILD中都要进行。

将一些必要的文件提交至本地git存储库中—— git add PKGBUILD .SRCINFO [一些其他补丁或者辅助文件] ,并提交 git commit -m "有意义的提交说明"

最后,执行 git push aur 推送至aur的服务器,然后应该就能在aur网站找到提交的软件包了。

这篇博客花了一天多时间来完成,不过,感觉完全是对archwiki的拙劣摘抄(思考)……就当自己给自己看,整理的好了?

怎么说呢,至少好歹是写完了吧?不过,还是请以官方wiki记载的为准,大概。