近期阅读了Nicholas Fraser的文章,颇有感触,翻译并搬运于此。
使用DeepL翻译,翻译问题处有本人的轻微修改。
原文:Flatpak Is Not the Future


发布日期:2021-11-18
最后更新:2021-11-23

为 Linux 桌面部署应用程序很难。历来的一个主要问题是库的兼容性。不同的 Linux 发行版,甚至同一发行版的不同版本,都有不兼容的库。不幸的是,Linux 桌面上并不总是存在向后兼容的文化。

这种情况终于有所改变。近年来,Linux 桌面的稳定性有了显著提高。核心库开发人员终于看到了保持兼容性的好处。尽管如此,许多开发者对依赖二进制软件的稳定库基础并不感兴趣。相反,他们决定忽略和覆盖用户系统中预装的几乎所有库。

目前的解决方案包括在容器化环境中打包整个备用运行时。FlatpakSnapAppImageDockerSteam:这些都提供了一种应用程序打包机制,可以取代系统的大部分或全部运行库,而且它们现在都使用容器化来实现这一目标。

Flatpak 自称是 "应用程序发布的未来"。我并不看好它。我将在这里概述 Flatpak 和其他软件在技术、安全和可用性方面存在的一些问题。我将尽量避免讨论 "可解决 "的问题(如主题化),而将重点放在其设计中固有的根本问题上。我的目标是让你相信,这些并不是 Linux 桌面应用程序的未来。

尺寸

假设您想制作一个简单的计算器应用程序。下载量应该多大?

在撰写本文时,最新的 KCalc AppImage(如果你知道如何下载的话)只有 152 MB。

image.png
计算器应用程序KCalc的屏幕截图。

从表面上看,这与 Windows 没有竞争力。如果我为 Windows 发布应用程序,我就不必在应用程序中包含整个 Win32 或 .NET 运行时。我只需使用用户系统中已有的程序即可。

其他解决方案(如 Flatpak 或 Steam)会单独下载运行时。您的应用程序元数据会指定要使用的运行时,然后服务会下载并运行您的应用程序。

那么,这些运行时到底有多大?在一台新机器上,从 Flathub 安装 KCalc。你需要下载近 900 MB 才能获得第一个运行时。仅仅对于一个计算器来说。

        ID                                      Branch    Op   Remote    Download
 1.     org.freedesktop.Platform.GL.default     20.08     i    flathub   < 106.4 MB
 2.     org.freedesktop.Platform.VAAPI.Intel    20.08     i    flathub    < 11.6 MB
 3.     org.freedesktop.Platform.openh264       2.0       i    flathub     < 1.5 MB
 4.     org.kde.KStyle.Adwaita                  5.15      i    flathub     < 6.6 MB
 5.     org.kde.Platform.Locale                 5.15      i    flathub   < 341.4 MB (partial)
 6.     org.kde.Platform                        5.15      i    flathub   < 370.1 MB
 7.     org.kde.kcalc.Locale                    stable    i    flathub   < 423.1 kB (partial)
 8.     org.kde.kcalc                           stable    i    flathub     < 4.4 MB

请注意,应用程序软件包本身只有 4.4 MB。其余的都是我系统中已有的冗余库。我从 Flatpak 安装路径中直接运行了 kcalc 二进制程序,未加任何沙盒,让它使用我的本地库。它运行得很好,因为它使用的所有库都是向后兼容的。

Flatpak 要下载 3D 驱动程序、专利视频编解码器、主题、本地化、Qt 5、KDE 5、GTK 3、ICU、LLVM、ffmpeg、Python 以及 org.kde.Platform 中的所有其他内容,而这一切都是为了运行一个计算器。因为与 AppImage 不同的是,运行时并不只限于应用程序所需的内容。它拥有任何应用程序所需的所有依赖项。它是现有操作系统之上的整个通用操作系统。

共享运行时?

Flatpak 说这是为了让应用程序共享运行时。但运行时系统的全部意义就在于让应用程序使用不同的运行时。运行时的每个分支(例如代表不同的 Ubuntu 基本版本)都是一个完全独立的运行时映像。

他们声称会重复运行时间。我质疑的是,当所有东西都要重新编译时,不同分支之间真正能共享的东西有多少?在不同版本的Ubuntu之间,/usr有多少变化?我猜几乎全部都变了。

Steam 至少要好一些。《士兵》的运行时下载量为 610 MB,仍然很大。不过,Steam 只发布了几个官方运行时,所以大多数游戏实际上是共享运行时的。

