非自由应用程序打包指南
32 位 – CLR – CMake – 交叉编译 – DKMS – Eclipse – Electron – 字体 – Free Pascal – GNOME – Go – Haskell – Java – KDE – 内核模块 – Lisp – Meson – MinGW – Node.js – 非自由 – OCaml – Perl – PHP – Python – R – Ruby – Rust - 安全 – Shell – VCS – Web – Wine
对于许多应用程序(其中大多数是 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 中搜索您正在打包的软件的现有软件包。 尝试使用已建立的命名约定,例如,如果存在名为 aquaria-hib、crayonphysicsdeluxe-hib 和 uplink-hib 的现有软件包,请不要将您的软件包命名为 gish-hb。 如果您确定永远不会有基于源代码的软件包,则可以省略后缀 -bin
。 否则,始终使用此后缀。 提交软件的基于源代码的软件包的用户将不得不要求您的软件包的维护者(或者,在最坏的情况下,软件包维护者)孤立现有软件包,以便可以提交其基于源代码的软件包,并且原始二进制软件包和新的基于源代码的软件包最终都将在其各自的 PKGBUILD 中堆满额外的 replaces
和 conflicts
条目。
文件放置
同样,分析现有软件包(如果存在)并决定是否要与它们冲突。 除非您想使用一些丑陋的技巧(例如将 root:games
所有权授予软件包目录(以便 games
组中的用户运行游戏可以在游戏自己的文件夹中写入文件)),否则不要将内容放置在 /opt
下。
缺少文件
对于大多数商业游戏,无法(合法地)下载游戏文件,这是正常软件包获取文件的首选方式。 即使可以在提供密码后下载文件(例如所有 Humble Indie Bundle 游戏),也不建议要求用户提供此密码并在 build
函数中的某处下载,原因有很多(例如,用户可能无法访问互联网,但已下载所有文件并本地存储)。
以下小节提供了针对您可能遇到的一些情况的建议。
文件只能从分布式存档/安装程序中获得
该软件仅通过该存档/安装程序文件可用,必须获取该文件才能获得缺少的文件。
将所需的存档/安装程序添加到 source
数组,重命名源文件名,以便 AUR Web 界面中的源链接看起来与源 tarball 中包含的文件名不同
sources=(... "originalname::local://originalname")
还要在 AUR 中的软件包页面上添加如下所示的置顶评论,并在 PKGBUILD 中解释详细信息
Need archive/installer to work.
选择方案
如果您在 source 数组中使用 local:// 方案,则 makepkg 的行为就像未指定方案一样,并且必须手动将文件放置在与 PKGBUILD 相同的目录中。
如果您使用 file:// 方案,则还可以为文件协议指定 DLAGENTS,因此可以以特殊方式获取它。 请参阅下面的 示例。
但是,对于您应该使用这些方案中的哪一个,仍然没有明确的规则。
文件只能从分布式光盘或其他类型的光盘介质中获得
该软件仅通过光盘介质(例如 CD、DVD、Bluray 等)可用,必须将其插入光盘驱动器才能获得缺少的文件。
将安装脚本和一个 .install
文件添加到软件包内容中。
文件可以从多种方式获得
从磁盘复制文件、从网络下载或在 build
阶段从存档中获取文件可能看起来是个好主意,但不建议这样做,因为它限制了用户的可能性并使软件包安装具有交互性(通常不鼓励这样做,而且很烦人)。 同样,一个好的安装脚本和 .install
文件可以替代。
获取软件包所需文件的各种策略的一些示例
- worldofgooAUR – 依赖于用户提供的文件
高级主题
自定义 DLAGENTS
一些软件作者积极保护他们的软件免受自动下载:禁止某些“User-Agent”字符串,创建文件的临时链接等。 您仍然可以通过在 PKGBUILD 中使用 DLAGENTS
变量方便地下载这些文件(请参阅 makepkg.conf(5))。 这在 官方存储库中的某些软件包中使用,例如在 以前版本 的 ttf-baekmuk 中。
请注意,如果您想要自定义用户代理字符串,如果后者包含空格、括号或斜杠(或实际上任何可能破坏解析的内容),这将不起作用。 没有解决方法,这是 bash 中数组的性质以及 DLAGENTS 在 makepkg 中被设计为使用的方式。 因此,以下示例不起作用
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
映像和.AppImage
文件(实际上是混合的自执行 iso9660)。 它还提供 bsdunzip,可以代替 unzip 使用。- pacman 需要 libarchive,因此它是基本安装的一部分。
- unzip 和 unrar 解包基于此格式的可执行 SFX 存档
- cabextract 可以解包大多数
.cab
文件(包括扩展名为.exe
的文件) - unshield 可以从 InstallShield 安装程序中提取 CAB 文件
- 7zip 不仅解包许多存档格式,还解包基于 NSIS 的
.exe
安装程序- 它甚至可以从常见的 PE (
.exe
&.dll
) 文件中提取单个节!
- 它甚至可以从常见的 PE (
- upx 有时用于压缩上面列出的可执行文件,也可以用于解压缩它们
- innoextract 可以解包使用 Inno Setup 创建的
.exe
安装程序(例如 GOG.com 游戏使用)
为了确定文件的确切类型,请运行 file file_of_unknown_type
。
获取 .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 中设置了产品版本字段。 pevAUR 软件包中的 peres
命令可以帮助您提取并使用该值来自动更新您的 pkgver
pkgver=VERSION makedepends=('pev') pkgver() { peres -v -f csv "${srcdir}/NonFreePackageWithPoorFileName.exe" \ | awk -F , '/^Product Version,/ { print $2 }' }
从主可执行文件
有时 .exe 安装程序不携带产品版本的有意义的值,但主可执行文件携带。 在这种情况下,您可以使用 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 软件包内的控制文件中提取版本
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 - . }