强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Flatpak 应用打包完整教程 / 第 5 章:Manifest 文件详解

第 5 章:Manifest 文件详解

本章目标:全面理解 Flatpak Manifest 的结构与语法,学会编写完整的应用构建配置。


5.1 Manifest 概述

Manifest(清单文件)是 Flatpak 构建过程的核心配置。它描述了:

  • 应用的基本信息(ID、名称、版本)
  • 使用的运行时和 SDK
  • 所需的权限
  • 构建模块(源代码获取、编译步骤)
  • 扩展点(可选组件)

支持的格式

格式文件扩展名推荐程度说明
JSON.json⭐⭐⭐ 最推荐flatpak-builder 原生支持
YAML.yaml / .yml⭐⭐ 推荐更易读,需 JSON 转换
JSON5.json5⭐ 支持支持注释和尾逗号
# YAML → JSON 转换工具
pip install pyyaml
python -c "
import yaml, json, sys
with open(sys.argv[1]) as f:
    data = yaml.safe_load(f)
print(json.dumps(data, indent=4))
" app.yaml > app.json

5.2 Manifest 基本结构

5.2.1 最小化 Manifest

{
    "app-id": "com.example.HelloWorld",
    "runtime": "org.freedesktop.Platform",
    "runtime-version": "24.08",
    "sdk": "org.freedesktop.Sdk",
    "command": "hello-world",
    "modules": [
        {
            "name": "hello-world",
            "buildsystem": "simple",
            "build-commands": [
                "gcc -o hello-world hello.c -I/usr/include",
                "install -Dm755 hello-world /app/bin/hello-world"
            ],
            "sources": [
                {
                    "type": "file",
                    "url": "https://example.com/hello.c",
                    "sha256": "abc123..."
                }
            ]
        }
    ]
}

5.2.2 完整 Manifest 结构

{
    "app-id": "com.example.MyApp",
    "runtime": "org.gnome.Platform",
    "runtime-version": "47",
    "sdk": "org.gnome.Sdk",
    "sdk-extensions": ["org.freedesktop.Sdk.Extension.rust-stable"],
    "command": "myapp",
    "separate-locales": true,
    "finish-args": [
        "--share=network",
        "--share=ipc",
        "--socket=fallback-x11",
        "--socket=wayland",
        "--socket=pulseaudio",
        "--device=dri",
        "--talk-name=org.freedesktop.Notifications",
        "--filesystem=xdg-download"
    ],
    "build-options": {
        "append-path": "/usr/lib/sdk/rust-stable/bin",
        "env": {
            "CARGO_HOME": "/run/build/myapp/cargo"
        },
        "build-args": ["--share=network"]
    },
    "cleanup": [
        "/include",
        "/lib/pkgconfig",
        "/share/man"
    ],
    "modules": [
        {
            "name": "dependency-a",
            "buildsystem": "cmake-ninja",
            "sources": [
                {
                    "type": "archive",
                    "url": "https://example.com/dep-a-1.0.tar.gz",
                    "sha256": "def456..."
                }
            ]
        },
        {
            "name": "myapp",
            "buildsystem": "meson",
            "config-opts": ["-Dbuildtype=release"],
            "sources": [
                {
                    "type": "git",
                    "url": "https://github.com/example/myapp.git",
                    "tag": "v1.0.0",
                    "commit": "abc123..."
                }
            ],
            "post-install": [
                "install -Dm644 icons/hicolor/256x256/apps/com.example.MyApp.png /app/share/icons/hicolor/256x256/apps/com.example.MyApp.png",
                "install -Dm644 data/com.example.MyApp.desktop /app/share/applications/com.example.MyApp.desktop",
                "install -Dm644 data/com.example.MyApp.metainfo.xml /app/share/metainfo/com.example.MyApp.metainfo.xml"
            ]
        }
    ],
    "cleanup-commands": ["rm -rf /app/share/gtk-doc"],
    "rename-icon": "myapp",
    "rename-desktop-file": "myapp.desktop",
    "rename-appdata-file": "myapp.metainfo.xml"
}

5.3 顶层字段详解

5.3.1 应用标识