Flatpak 允许任何人定义自己的运行时。freedesktop.org 发布了一些常用的 Flatpak 运行时,但应用程序并不一定使用这些运行时。例如,Fedora 发布的应用程序都有自己的运行时,这些运行时在其软件商店中默认可用。

如果在 Fedora 34 的软件商店中安装 GIMP,默认情况下会使用 Fedora 的 GIMP Flatpak。这会调入 Fedora 35 的 650 MB 运行时,而不是任何 freedesktop.org 运行时。与我们之前从 Flathub 安装的 freedesktop runtime KCalc 没有任何共享。在我的机器上,/var/lib/flatpak 仅这两个应用程序就占用了超过 3 GB 的磁盘空间。

这显然是按计划进行的。他们想让运行时成为一个 "自由市场",让你的硬盘里塞满每个应用程序的千兆字节自定义垃圾。我无法想象,当你有几十个应用程序存储着几十 GB 的运行时,而所有这些运行时都希望保持最新时,未来的系统更新会是什么样子。

"磁盘空间很便宜!"

有人说磁盘空间很便宜。事实并非如此,现代计算机的根设备就不是这样。事实上,内置存储空间一直在缩小。

软件变得越来越慢、越来越臃肿,操作系统已无法在旋转的铁锈上正常运行。笔记本电脑制造商正在改用更小的闪存驱动器,以提高性能,同时保持利润。2015 年前后,经济型笔记本电脑配备的是 256GB 或更大容量的机械硬盘。现在,到 2021 年,它们将配备 120 GB 闪存驱动器。NVMe 硬盘的价格约为 100 美元/TB,笔记本电脑制造商将这些价格抬高了 500% 或更多,因此升级新笔记本电脑的价格可能会很高。

Chromebook 的体积更小了,因为它们把所有东西都推到了云存储上。智能手机开始运行成熟的 Linux 发行版。Raspberry Pi 4400 使用 SD 卡作为 root 设备,性能非常出色,我们即将迎来一场低成本计算的革命。Flatpak 当然可以在这些系统上使用!一个 16GB 的 root 设备没有理由装不下我们想要的所有非游戏软件。Flatpak 并不是这场革命的一部分,而是阻碍了它的发展。

为什么存储不能缩小?软件的效率应该越来越高,而不是越来越低。即使带宽是免费的,硬盘是长在树上的,也不能成为软件大幅膨胀的借口。这些应用程序打包解决方案所造成的浪费简直令人反感。阿波罗登月时只用了 4 kB 的 RAM 和 72 kB 的 ROM,而我们却无法运行一个少于 150 MB 的计算器。任何有价值的工程师都应该优化效率,而不是将其视为无关紧要,尤其是当它如此明显地影响用户体验时。

内存使用量、启动时间

巨大的交替运行时间所带来的损失不仅仅是存储和带宽。

每个新运行时应用程序都会增加百兆或更多的内存使用量。这种情况会迅速增加。大多数电脑都没有足够的 RAM 来运行所有采用交替运行时的应用程序。Raspberry Pi 400 的内存只有 4 GB。低端 Chromebook 只有 2 GB。经济型笔记本往往只有 8 GB,这主要归功于 Windows 10 的臃肿,但这些应用打包解决方案正在迎头赶上。

更大的问题是,这些应用程序的启动实际上需要数秒时间。它们必须从磁盘上加载自己的所有库,而不是使用系统内存中已有的库。

Snap 的运行速度是最慢的,这主要是因为它将所有数据存储在 squashfs 镜像中。Snap 会在启动时挂载所有已注册的 Snap,而不是事先提取所需的元数据,这可能是为了减轻速度慢的问题。他们只是将部分缓慢的启动时间移到了电脑的启动时间。mountfdisk -l 中会显示各种快照垃圾。安装的 Snap 越多,电脑启动速度就越慢,即使你不使用它们。

今天,在我的机器上,KCalc Snap 需要整整 7 秒钟才能启动。不只是启动后的第一次,每次都是如此。七秒钟才能启动一个计算器。

Canonical 在 Ubuntu 18.04 中开始将 GNOME 计算器等基本桌面应用程序转换为 Snap。由于用户体验非常糟糕,他们在 Ubuntu 20.04 中又悄悄地将其转换为普通应用程序。如果这些技术连他们自己的应用程序都不够好,连计算器这么基本的应用程序都不够好,那为什么你的应用程序会好呢?

