很久以前,Linux 发行版会发布一个操作系统,以及所有可用的软件。 没有“第三方”软件的概念,因为一切都是发行版的一部分。 应用程序与其说被安装,不如说是在你购买或下载的许多软盘或后来的 CD 之一上的一个巨大的软件仓库中启用。
随着互联网的普及,这演变成了更加方便的东西,如今“应用商店”的概念诞生了。 当然,Linux 发行版倾向于将其称为软件仓库,或简称repo,以及一些“品牌”的变体,例如Ubuntu 软件中心,或者具有典型的 GNOME 简约风格,简单地称为软件。
当开源软件仍然是一种新事物,并且开源应用程序的数量是一个数字而不是理论上的数字时,这种模式运行良好。 在今天的 GitLab、GitHub 和 Bitbucket 世界中(以及许多许多更多),几乎不可能统计开源项目的数量,更不用说将它们打包到仓库中了。 即使是 Debian 及其强大的软件包维护者团队,如今也没有任何 Linux 发行版可以声称或希望拥有每个可安装的开源项目的软件包。
当然,Linux 包不必位于仓库中才能安装。 任何程序员都可以打包他们的软件并从他们自己的网站上分发它。 但是,由于仓库被视为发行版不可或缺的一部分,因此没有通用的打包格式,这意味着程序员必须决定是发布 .deb
还是 .rpm
,或是 AUR 构建脚本,或是 Nix 或 Guix 软件包,或是 Homebrew 脚本,或者只是一个几乎通用的 .tgz
存档用于 /opt
。 这对于每天生活在 Linux 中的开发人员来说不堪重负,更不用说那些只是想尽最大努力支持免费和开源目标的开发人员了。
为什么选择 Flatpak?
Flatpak 项目提供了一种通用的打包格式,以及一种去中心化的分发方式,此外还具备可移植性和沙盒功能。
- 通用安装 Flatpak 系统,无论您使用哪个发行版,都可以运行 Flatpak。 无需守护程序或 systemd。 同一个 Flatpak 可以在 Fedora、Ubuntu、Mageia、Pop OS、Arch、Slackware 等上运行。
- 去中心化开发人员可以创建和签署他们自己的 Flatpak 软件包和仓库。 无需请求仓库以包含软件包。
- 可移植性如果您在您的系统上有 Flatpak,并且想将其交给朋友以便他们可以运行相同的应用程序,您可以将 Flatpak 导出到 USB 拇指驱动器。
- 沙盒化Flatpak 使用基于容器的模型,允许在同一个系统上存在多个版本的库和应用程序。 是的,您可以轻松安装最新版本的应用程序进行测试,同时保留您所依赖的旧版本。
构建 Flatpak
要构建 Flatpak,您必须首先安装 Flatpak(使您能够使用 Flatpak 软件包的子系统)和 Flatpak-builder 应用程序。
在 Fedora、CentOS、RHEL 和类似系统上
$ sudo dnf install flatpak flatpak-builder
在 Debian、Ubuntu 和类似系统上
$ sudo apt install flatpak flatpak-builder
您还必须安装构建您正在打包的应用程序所需的开发工具。 由于开发您现在正在打包的应用程序的性质,您可能已经安装了开发环境,因此您可能没有注意到这些组件是必需的,但是如果您开始使用 Jenkins 或从容器内部构建 Flatpak,那么您必须确保您的构建工具是您的工具链的一部分。
对于第一个示例构建,本文假设您的应用程序使用 GNU Autotools,但是 Flatpak 本身支持其他构建系统,例如 cmake
、cmake-ninja
、meson
、ant
,以及自定义命令(在 Flatpak 术语中是simple
构建系统,但这绝不意味着构建本身实际上很简单)。
项目目录
与严格的 RPM 构建基础设施不同,Flatpak 不强制执行项目目录结构。 我喜欢基于软件的 dist 软件包创建项目目录,但从技术上讲,您完全可以将您的 Flatpak 构建过程与您的源代码目录集成。 但是,从您的 dist 软件包构建 Flatpak 在技术上更容易,而且也是一个更简单的演示,因此本文使用了该模型。 为 GNU Hello 设置一个项目目录,作为您的第一个 Flatpak
$ mkdir hello_flatpak
$ mkdir src
下载您的可分发源代码。 在此示例中,源代码位于 https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
。
$ cd hello_flatpak
$ wget https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
清单 (Manifest)
Flatpak 由清单定义,该清单描述了如何构建和安装它所交付的应用程序。 清单是原子性的和可重现的。 但是,Flatpak 存在于“沙箱”容器中,因此清单基于一个几乎为空的环境,其根目录称为 /app
。
前两个属性是您正在打包的应用程序的 ID 及其提供的命令。 应用程序 ID 必须对您正在打包的应用程序是唯一的。 制定唯一 ID 的规范方法是使用由代码负责人,后跟应用程序名称组成的三元值,例如 org.gnu.Hello
。 应用程序提供的命令是您在终端中键入以运行应用程序的任何内容。 这并不意味着该应用程序旨在从终端而不是“活动”或“应用程序”菜单中的 .desktop
文件运行。
在一个名为 org.gnu.Hello.yaml
的文件中,输入此文本
id: org.gnu.Hello
command: hello
清单可以用 YAML 或 JSON 编写。 本文使用 YAML。
接下来,您必须定义此 Flatpak 软件包提供的每个“模块”。 您可以将模块视为依赖项或组件。 对于 GNU Hello,只有一个模块:GNU Hello。 更复杂的应用程序可能需要一个特定的库或另一个完整的应用程序。
modules:
- name: hello
buildsystem: autotools
no-autogen: true
sources:
- type: archive
path: src/hello-2.10.tar.gz
buildsystem
值标识 Flatpak 必须如何构建模块。 每个模块都可以使用自己的构建系统,因此一个 Flatpak 可以定义多个构建系统。
no-autogen
值告诉 Flatpak 不要运行 autotools
的设置命令,因为 GNU Hello 源代码是 make dist
的产品,所以没有必要。 如果您正在构建的代码不容易构建,那么您可能需要安装 autogen
和 autoconf
来为 autotools
准备源代码。 此选项根本不适用于不使用 autotools
的项目。
type
值告诉 Flatpak 源代码位于存档中,这会在构建之前触发必要的解压缩任务。 path
指向源代码。 在此示例中,源代码存在于本地构建机器的 src
目录中,但是您可以将源代码定义为远程位置
modules:
- name: hello
buildsystem: autotools
no-autogen: true
sources:
- type: archive
url: https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
最后,您必须定义应用程序运行和构建所需的平台。 Flatpak 维护者提供运行时和 SDK,其中包括常见的库,包括 freedesktop
、gnome
和 kde
。 基本要求是 freedesk
运行时和 SDK,尽管这可能会被 GNOME 或 KDE 取代,具体取决于您的代码运行需要什么。 对于此 GNU Hello 示例,只需要基本知识。
runtime: org.freedesktop.Platform
runtime-version: '18.08'
sdk: org.freedesktop.Sdk
整个 GNU Hello flatpak 清单
id: org.gnu.Hello
runtime: org.freedesktop.Platform
runtime-version: '18.08'
sdk: org.freedesktop.Sdk
command: hello
modules:
- name: hello
buildsystem: autotools
no-autogen: true
sources:
- type: archive
path: src/hello-2.10.tar.gz
构建 Flatpak
现在定义了软件包,您可以构建它。 构建过程会提示 Flatpak-builder 解析清单并解析每个需求:它确保必要的平台和 SDK 可用(如果它们不可用,那么您必须使用 flatpak
命令安装它们),它会解压缩源代码,并执行指定的 buildsystem
。
启动命令
$ flatpak-builder build-dir org.gnu.Hello.yaml
如果目录 build-dir
尚不存在,则会创建该目录。 名称 build-dir
是任意的;您可以将其称为 build
或 bld
或 penguin
,并且您可以在同一个项目目录中拥有多个构建目标。 但是,术语 build-dir
是文档中常用的值,因此将其用作文字值可能会有所帮助。
测试您的应用程序
您可以通过运行构建命令以及 --run
选项来在构建之前或之后测试您的应用程序,并以 Flatpak 提供的命令结束该命令
$ flatpak-builder --run build-dir \
org.gnu.Hello.yaml hello
Hello, world!
使用 Flatpak 打包 GUI 应用程序
打包一个简单的自包含的hello world应用程序非常简单,幸运的是,打包一个 GUI 应用程序并不难多少。 最难打包的应用程序是那些不依赖于常用库和框架的应用程序(在打包的上下文中,“常用”意味着任何不已经由其他人打包的东西)。 Flatpak 社区为许多组件提供 SDK 和 SDK 扩展,否则您可能必须自己打包。 例如,在打包 pdftk
的纯 Java 实现时,我使用在 Flatpak Github 存储库中找到的 OpenJDK SDK 扩展
runtime: org.freedesktop.Platform
runtime-version: '18.08'
sdk: org.freedesktop.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.openjdk11
Flatpak 社区在应用程序运行所需的基础设施上做了大量工作,以简化开发者的打包流程。例如,来自 KDE 社区的 Kblocks 游戏需要 KDE 平台才能运行,而该平台已经可以通过 Flatpak 获得。额外的 libkdegames
库未包含在内,但将其添加到您的 modules
列表中与添加 kblocks
本身一样容易。
这是 Kblocks 游戏的 manifest 文件
id: org.kde.kblocks
command: kblocks
modules:
- buildsystem: cmake-ninja
name: libkdegames
sources:
type: archive
path: src/libkdegames-19.08.2.tar.xz
- buildsystem: cmake-ninja
name: kblocks
sources:
type: archive
path: src/kblocks-19.08.2.tar.xz
runtime: org.kde.Platform
runtime-version: '5.13'
sdk: org.kde.Sdk
正如您所看到的,manifest 文件仍然简单明了且相对直观。构建系统不同,运行时和 SDK 指向 KDE 而不是 Freedesktop,但结构和要求基本相同。
然而,由于它是一个 GUI 应用程序,因此需要一些新的选项。首先,它需要一个图标,以便在 Activities 或应用程序菜单中列出时,看起来美观且易于识别。Kblocks 在其源代码中包含一个图标,但 Flatpak 导出的文件名称必须使用应用程序 ID 作为前缀(例如 org.kde.Kblocks.desktop
)。最简单的方法是直接在应用程序源代码中重命名该文件,只要您在 manifest 文件中包含此指令,Flatpak 就可以为您完成此操作。
rename-icon: kblocks
GUI 应用程序的另一个独特之处在于,它们通常需要与常见的桌面服务集成,例如图形服务器(X11 或 Wayland)本身、诸如 Pulse Audio 等声音服务器以及进程间通信 (IPC) 子系统。
对于 Kblocks,要求是
finish-args:
- --share=ipc
- --socket=x11
- --socket=wayland
- --socket=pulseaudio
- --device=dri
- --filesystem=xdg-config/kdeglobals:ro
这是最终的完整 manifest 文件,使用 URL 作为源代码,以便您可以轻松地在自己的系统上尝试。
command: kblocks
finish-args:
- --share=ipc
- --socket=x11
- --socket=wayland
- --socket=pulseaudio
- --device=dri
- --filesystem=xdg-config/kdeglobals:ro
id: org.kde.kblocks
modules:
- buildsystem: cmake-ninja
name: libkdegames
sources:
- sha256: 83456cec44502a1f79c0be00c983090e32fd8aea5fec1461fbfbd37b5f8866ac
type: archive
url: https://download.kde.org/stable/applications/19.08.2/src/libkdegames-19.08.2.tar.xz
- buildsystem: cmake-ninja
name: kblocks
sources:
- sha256: 8b52c949e2d446a4ccf81b09818fc90234f2f55d8722c385491ee67e1f2abf93
type: archive
url: https://download.kde.org/stable/applications/19.08.2/src/kblocks-19.08.2.tar.xz
rename-icon: kblocks
runtime: org.kde.Platform
runtime-version: '5.13'
sdk: org.kde.Sdk
要构建应用程序,您必须安装 KDE 平台和 SDK Flatpaks(截至本文撰写时为 5.13 版本)。构建应用程序后,您可以使用 --run
方法运行它,但要查看应用程序图标,您必须安装它。
分发和安装您构建的 Flatpak
Flatpak 的分发通过存储库进行。
您可以在 Flathub.org 上列出您的应用程序,这是一个社区网站,旨在成为一个技术上去中心化(但在精神上是中心化的)的 Flatpak 位置。要提交您的 Flatpak,将您的 manifest 文件放入 Git 存储库,并 在 Github 上提交 pull request。
或者,您可以使用 flatpak build-export
命令创建自己的存储库。
您也可以只在本地安装。
$ flatpak-builder --force-clean --install build-dir org.kde.Kblocks.yaml
安装完成后,打开您的 Activities 或应用程序菜单并搜索 Kblocks。

了解更多信息
Flatpak 文档站点 提供了一个很好的构建您的第一个 Flatpak 的演练。即使您已经按照本文的说明进行操作,也值得阅读。此外,该文档还提供了有关哪些平台和 SDK 可用的详细信息。
对于那些喜欢从示例中学习的人来说,Flathub 上提供了每个应用程序的 manifest 文件。
构建和使用 Flatpak 的资源非常丰富,而且 Flatpak,以及容器和沙盒应用程序,可以说是 未来,所以熟悉它们,开始将它们与你的 Jenkins 管道集成,并享受简单而通用的 Linux 应用程序打包。
2 条评论