如何构建 Flatpak

一种具有去中心化分发方式的通用打包格式。此外,还具备可移植性和沙盒功能。
136 位读者喜欢这篇文章。

很久以前,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 本身支持其他构建系统,例如 cmakecmake-ninjamesonant,以及自定义命令(在 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 的产品,所以没有必要。 如果您正在构建的代码不容易构建,那么您可能需要安装 autogenautoconf 来为 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,其中包括常见的库,包括 freedesktopgnomekde。 基本要求是 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 是任意的;您可以将其称为 buildbldpenguin,并且您可以在同一个项目目录中拥有多个构建目标。 但是,术语 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。

The Activities menu in GNOME

了解更多信息

Flatpak 文档站点 提供了一个很好的构建您的第一个 Flatpak 的演练。即使您已经按照本文的说明进行操作,也值得阅读。此外,该文档还提供了有关哪些平台和 SDK 可用的详细信息。

对于那些喜欢从示例中学习的人来说,Flathub 上提供了每个应用程序的 manifest 文件。

构建和使用 Flatpak 的资源非常丰富,而且 Flatpak,以及容器和沙盒应用程序,可以说是 未来,所以熟悉它们,开始将它们与你的 Jenkins 管道集成,并享受简单而通用的 Linux 应用程序打包。

标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。 他曾在电影和计算机行业工作,而且经常同时从事这两个行业。

2 条评论

感谢你的这篇文章!你真的简化了它,并帮助人们快速上手和构建!谢谢!

谢谢!这是很棒的东西!它确实会让人们更容易开始使用 Flatpak。在得到像这样的良好指导之前,它可能会让人感觉非常抽象。

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.