驱动程序

替代运行时的一个主要问题是驱动程序。新的图形硬件需要新的图形库,而新的图形库有大量的依赖关系。Mesa 需要依赖 LLVM 来编译着色器。NVidia 驱动程序依赖于内核模块,而内核模块的版本必须与库的版本完全匹配。所有这些库都有自己的传递依赖关系,如 libdrm、libstdc++ 和 glibc。如果想让新硬件正常工作,就必须使用所有这些库的新版本。

Linux 发行版,尤其是那些有滚动发行版或硬件启用软件包的发行版,在为新硬件更新这些库方面做得很好。捆绑运行时则不然。

看看 Steam 为了让驱动程序在 Steam 运行时中正常工作所经历的痛苦吧。他们使用各种启发式方法来决定是否用主机系统的库覆盖运行时中的每个库,因此每个应用程序都运行在一个科学怪人的大杂烩库上。这不是构建稳定软件的方法。

Flatpak 认识到,将库与主机系统混合在一起会造成混乱。相反,他们希望在运行时中捆绑自己的图形驱动程序,并根据新硬件定期更新。但他们无法控制最重要的部分--内核,因此无法直接打包依赖于特定内核版本或专有内核模块的驱动程序。因此,运行时被分解为多个扩展,扩展可以采用 Steam 的方式调入原生驱动程序,甚至可以即时下载与内核模块匹配的特定 NVidia 驱动程序。

AppImage 也会将主机库与运行时混合在一起,但不是动态混合;他们只是在打包时决定排除哪些库,因此其可靠性甚至不如 Steam。Docker 有一个 NVidia 工具包,必须同时安装在主机系统和容器运行时,才能让驱动程序正常工作。而 Snap 则不知在做什么。这些都不是合适的解决方案。

驱动程序本应是操作系统的职责。这正是操作系统的强项。为什么我们要如此努力地绕过操作系统为本地应用程序默认提供的驱动程序呢?

顺便说一句,这并不是视频游戏特有的问题。现在很多现代应用程序都直接使用硬件加速图形,甚至终端文本编辑器也是如此。许多应用程序都需要 GPU 进行后台计算。视频编辑器等生产力应用程序、使用机器学习的应用程序、空间/天文学可视化等科学工具、任何像 Google 地球这样的 3D 应用程序......所有这些都需要访问现代视频硬件。随着应用程序的速度越来越快,功能越来越多,用户界面越来越丰富,这种情况只会越来越多。

安全

Flatpak 允许应用程序声明它们需要完全访问你的文件系统或主文件夹,但图形软件商店仍声称这些应用程序是沙盒的。我们以前讨论过这个问题。下面是我在新安装的 Fedora 34 上的软件应用程序中搜索 GIMP 时发生的情况:

image.png
Fedora 声称 GIMP 是沙盒版的。如果点击 "权限 "旁边的 "高",就会看到一个小感叹号,显示它有 "文件系统 "权限。

这样的应用程序可以将恶意软件可执行文件放在主文件夹中的任意位置,并在 ~/.profile 中添加一行,或在 ~/.config/autostart/ 中添加一个桌面条目,使其在下次登录时自动启动。它不仅会在任何容器外运行,甚至在卸载应用程序后仍会继续存在。

这正是一个邪恶的应用程序为突破沙盒所做的事情。病毒利用沙盒应用程序的安全漏洞也会这么做。

假设 libjpeg 存在零日远程代码执行漏洞。您在 Flatpak GIMP 中打开一个看似无害的 JPEG 文件,它就会将其有效载荷设置为自动启动,并放到您的主文件夹中。沙盒在这方面有什么帮助?无论 GIMP 是否在沙盒中,该病毒的行为都是一样的。唯一的区别是:a) 替代运行时中的 libjpeg 可能比 Linux 发行版中的 libjpeg 过期时间更长;b) 病毒更有可能对沙箱应用程序起作用,因为所有安装都将使用完全相同的 libjpeg 二进制文件。

值得称赞的是,Snap Store 应用程序会显示一个警告:"此应用程序不受限制。它可以访问所有个人文件和系统资源"。你要问哪些应用程序会显示这个警告?所有的。KCalc 有。所有编辑精选都有。在我为这篇博文进行的测试中,我找不到一款不显示该警告的应用程序。

"有总比没有好!"

