非自由应用程序打包指南
对于许多应用程序(其中大部分是 Windows 应用程序),既没有源代码也没有 tarball 可用。其中许多应用程序由于许可证限制和/或没有合法的免费获取安装程序的方式,因此不能自由分发。
基本原理
即使打包不可打包的软件也有多种原因
- 简化安装/卸载过程
- 这适用于最简单的应用程序,它们由一个要安装到
/usr/bin的脚本组成。而不是发出 $ chmod +x filename
$ chown root:root filename
# cp filename /usr/bin/- 你可以只发出
$ makepkg -i
- 大多数非自由应用程序明显要复杂得多,但通过精心编写的打包脚本,可以有效地减轻从主页(通常充满广告)下载存档/安装程序、解压/解密它、手动编写典型的启动器脚本以及执行其他类似任务的负担。
- 利用 pacman 的功能
- 跟踪状态、自动更新任何已安装的软件、确定每个文件的所有权以及将压缩包存储在组织良好的缓存中的能力,是 GNU/Linux 发行版如此强大的原因。
- 共享代码和知识
- 在 AUR 这样的单一公共场所应用调整、修复错误和寻求/提供帮助比向可能已停止支持的专有开发人员提交补丁或在通用论坛上提出含糊不清的问题要简单得多。
通用规则
尽可能避免使用非自由软件
是的,最好放弃本指南,花一些时间搜索(甚至创建)您想打包的应用程序的替代品,因为
- 支持由我们所有人拥有的软件比支持由公司拥有的软件要好
- 支持积极维护的软件要好
- 如果数百万中的一个人足够关心,那么支持可以修复的软件要好
尽可能使用开源变体
许多商业游戏(一些列在本 Wiki 上)拥有开源引擎,并且许多旧游戏可以通过模拟器(如 ScummVM)来玩。将开源引擎与原始游戏资产一起使用,可以让用户访问错误修复并消除二进制包造成的几个问题。
保持简单
如果打包某个程序比购买和使用原始版本需要更多的努力和技巧,那就做最简单的事情——毕竟这是 Arch!
包命名
在命名软件包之前,请搜索 AUR 中已有的要打包软件的软件包。尝试使用既定的命名约定,例如,不要将您的软件包命名为 gish-hb,如果已有的软件包名为 aquaria-hib、crayonphysicsdeluxe-hib 和 uplink-hib。对于非自由软件,如果源代码不可用,则不应使用 -bin 后缀。AUR 中存在 -bin 后缀的软件包意味着存在一个相应的不带 -bin 的软件包的可能性,该软件包可能在 AUR 中或官方存储库中。提交该软件基于源代码的软件包的用户必须要求您的软件包的维护者(或者,在最坏的情况下, 软件包维护者)放弃现有软件包,以便他们的基于源代码的软件包可以被提交,并且原始二进制软件包和新基于源代码的软件包最终都会在其各自的 PKGBUILD 中充斥着额外的 replaces 和 conflicts 条目。
文件放置
再次,分析现有软件包(如果存在),然后决定是否要与它们冲突。除非您想使用一些丑陋的技巧,例如将软件包目录的所有权设置为 root:games(这样属于 games 组的用户在运行游戏时可以在游戏自己的文件夹中写入文件),否则不要将文件放在 /opt 下。
缺失文件
对于大多数商业游戏来说,没有办法(合法地)下载游戏文件,这是普通软件包的首选获取方式。即使在提供密码后可以下载文件(例如所有 Humble Indie Bundle 游戏),出于多种原因也不建议在 build 函数中要求用户输入密码和下载(例如,用户可能没有互联网连接,但已经下载并本地存储了所有文件)。
下面的子节为可能遇到的几种情况提供了建议。
文件只能通过分发的存档/安装程序获取
该软件只能通过该存档/安装程序文件获得,必须获取该文件才能获得缺失的文件。
将所需的存档/安装程序添加到 source 数组中,重命名源文件名,以便 AUR 网页界面中的源链接与源 tarball 中包含的文件名有所不同
source=(... "originalname::local://originalname")
另外,在 AUR 的软件包页面添加一个如下的固定评论,并在 PKGBUILD 中解释细节
Need archive/installer to work.
选择方案
如果您在源数组中使用 local:// 方案,makepkg 会表现得好像没有指定方案,并且文件必须手动放在与 PKGBUILD 相同的目录中。
如果您使用 file:// 方案,您可以为文件协议另外指定 DLAGENTS,因此它可以通过特殊方式获取。请参阅 下面的 示例。
但是,对于应该使用哪种方案,仍然没有明确的规则。
文件只能通过分发的光盘或其他类型的光盘介质获取
该软件只能通过光盘介质(例如 CD、DVD、蓝光等)获得,必须将光盘插入光驱才能获取缺失的文件。
将安装脚本和 .install 文件添加到软件包内容中。
文件可以从多种方式获取
从磁盘复制文件、从网络下载或在 build 阶段从存档中获取可能看起来是个好主意,但不建议这样做,因为它限制了用户お的可能性并使软件包安装具有交互性(这通常不被推荐,而且很烦人)。同样,一个好的安装脚本和 .install 文件可以代替。
获取软件包所需文件的几种策略的示例
- worldofgooAUR – 依赖用户提供的文件
高级主题
自定义 DLAGENTS
一些软件作者会积极保护他们的软件免遭自动下载:禁止某些“User-Agent”字符串,创建文件的临时链接等。您仍然可以通过在 PKGBUILD 中使用 DLAGENTS 变量(请参阅 makepkg.conf(5))方便地下载这些文件。AUR 中的一些软件包(例如 官方存储库 中 ttf-baekmuk 的先前版本)也使用了此功能。
请注意,如果您想拥有一个自定义的用户代理字符串,如果后者包含空格、括号或斜杠(或任何可能破坏解析的内容),这将不起作用。没有解决方法,这是 bash 中数组的性质以及 makepkg 设计 DLAGENTS 的方式。因此,以下示例将不起作用
DLAGENTS=("http::/usr/bin/curl -A 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)' -fLC - --retry 3 --retry-delay 3 -o %o %u")
将其缩短为以下有效形式
DLAGENTS=("http::/usr/bin/curl -A 'Mozilla' -fLC - --retry 3 --retry-delay 3 -o %o %u")
以下允许从下载页面提取文件的临时链接
DLAGENTS=("http::/usr/bin/wget -r -np -nd -H %u")
为了下载文件的临时链接或绕过交互式下载,可以分析用于创建最终下载链接的 HTTP 请求,然后创建模拟此过程的 DLAGENTS,使用 curl。例如,请参阅 decklink-sdkAUR 或 jlink-software-and-documentationAUR。
或者,DLAGENTS 可用于在文件缺失时向用户提供更具信息性的错误消息。例如,请参阅 ttf-ms-win10AUR。
解压
许多专有程序以令人头疼的安装程序形式提供,这些安装程序有时甚至无法在 Wine 中运行。以下工具可能会有所帮助
- libarchive 包含 bsdtar,它可以提取
.iso映像。它还提供 bsdunzip,可以代替 unzip 使用。bsdunzip -O用于非 UTF-8 zip 文件。- libarchive 是 pacman 所必需的,因此它是基本安装的一部分。
.AppImage文件可以通过使用--appimage-extract标志启动它们来提取。- unzip 和 unrar 可以解压基于这些格式的可执行 SFX 存档。
- cabextract 可以解压大多数
.cab文件(包括扩展名为.exe的文件)。 - unshield 可以从 InstallShield 安装程序中提取 CAB 文件。
- 7zip 不仅可以解压许多存档格式,还可以解压基于 NSIS 的
.exe安装程序。- 它甚至可以从常见的 PE(
.exe和.dll)文件中提取单个部分!
- 它甚至可以从常见的 PE(
- upx 有时用于压缩上述可执行文件,也可用于解压缩它们。
- innoextract 可以解压使用 Inno Setup 创建的
.exe安装程序(例如 GOG.com 游戏使用的)。
为了确定文件类型,请运行 file unknown_type_file。
为 .desktop 文件获取图标
专有软件通常没有单独的图标文件,因此在创建 .desktop 文件时没有什么可以使用的。幸运的是,可以使用 icoutils 包中的程序从可执行文件中轻松提取 .ico 文件。您甚至可以在 build 阶段实时执行此操作,例如
$ wrestool -x --output=icon.ico -t14 executable.exe
自动更新 pkgver
非自由软件供应商通常不在其下载源 URL 中包含版本号
source=('https://downloads.example.com/NonFreePackageWithPoorFileName.exe')
这可能会导致上游包在未经通知的情况下更改,这对于打包来说是一个问题。就像在 VCS 包中一样,您可能需要自动更新您的 pkgver 来处理这个问题。
从安装程序包
例如,一些 .exe 安装程序在其 PE 中设置了 Product Version 字段。来自 pevAUR[链接已损坏: 未找到软件包] 包中的 peres 命令可以帮助您提取并使用该值来自动更新您的 pkgver
pkgver=VERSION
makedepends=('pev')
pkgver() {
peres -v -f csv "${srcdir}/NonFreePackageWithPoorFileName.exe" \
| awk -F , '/^Product Version,/ { print $2 }'
}
从主可执行文件
有时 .exe 安装程序不包含有意义的 Product Version 值,但主可执行文件包含。在这种情况下,您可以使用 prepare 步骤提取嵌套的主可执行文件(有关详细信息,请参阅 解压),然后自动更新 pkgver
例如:
pkgver=VERSION
makedepends=('p7zip' 'pev')
prepare() {
mkdir -p "${srcdir}/${pkgname}-unpacked"
7z x -o"${srcdir}/${pkgname}-unpacked" "${srcdir}/NonFreePackageWithPoorFileName.exe"
}
pkgver() {
peres -v -f csv "${srcdir}/${pkgname}-unpacked/NonFreeApp.exe" \
| awk -F , '/^Product Version,/ { print $2 }'
}
从 Debian (.deb) 文件
有时 .deb 文件在其名称中没有版本号,但在其控制文件中。但是,您可以使用 dpkg-deb 从 .deb 包中的控制文件直接提取版本。
您可以使用 dpkg-deb 从 .deb 包中的控制文件直接提取版本
pkgver=VERSION
makedepends=('dpkg')
source=('https://example.com/vendor/nonfree-app-latest.deb')
pkgver() {
# shellcheck disable=SC2016
dpkg-deb --show --showformat='${Version}' nonfree-app-latest.deb | tr - .
}