字段类型必填说明
app-idstring应用唯一标识,遵循反向域名格式
idstringapp-id 的别名
branchstring默认 stable

应用 ID 规范

# 推荐格式
com.company.AppName          # 商业应用
org.organization.AppName     # 组织/开源项目
io.github.username.AppName   # GitHub 托管项目
net.project.AppName          # 网络项目

# 反面示例(不推荐)
myapp                        # 太简短
com.example.app123           # 包含数字后缀

5.3.2 运行时配置

字段类型说明
runtimestring运行时 ID
runtime-versionstring运行时版本
sdkstringSDK ID
sdk-extensionsstring[]SDK 扩展列表
basestring基础应用(用于应用扩展)
base-versionstring基础应用版本
inherit-extensionsbool是否继承基础应用的扩展

5.3.3 应用元数据

字段类型说明
commandstring启动命令
separate-localesbool分离语言包(默认 true
tagsstring[]应用标签
default-branchstring默认分支名
collection-idstringOSTree 集合 ID

5.4 权限声明 (finish-args)

finish-args 是一个字符串数组,每个元素是一个 Flatpak 权限参数:

{
    "finish-args": [
        "--share=network",
        "--share=ipc",
        "--socket=x11",
        "--socket=wayland",
        "--socket=fallback-x11",
        "--socket=pulseaudio",
        "--socket=ssh-auth",
        "--device=dri",
        "--device=shm",
        "--filesystem=home",
        "--filesystem=xdg-download",
        "--filesystem=~/Projects:create",
        "--filesystem=ro:~/.config",
        "--env=GTK_THEME=Adwaita:dark",
        "--talk-name=org.freedesktop.Notifications",
        "--talk-name=org.kde.StatusNotifierWatcher",
        "--system-talk-name=org.freedesktop.login1",
        "--own-name=com.example.MyApp",
        "--no-talk-name=*"
    ]
}

常见应用类型权限模板

文本编辑器

{
    "finish-args": [
        "--share=ipc",
        "--socket=fallback-x11",
        "--socket=wayland",
        "--filesystem=home",
        "--talk-name=org.freedesktop.Notifications",
        "--talk-name=org.freedesktop.FileManager1"
    ]
}

网络浏览器

{
    "finish-args": [
        "--share=network",
        "--share=ipc",
        "--socket=x11",
        "--socket=wayland",
        "--socket=pulseaudio",
        "--device=dri",
        "--device=all",
        "--filesystem=home",
        "--filesystem=host",
        "--talk-name=org.freedesktop.Notifications",
        "--system-talk-name=org.freedesktop.login1"
    ]
}

媒体播放器

{
    "finish-args": [
        "--share=network",
        "--share=ipc",
        "--socket=fallback-x11",
        "--socket=wayland",
        "--socket=pulseaudio",
        "--device=dri",
        "--filesystem=home",
        "--talk-name=org.freedesktop.Notifications"
    ]
}

5.5 构建选项 (build-options)

5.5.1 环境变量

{
    "build-options": {
        "env": {
            "CFLAGS": "-O2 -g",
            "CXXFLAGS": "-O2 -g",
            "LDFLAGS": "-Wl,--as-needed",
            "PYTHON": "/usr/bin/python3",
            "CARGO_HOME": "/run/build/myapp/cargo"
        }
    }
}

5.5.2 路径配置

{
    "build-options": {
        "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm18/bin",
        "prepend-path": "/app/bin",
        "append-ld-library-path": "/app/lib",
        "append-pkg-config-path": "/app/lib/pkgconfig"
    }
}

5.5.3 构建参数

{
    "build-options": {
        "build-args": ["--share=network", "--filesystem=host"],
        "test-args": ["--no-net"],
        "config-opts": ["-Dprefix=/app", "-Dbuildtype=release"],
        "cflags": "-O2",
        "cxxflags": "-O2",
        "ldflags": "-Wl,--as-needed"
    }
}

5.5.4 架构相关配置

{
    "build-options": {
        "arch": {
            "x86_64": {
                "env": {
                    "CFLAGS": "-march=x86-64-v2"
                }
            },
            "aarch64": {
                "env": {
                    "CFLAGS": "-march=armv8-a"
                }
            }
        }
    }
}

5.6 模块 (Modules)

5.6.1 模块类型

构建系统buildsystem适用项目
MesonmesonGNOME 生态、现代 C/C++ 项目
CMake + Ninjacmake-ninjaCMake 项目
CMake + MakecmakeCMake 项目(回退)
Autotoolsautotools传统 GNU 项目
QMakeqmakeQt 项目
简单脚本simple自定义构建命令
PythonpythonPython 包
PerlperlPerl 模块

5.6.2 源类型

源类型说明关键字段
archivetar.gz/zip 等压缩包url, sha256
gitGit 仓库url, tag/commit/branch
file单个文件url, sha256, dest-filename
dir本地目录path
patch补丁文件pathurl
shellShell 命令commands
extra-data额外数据(运行时下载)url, sha256, size

5.6.3 完整模块示例

{
    "name": "myapp",
    "buildsystem": "meson",
    "config-opts": [
        "-Dbuildtype=release",
        "-Dtests=false",
        "-Ddocs=false"
    ],
    "builddir": true,
    "sources": [
        {
            "type": "git",
            "url": "https://github.com/example/myapp.git",
            "tag": "v1.0.0",
            "commit": "abc123def456789..."
        },
        {
            "type": "patch",
            "path": "patches/fix-build.patch"
        },
        {
            "type": "shell",
            "commands": [
                "sed -i 's|/usr/local|/app|g' meson.build"
            ]
        }
    ],
    "post-install": [
        "install -Dm644 ../data/com.example.MyApp.desktop /app/share/applications/com.example.MyApp.desktop",
        "install -Dm644 ../data/com.example.MyApp.metainfo.xml /app/share/metainfo/com.example.MyApp.metainfo.xml",
        "glib-compile-schemas /app/share/glib-2.0/schemas/"
    ],
    "cleanup": [
        "/include",
        "/lib/pkgconfig",
        "/share/man"
    ]
}

5.6.4 Python 模块示例

{
    "name": "python-requests",
    "buildsystem": "simple",
    "build-commands": [
        "pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} requests"
    ],
    "sources": [
        {
            "type": "file",
            "url": "https://files.pythonhosted.org/packages/.../requests-2.31.0-py3-none-any.whl",
            "sha256": "abc123..."
        },
        {
            "type": "file",
            "url": "https://files.pythonhosted.org/packages/.../urllib3-2.0.7-py3-none-any.whl",
            "sha256": "def456..."
        }
    ]
}

5.6.5 Rust 模块示例

{
    "name": "myapp",
    "buildsystem": "simple",
    "build-commands": [
        "cargo --offline fetch --manifest-path Cargo.toml",
        "cargo --offline build --release",
        "install -Dm755 target/release/myapp /app/bin/myapp"
    ],
    "sources": [
        {
            "type": "git",
            "url": "https://github.com/example/myapp.git",
            "tag": "v1.0.0",
            "commit": "abc123..."
        },
        {
            "type": "shell",
            "commands": [
                "mkdir -p .cargo",
                "cat > .cargo/config.toml << 'TOML'",
                "[net]",
                "offline = true",
                "[source.crates-io]",
                "replace-with = \"vendored-sources\"",
                "[source.vendored-sources]",
                "directory = \"vendor\"",
                "TOML"
            ]
        },
        "cargo-sources.json"
    ]
}

5.7 清理规则 (cleanup)

{
    "cleanup": [
        "/include",
        "/lib/pkgconfig",
        "/lib/cmake",
        "/share/man",
        "/share/doc",
        "/share/gtk-doc",
        "*.a",
        "*.la"
    ],
    "cleanup-commands": [
        "rm -rf /app/share/icons/hicolor/256x256",
        "find /app -name '*.pyc' -delete"
    ],
    "cleanup-platform": [
        "/lib/debug"
    ]
}

5.8 文件重命名

{
    "rename-desktop-file": "org.example.myapp.desktop",
    "rename-appdata-file": "org.example.myapp.metainfo.xml",
    "rename-icon": "myapp-icon"
}

这些选项将自动重命名文件为与 app-id 匹配的名称。


5.9 完整 Manifest 示例

示例 1:简单的 GTK 应用

{
    "app-id": "com.example.TextEditor",
    "runtime": "org.gnome.Platform",
    "runtime-version": "47",
    "sdk": "org.gnome.Sdk",
    "command": "text-editor",
    "finish-args": [
        "--share=ipc",
        "--socket=wayland",
        "--socket=fallback-x11",
        "--filesystem=home",
        "--talk-name=org.freedesktop.Notifications"
    ],
    "cleanup": [
        "/include",
        "/lib/pkgconfig",
        "/share/man"
    ],
    "modules": [
        {
            "name": "text-editor",
            "buildsystem": "meson",
            "sources": [
                {
                    "type": "git",
                    "url": "https://github.com/example/text-editor.git",
                    "tag": "1.0.0",
                    "commit": "abc123..."
                }
            ]
        }
    ]
}

示例 2:Electron 应用

{
    "app-id": "com.example.ElectronApp",
    "runtime": "org.freedesktop.Platform",
    "runtime-version": "24.08",
    "sdk": "org.freedesktop.Sdk",
    "base": "org.electronjs.Electron2.BaseApp",
    "base-version": "24.08",
    "command": "electron-app",
    "separate-locales": false,
    "finish-args": [
        "--share=ipc",
        "--socket=x11",
        "--socket=wayland",
        "--socket=pulseaudio",
        "--share=network",
        "--device=dri",
        "--filesystem=home",
        "--talk-name=org.freedesktop.Notifications"
    ],
    "modules": [
        {
            "name": "electron-app",
            "buildsystem": "simple",
            "build-commands": [
                "cp -r app /app/electron-app",
                "install -Dm755 run.sh /app/bin/electron-app",
                "install -Dm644 com.example.ElectronApp.desktop /app/share/applications/com.example.ElectronApp.desktop",
                "install -Dm644 icon.png /app/share/icons/hicolor/512x512/apps/com.example.ElectronApp.png"
            ],
            "sources": [
                {
                    "type": "archive",
                    "url": "https://github.com/example/electron-app/releases/download/v1.0.0/electron-app-linux-x64.zip",
                    "sha256": "abc123..."
                }
            ]
        }
    ]
}

5.10 业务场景

场景:从零编写 Manifest

假设要打包一个名为 “MyPainter” 的 GTK4 绘图应用:

# 1. 创建项目目录
mkdir -p mypainter-flatpak
cd mypainter-flatpak

# 2. 创建 Manifest
cat > com.example.MyPainter.json << 'JSONEOF'
{
    "app-id": "com.example.MyPainter",
    "runtime": "org.gnome.Platform",
    "runtime-version": "47",
    "sdk": "org.gnome.Sdk",
    "command": "mypainter",
    "finish-args": [
        "--share=ipc",
        "--socket=wayland",
        "--socket=fallback-x11",
        "--filesystem=xdg-pictures",
        "--talk-name=org.freedesktop.Notifications"
    ],
    "modules": [
        {
            "name": "mypainter",
            "buildsystem": "meson",
            "sources": [
                {
                    "type": "git",
                    "url": "https://github.com/example/mypainter.git",
                    "tag": "v1.0.0"
                }
            ]
        }
    ]
}
JSONEOF

# 3. 验证 JSON 语法
python3 -m json.tool com.example.MyPainter.json > /dev/null && echo "JSON 语法正确"

5.11 注意事项

⚠️ SHA256 校验和
所有远程源都必须提供 sha256 校验和。省略校验和会导致构建失败(安全策略)。

⚠️ app-id 不可更改
应用 ID 一旦确定并发布,不可更改。更改 ID 等于发布全新应用,会丢失用户数据。

⚠️ 模块顺序
模块按照数组顺序依次构建。如果模块 B 依赖模块 A,A 必须排在 B 前面。

⚠️ 离线构建
Flathub 要求所有构建都是离线的(不允许构建时联网下载依赖)。所有依赖必须在 sources 中预先声明。


5.12 扩展阅读