Flatpak 和 Snap 的辩护者声称,有安全保障总比没有好。事实并非如此。从纯粹的技术角度来看,对于可以访问文件系统的应用程序来说,安全性完全等于零。实际上,这比什么都没有更糟糕,因为它会导致人们对在互联网上随意找到的应用程序产生更多的信任。

看看这位作者在赞扬 Flatpak 和 Snap 的同时,还在抱怨 AppImages 的安全性:

我通过源代码、apt、Snap 和 Flatpak 安装应用程序,不存在区别对待。只要应用程序能按预期安装和运行,无论软件包格式如何,我都会安装。

但有一个例外:AppImages

...

在极少数情况下,我愿意使用 AppImage,但只有在我绝对信任开发者的情况下才会这样做。为什么呢?请记住,AppImage 是一个你只需下载并运行的应用程序。任何人都可以制作一个 AppImage,宣称它是一款必备软件,在其中加入一些邪恶的东西,然后提供下载。

他对 AppImages 深表怀疑,但对 Flatpaks 或 Snaps 却不以为然,因为他相信它们的安全措施能保证他的安全。这就是在沙盒问题上撒谎的危险。

权限和门户

Flatpak 正在开发一种细粒度权限系统,以提高沙箱的安全性。权限指的是应用程序是否被允许访问麦克风或打印机。门户是指在沙箱外运行的文件打开对话框,因此沙箱中的应用程序只能获取用户选择的文件。

Flatpak 记录了这些门户,并提供了 libportal 这个客户端库来访问它们。不过,这并不是真正针对单个应用程序的。所有这些都是为了集成到工具包中。来自文档

GTK3 和 Qt5 等界面工具包实现了对门户的透明支持,这意味着应用程序无需做任何额外工作即可使用它们(值得查看每个工具包支持哪些门户)。

显然,为应用程序本身开发客户端 API 与 Flatpak 的使命背道而驰。他们希望在 Flatpak 上运行的应用程序对 Flatpak 一无所知。他们宁愿修改 GTK 等核心库,以便与 Flatpak 集成。因此,举例来说,如果你想打开一个文件,你不会调用 Flatpak API 函数来获取文件或请求权限。取而代之的是,你调用一个普通的 GTK 文件打开对话框,然后 Flatpak 运行时的 GTK 在内部完成与 Flatpak 服务的门户交互(使用各种黑客手段让你 "正常 "访问文件,并假装你没有被沙盒控制)。

这是最复杂、最脆弱的实现方式。这也与其他沙盒平台的工作方式完全不同。如果我想获得 Android 上的文件访问权限,我不能只尝试用 Java File API 打开文件,然后指望它会神奇地提示用户。我必须先调用Android特定的接口来请求权限。iOS 也是如此。那么,为什么我不能调用 flatpak_request_permission(PERMISSION),并在用户同意或拒绝时获得回调呢?

这就是原因。Fedora 正在将所有 rpm 应用程序自动转换为 Flatpak。为了让这项工作顺利进行,他们需要 Flatpak 权限系统和 Flatpak 在总体上不需要对应用程序进行任何更改。

他们到底为什么要对应用程序进行大规模自动转换?你的猜测和我的一样。视频声称 Fedora 的应用程序比上游的质量更高,而且 Fedora 还在旧版本上提供了 Flatpaks。我认为更有可能的是,他们只是想要大量自动转换的应用程序,让 Flatpak 看起来很有用。不管是什么原因,很明显,这一要求影响了他们许多糟糕的设计决策。

标识符冲突

所以 Fedora 自动将所有应用程序转换为 Flatpak。它至少会将它们命名为 Fedora 特有的名称空间吗?

不,没有。Fedora 将其 GIMP 的 Flatpak 发布为 org.gimp.GIMP。这与 GIMP 开发者在 Flathub 上发布的 org.gimp.GIMP 官方版本相冲突。在全新安装的 Fedora 34 中,如果添加 Flathub 软件源并输入 flatpak install org.gimp.GIMP,系统会提示你安装哪一个:

[nick@fedora active]$ flatpak install org.gimp.GIMP
Looking for matches…
Remotes found with refs similar to ‘org.gimp.GIMP’:

   1) ‘fedora’ (system)
   2) ‘flathub’ (system)

Which do you want to use (0 to abort)? [0-2]:

如果您选择选项 1,您将得到使用 Fedora 35 650 MB 运行时的 Fedora 补丁构建的 GIMP。如果选择选项 2,则会得到使用 1.8 GB freedesktop.org GNOME 运行时的另一个 GIMP 版本。

