Arch折腾记 | PKGBUILD怎么写
自安装了ArchLinux以来,准确的来说是从AUR安装东西以来,就一直想学PKGBUILD的写法。但是因为太懒没有动力,就一直拖着。直到最近想装个东西,但它没提供Arch包,这才整了整活。
跟着其他教程弄了半天,总算装上能用了,但写得肯定不够规范,以后有空了再更新吧~
PKGBUILD和AUR
使用ArchLinux的朋友可能不陌生,AUR(Arch User Repository)是一个用户自行打包、分享软件的平台,其安全性和稳定性虽然没法保证。但一般来说,只要安装有人气的包就没大问题。对于官方来说,也会将符合一些条件的包收录到官方库里面去。是ArchLinux社区的重要组成部分(这说法好官方哈哈哈哈哈)。
这无穷无尽的软件想要都塞给官方来保存,人又不是网盘,顶不住这么折腾,于是PKGBUILD就是一个很好的解决方式。
简单来说,PKGBUILD这个文件(对,它只是一个文本文件罢了)负责记录:
- 从哪来:软件数据从哪里下载
- 到哪去:怎么安装,安装到哪
大陆网络有时会发现无法下载AUR的包,如果不是PKGBUILD写错了,那么很大概率是连不上作者指定的下载源(你懂的)
这么一来,只要写好一份PKGBUILD,并在下载源(比如本地,或者Github之类的)放好软件数据,就可以交给makepkg
命令来安装了,nice!
而如果要提交上AUR给大伙瞧瞧,还得在里面写好软件版本、作者信息、许可证、完整性检验等等更规范的玩意,当然也得负责后续更新以及bug的处理。当然,本篇并不关注这些,咱只想装个AUR里面没有的包罢了。
PKGBUILD结构
前面说到,PKGBUILD实际上就是一个文本文档,它的结构在Wiki里已经有比较好的说明了。
不妨先把/usr/share/pacman/PKGBUILD.proto
这个模板复制一份到某个空文件夹里面(这个文件夹就是后续的操作目录),去掉后缀。
当然,在我的简单需求下,并不是所有的参数都需要用到,只需要关注:
1 | pkgname=XXX # 包名 |
模板里其他部分并不是不重要,如果需要提交AUR的话还是必须了解所有功能的,但对于我来说已经够用了
注意到这整个安装过程分了好几个阶段,它们实际上是会按顺序来的。换句话说,如果你喜欢,也可以把所有步骤全扔到比如package()
里面,也同样能跑。
但之所以这么分,是因为我们的安装不一定会走完全流程,比如:
- 已经下载好了源文件,直接本地编译就行,那就不用跑
prepare()
- 已经编译好了,只想重装一下,那就不用跑
prepare()
和build()
正因为有这些更灵活的需求,我还是建议尽量分开各个步骤。
安装,更新与卸载
安装
写好了PKGBUILD之后,在PKGBUILD所在的文件夹里面,可以使用makepkg
命令安装:
1 | $ makepkg -si # 加-s自动安装依赖包, -i编译后安装 |
而且你还会发现搞定后多出了一个src
文件夹,一个pkg
文件夹,和一个*.pkg.tar.zst
文件:
src
:下载及预处理后的软件源文件;pkg
:一个软件安装虚拟环境(沙箱?),如果安装成功,会被复制到根目录去;*.pkg.tar.zst
:打包好的二进制文件,以后可以使用pacman -U
直接安装。
所以简单来说,除了最后一个可以保存以便重新安装,其他都没啥用。
更新
更新十分简单,只需要修改PKGBUILD的版本相关参数(包括pkgver,pkgrel等),重新运行makepkg
即可。
卸载
对于安装到正确位置的软件包,都能被Pacman正确识别到信息,然后和别的软件包一样使用sudo pacman -R
就好啦~
举个栗子:Terminus Player
吐槽:网上搜的大多数教程具体的例子都不给,感觉看着太难受。。
这里简单举个例子,以我想要安装的Terminus Player为例。
命令行安装
在正式编写PKGBUILD之前,我推荐要先在命令行走一遍安装流程。
在Github简介内,作者给出了命令行的安装方式,虽然是Ubuntu的,但我们完全可以借鉴这个步骤。
首先我习惯新开一个文件夹在里面操作,不妨就叫terminus
好了。由于系统不同,我们直接跳过所有依赖包,开始它的安装步骤,即:
1 | # pwd: terminus |
在我的电脑上,进行第三行命令运行./download_webclient.sh
时报了错误,少了个包:mpv,这简单,用Pacman给它装上,再跑一遍。
细心的话可以发现,其实Github作者给的安装步骤里是有类似mpv的东西。但对于像我一样使用另一个系统的朋友,还是建议先直接安装,有提示缺漏再补。(以避免安装错误或者不必要的安装。)
安装顺利完成,留意一下安装路径(因为不一定符合要求)是在/usr/local
里面:
1 | # ...(前略) |
由于我更希望和其他软件一起存在
/usr
里面,这样可以方便管理,因此可以给make install
增加参数make DESTDIR="/" install
(但在PKGBUILD里面需要写成${pkgdir}
来代表根目录,而不是/
,后面会提到)
尝试打开,又发现了错误(雾):
1 | libpng warning: iCCP: known incorrect sRGB profile |
好家伙,这我就只能交给谷歌了(此处花了几乎一个小时),终于在这里找到了方法,需要把cmake
那一行命令加多一个参数:
1 | $ cmake -DQTROOT="{qt所在的文件夹}" .. |
卸载(手动删除)掉之前装上的东西:
1 | $ sudo rm -rf /usr/local/bin/jellyfinmediaplayer |
重新安装成功,可以使用,nice!
实际上到这里也可以直接使用了,但如果要管理软件会比较麻烦(比如卸载的话,要手动去删除软件)…
编写PKGBUILD
有了成功的经验,我们便可以开始编写PKGBUILD了,新建一个文件terminus/PKGBUILD
。
我直接把写好的放出来,大家对照着看解释即可:
1 | pkgname="terminus" |
我在这里用到了很多诸如${srcdir}
的玩意,这些是PKGBUILD的“暗号”,具体来说:
${srcdir}
:安装文件夹,实际上是与PKGBUILD同级的terminus/src
文件夹(开始安装后会出现),可看作是安装过程中的根目录;${pkgdir}
:只应在package()
里使用,对应着外部的根目录;${pkgname}
:前面定义的包名${pkgver}
:前面定义的版本
现在用makepkg
来安装:
1 | # pwd: terminus |
注意:安装过程中有可能出现这个INSTALL路径错误:
1
2
3
4 CMake Error at src/cmake_install.cmake:50 (file):
file INSTALL cannot find
"terminus/src/terminus-0.0.1/jellyfin-media-player/build/src/../dist":
No such file or directory.具体原因我还没搞清楚,但可以通过
rm -rf src pkg
删掉已有文件后重新来一遍解决。
完事!
修复PGP: marginal trust / invalid问题
我在某一次安装的时候遇到了类似这样的问题:
1 | error: XXXXXX: signature from "XXXXX" is marginal trust |
根据他的提示删除PGP签名又提示失败:
1 | error: failed to commit transaction (invalid or corrupted package) |
其原理还没怎么搞懂,但至少是PGP签名出了问题。
这里提到一种解决办法是检测并刷新所有签名:
1 | $ sudo pacman-key --refresh-keys |
注意:这行命令会运行很久很久,甚至超过半小时。但对系统负载不高,可以干别的。
等待PGP刷新结束即可重新makepkg -si
。