反向 DNS 的全部意义不就是为真正拥有 gimp.org 域名的人保留 org.gimp 前缀吗?Fedora 怎么能在伪装成上游开发者的同时发布应用程序呢?如果主要的 Linux 发行版都不尊重 DNS,谁还会尊重呢?

顺便说一句,Flathub 也不强制执行 DNS 所有权。他们允许任何人发布任何内容;他们只是希望应用程序由其作者控制。合理的安全策略应该是,允许发布者使用特定应用程序前缀需要 DNS 挑战。

复杂性

关于软件设计简洁性重要性的文章不胜枚举。最早期的例子可能就是 "越简单越好"。现代人常说的一句话是 "软件的复杂性正在杀死我们"。2021 年,软件开发的状况简直惨不忍睹。

你会认为,如果这些打包机制想要吸引软件开发人员,它们就会崇尚简单。事实上,它们的做法恰恰相反。我们已经讨论过的驱动程序、沙箱和权限/门户问题,几乎没有触及使这一切运转起来所涉及的复杂性的表面。用 "坏事变好事 "的话来说,它们甚至不再是 "正确的事情"。在这一点上,它们只是为了复杂而复杂。

容器化的支持者认为,容器化是解决所有问题的办法,是钉子的锤子。我们现在有多个基于容器化一切的 Linux 发行版(如 Fedora CoreOSMocaccinoOS)。我们有一场在嵌入式上采用 Docker 和 Snap 的大运动(如 balenaOSUbuntu Core)。

请继续观看前面链接的视频,看看它是如何陷入疯狂的:嵌套在 Flatpak 中的 Steam;嵌套在 Soldier 运行时中的 Scout 运行时从 Freedesktop 运行时中调入驱动程序;Steam 对其 Flatpak 容器进行 IPC 调用,以创建具有更多运行时的并行容器。

image.png
Steam 和 Flatpak 容器及运行时间的各种组合。图中未显示:Steam 和游戏直接在用户的本地环境中运行,就像在其他操作系统上一样。

复杂程度远比上述视频显示的还要糟糕。Flatpak 使用 libostree 将所有数据存储在文件系统上方的内容可寻址重复层中。Steam 现在使用 libcapsule,它使用 dlmopen() 命名空间,因此游戏可执行文件和驱动程序库可以将不同版本的 libstdc++ 加载到同一进程中。我们甚至还没有谈到 Wine/Proton,它是另一个疯狂的层次。

这是软件复杂性将我们推向崩溃边缘的一个生动例子。这是可以想象到的最复杂的软件分发方式。当大量依赖于这种脚手架的应用程序发布后会发生什么?如何对其进行维护?地球上有多少人能真正理解这一切是如何运作的?

服务

所有这些应用程序打包系统都要求用户在电脑上安装一些服务,然后才能安装任何软件包。

值得称赞的是,AppImage 在技术上并不需要服务来运行应用程序,但如果没有服务,它就无法与桌面集成。有一段时间,我需要使用 AppImage 应用程序,而我的解决办法就是把它放在我的 ~/Downloads 文件夹中,然后从文件管理器中双击运行它。这种用户体验太糟糕了。

所有的桌面集成(启动项、模拟类型、图标、更新)都由 appimaged 或 AppImageLauncher 提供,用户必须安装其中之一才能使用这些功能。因此,在实践中,AppImage 与我们的其他解决方案并无不同:它需要服务才能使用。

如果用户没有这项服务,那么安装应用程序时就又多了一个障碍。一些发行版,尤其是 Fedora,会预装 Flatpak。一些发行版,尤其是 Ubuntu,会预装 Snap。SteamOS 预装了 Steam。除了这些特殊情况,用户必须在安装应用程序前安装正确的服务。开发者必须教会他们这样做,否则就会失去所有搞不清楚或懒得去做的用户。

应用程序商店

大多数这些技术的主要目标都是支持 "应用商店 "体验:Docker HubFlathubSteam StoreSnapcraftAppImageHub(但不是 AppImageHub?)这些技术都是围绕这一模式设计的,因为所有者都希望从销售收入中分一杯羹,或收取企业分发费用。(Flathub 只说他们目前不处理付款,但马上就会有了)。

这就是 Ubuntu 希望每个人都使用 Snap,而不是帮助我们构建能在 Ubuntu 上运行的应用程序的真正原因。这也是他们封闭Snap服务器源代码的原因。他们希望Snap能像安卓系统那样 "开放",只有一个官方商店,而且侧载应用程序也尽可能地令人讨厌。

这与传统的 Windows 体验大相径庭:只需下载安装程序,点击几下 "下一步",就能安装应用程序并与桌面完全集成。这是真正的自由。安装应用程序没有任何要求,没有其他步骤,没有任何障碍。这就是 Windows 应用商店,甚至在某种程度上 MacOS 应用商店失败的原因。它们无法与自己平台提供的自由相媲美。

我知道,自由软件和隐私保护人士不想让专有应用程序在他们的 PC 上有如此大的自由度。但绝大多数用户和独立软件供应商并不在乎。用户想要的是简单(高效)的安装。最大的软件厂商想要的是直接向客户发送软件的自由,而不需要服务或中心的干预。

这在 Linux 桌面上确实可行。让我们在下一节讨论这个问题。

向后兼容性的现状

在 Linux 社区中,依赖库在不同发行版和版本升级中保持二进制兼容似乎是一种集体创伤。这些备用运行时工具显然是由那些拒绝考虑在用户系统上使用任何东西(就 Flatpak 而言,甚至连驱动库都不考虑)的人构建的。我在这里要告诉你,你不必再害怕了。

近年来,向后兼容性的情况已经大为改观。Linux 内核慢慢地将其传奇的向后兼容性文化向堆栈输出。glibc(自 2.1 版起)和 libstdc++(自 GCC 5 版起)等核心库都打算无限期地保持向后兼容。freedesktop.org 在实现各发行版运行环境标准化方面取得了巨大进步。Debian 和其他发行版大多已停止对其软件包进行 ABI 破坏性定制。ABI 实验室(ABI Laboratory)等网站会跟踪 ABI 的变化,以便及早预警。Linux 标准库(LSB)虽然现在似乎已不复存在,但它在功能标准化和防止 ABI 破坏方面取得了重大进展。

就在上周,我使用了几个以普通二进制压缩包形式发布的 Linux 应用程序,它们都能在我的本地环境中运行。DevilutionXOpenTTD 的通用 Linux 二进制版本使用我的本地 SDL 来处理图形、声音和输入。Master PDF Editor 使用了一长串本地库,包括 Qt 5。QNX 软件中心是为 LSB 编译的,使用的是本地 GTK 3。为什么会这样?因为现在的大多数程序库都能很好地向后兼容。

GOG.com 在 Linux 支持方面的策略与 Steam 恰恰相反,其工作方式与 Windows 的传统安装程序一样。每款游戏都针对特定的 Ubuntu LTS 版本:14.04, 16.04, 18.04.只要你的程序库至少是那个版本的,游戏就能运行。他们会提供使用 mojosetup 制作的自解压安装向导,这有点像以前基于 Windows 的 WISEInstallShield 安装程序(只不过它们不需要 root 访问权限)。你以普通用户身份下载并运行安装程序,点击下一步->下一步->下一步,游戏就安装好了。完全桌面集成,没有巨大的备用运行时,没有 root 权限,无需服务。任何 ISV 都能以这种方式发送软件:只需将一个可自动安装的可执行文件直接发送给用户即可。

它并不完美。特别是,mojosetup 无法安装缺失的依赖项(目前还没有),GOG 也没有完全遵循 XDG 的安装路径规范(目前还没有)。这些都是可修复的小问题,与 Flatpak 的问题相比,根本不值一提。这就是简单,这就是真正的自由,用户体验的反差是惊人的。无论如何,我都会选择 mojosetup 安装程序,而不是 AppImage、Flatpak 或 Steam。

对于开发人员来说,是的,这可能比制作 AppImage 更难。在不同版本的库之间,偶尔仍会出现错误。发行版之间偶尔也会有差异。这些都是可以解决的问题。一开始可能会很痛苦,但这是值得的:通过解决用户库中的问题而不是试图替换它们,你将为用户提供更好的用户体验。

强迫发行版保持兼容性

随着时间的推移,向后兼容性的情况会越来越好。为原生 Linux 桌面提供的专有软件越多,主要发行版就越不可能接受上游破坏。想象一下,如果数百万办公人员在 Ubuntu 上使用 Excel。如果发行版的升级导致Excel崩溃,你认为企业会有多大的怨言?

2014 年,Linus Torvalds 建议 Valve 挽救 Linux 桌面。他希望他们能发布大量依赖于 Linux 桌面核心库的专有游戏,最终迫使发行版保留其 ABI。不幸的是,正如他所预料的那样,这并没有发生。Steam 没有依赖本地运行库,而是用自己的运行库取代了大部分本地运行库。

早在 2012 年,Steam 就需要更换一些库才能让游戏正常运行。如今,这已不再必要。那么,他们为什么还在推行他们的运行时呢?如果 Steam 废弃了他们的运行时,放弃对新游戏的容器化,让所有新游戏都只使用原生系统库,我们还能取得多大的进步?如果发行版升级破坏了玩家最喜爱的游戏,你认为玩家会有多大的怨言?

几年前,Canonical 决定放弃 Ubuntu 19.10 中的 32 位库。在激起众怒,包括 Wine 和 Steam 威胁要放弃对 Ubuntu 的支持之后,他们改变了决定。试想一下,如果 Steam 游戏依赖于更多的系统库,Ubuntu 还能有多稳定。

对于正在阅读这篇文章的程序库开发人员来说,向后兼容性对于一个平台的普及有多么重要,怎么强调都不过分。向后兼容性是 Windows 至今仍是主流桌面操作系统的主要原因。25 年来,微软成功地保持了 Win32 API 的稳定性。为 Windows 95 构建的 GUI 应用程序仍可在 Windows 10 上开箱即用。企业其实很在意这一点!他们使用对其业务至关重要的古老专有软件,而这些软件的源代码早已消失在时间的长河中。一个会破坏其软件的平台根本就不是平台。

GTK 问题

对于我所说的 Linux 库的稳定性,有一个明显的例外。这个例外就是 GTK。GTK 以肆无忌惮地破坏其库而闻名。这历来是 Linux 二进制应用程序最大的问题之一。

我认为这部分是由于自由软件的激进立场造成的。一些倡导者坚信用户应该能够重新编译他们的软件,因此他们强迫用户这样做。他们破坏库的目的似乎只是为了说:"重新编译!哦,你不能吗?这会让你学会使用二进制软件!"用户当然不想重新编译他们的软件,但 GNOME 开发者通常不知道用户真正想要的是什么。

随着 GTK 4 最近的发布,我们几乎没有理由相信情况会有所改善。他们曾一度提议提高所有主要和次要版本的 soname。值得庆幸的是,他们已经扭转了方向,但他们最新的版本计划仍然表明,他们希望加快主要版本的发布速度,以便更频繁地进行破坏性修改并移除过时的功能。他们至少打算在主要版本系列中保持 ABI 的稳定性,但考虑到他们的过往记录,当人们相信 GTK 4 会保持稳定时,它已经过时了。

这听起来像是个坏消息,但也有一线希望:虽然他们在捣鼓 GTK 4,但并没有破坏 GTK 3。

正在进行的向 GTK 4 的过渡给了我们一个机会。GTK 3 ABI 终于成为了一个稳定的目标,而且它仍然预装在大多数发行版中,因为许多内置应用程序尚未升级。如果我们能让足够多的二进制应用程序依赖于它,发行版就会被迫维护它,甚至 "永远 "预装它,就像微软 "永远 "维护 Win32 API 一样。

我强烈建议所有应用程序开发人员(无论是否开源)尽可能推迟升级到 GTK 4。我们能推迟的时间越长,GTK 3 就会越稳定。如果 GTK 团队希望我们使用 GTK 4,他们就必须证明 GTK 4 多年来的稳定性,而不是简单地用 GTK 5 取而代之。

我不是说 GTK 3 很好。我要说的只是它的存在。对于桌面应用程序来说,没有其他工具包可以称得上实用,而且相对稳定,并预装在绝大多数 Linux 桌面上。我们都希望有一天会有更好的东西出现,但与此同时,GTK 3 就是我们所拥有的。

现在是发布针对 Linux 桌面的二进制应用程序的最佳时机。我指的不是针对自己的捆绑运行环境,而是真正针对用户的运行环境。现在正是时候。

Flatpak 可以修复吗?

事情是这样的。实际上,我认为 Flatpak(现在是 Steam)使用的沙盒工具 Bubblewrap 非常不错。它是使应用程序沙箱功能足以与 Android 或 iOS 竞争的关键技术。如果它能用于隐藏 /home 等敏感文件,而只是将本地 /usr 直接挂载到沙盒中,那就太棒了。不幸的是,Flatpak 的做法恰恰相反。

如果 Flatpak 开发人员真的想要一个能与 Android 和 iOS 相媲美的应用程序发布系统,那么沙盒、权限和门户系统就应该是唯一的重点。

他们应该这样做:

  • 放弃与运行时相关的一切,转而将本地 /usr(或来自 /usr的一组受限核心库)以只读方式挂载到每个容器中;

  • 在 Flatpaks 中添加元数据,以声明 Flatpak 服务将通过主机发行版的软件包管理器安装的库依赖关系(或许可使用生成的元软件包,以便干净利落地删除);

  • 建立一个细粒度的用户交互式运行时权限系统,要求应用程序调用特定于 Flatpak 的 API 来激活权限对话框;以及

  • 废弃安装时权限(尤其是文件系统访问权限),并从 Flathub 中移除所有使用这些权限的应用程序。

在这一系统下,将鼓励应用程序静态链接其许多依赖库,但要使用系统 GTK/Qt/SDL、OpenGL/Vulkan、OpenSSL/curl 和其他大型或安全关键库。社区可以维护指导原则和封装程序,使针对系统库进行动态链接的应用程序能够跨版本和跨发行。应用程序应通过 Flatpak 客户端 API 直接更改沙箱运行和请求权限。

这更类似于 iOS 和 Android 的工作方式。但这意味着要放弃 95% 的 Flatpak。这将是一个翻天覆地的变化,他们还不如换个名字重新开始。我不认为这会发生。

基于本地应用程序沙盒技术的应用程序商店是一个合理的想法。当然,我并不认为它适用于所有应用。我认为 Excel 或 Photoshop 等软件完全没有必要使用沙盒技术。用户并不关心这些应用程序的沙盒问题,而它们的供应商也会拒绝沙盒。

但对于独立开发者开发的小型应用程序和游戏来说,一个适当的沙盒应用程序市场理论上可以扩大它们的覆盖范围。它可以消除在电脑上运行应用程序所需的信任,并使本地应用程序更接近网络应用程序的易用性。

对开发者来说,这当然不是件容易的事,但优秀的原生应用仍能提供比网络应用更好的用户体验,因此一个合适的沙盒应用商店有可能让原生应用重新崛起。微软的尝试显然失败了,但 macOS 却没有。也许 Linux 也能成功。

结论

Snap 和 Flatpak 的现有版本至少已有五年历史。AppImage、Steam 和 Docker 的历史甚至更长。以上这些都不是新事物。替代运行时的问题从一开始就为人所知,但在解决这些问题方面却进展甚微。我不认为这些是新技术的成长之痛。这些都是基本问题,而且大多无法解决。

所有这些技术本质上都是在另一个操作系统之上构建整个操作系统,只是为了避免向后兼容的挑战。这样做带来的问题远远多于解决的问题。兼容性问题最好由真正的操作系统来解决,而不是在其上进行一些容器化的杂交。我们需要尽可能多地使用系统库,让应用程序能够原生运行。如果我们还有希望吸引专有软件使用 Linux,我们就必须大幅简化一切

如果你是 Linux 发行版的维护者,请理解所有这些解决方案的目的。你辛辛苦苦建立软件仓库、维护库、测试无数系统配置、设计一致的用户体验......他们正试图将这一切付诸东流。每一种运行时打包机制都在试图颠覆操作系统,尽可能用自己的东西取而代之。你为什么要支持这种做法?

我恳求你们,不要使用这些打包工具。不要在你的 Linux 发行版中添加它们的服务,不要使用以这种方式打包的应用程序,也不要发布使用它们的应用程序。大规模容器化和备用运行时不可能成为 Linux 桌面应用程序的未来。如果这真的是未来的发展方向,那么未来将会非常糟糕,我们最终都会回到 macOS 或 Windows 上。

就我个人而言,我更感兴趣的是如何在 Linux 上使用 Excel 和 Photoshop,而不是不值得信赖的驱动程序和游戏,所以我并不关心沙箱、权限、门户、应用程序商店、备用运行时或 Flatpak 所做的任何事情。要说服微软和 Adobe 将其软件套件移植到 Linux 上,这些东西只会适得其反。吸引这些厂商的唯一办法就是为他们提供一个稳定的平台,而不是把他们锁在一个盒子里。

在今后的文章中,我将讨论直接针对桌面 Linux 的一些问题,介绍我正在研究的一些东西,并希望能提出不依赖于其他运行时的真正解决方案。

更新:添加了指向 libportal 的链接,添加了对 AppImageLauncher 的引用,并更正了对 GTK 4 版本方案的描述。