Compose Multiplatform 发布流程实战指南:从 Skia/Skiko 升级到 Maven 发布与 Docker 镜像构建
2026/9/13 19:02:12 网站建设 项目流程

Compose Multiplatform 发布流程实战指南:从 Skia/Skiko 升级到 Maven 发布与 Docker 镜像构建

【免费下载链接】compose-multiplatformCompose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.项目地址: https://gitcode.com/GitHub_Trending/co/compose-multiplatform

导读

本文以 Compose Multiplatform 仓库中的 ci/release.md 为骨架,完整讲解该项目的端到端发布流水线:从更新底层 Skia 渲染库、发布 Skiko(Skia 的 Kotlin 绑定层)、把新版本 Skiko 引入 Compose,到最终发布 Compose Desktop 组件与构建 CI 所用的 Docker 镜像。读完本文,你将掌握每一环节的操作步骤、关键配置参数(如dependencies.skia.windows/dependencies.skia.linuxSKIKO_VERSION)、验证命令(如./gradlew publishToMavenLocal)以及背后涉及的仓库源码与脚本佐证,可直接用于参与或复现 Compose Multiplatform 的发布过程。

发布链路全景:Compose Multiplatform 的三层依赖体系

Compose Multiplatform(CMP)的桌面渲染栈是一条典型的"自底向上"依赖链:Skia(C++ 图形库)→ Skija/Skiko(Skia 的 Kotlin/JVM 绑定)→ Compose Multiplatform(UI 框架)

  • Skia:Google 开源的 2D 图形引擎,负责所有实际的绘制、文本排版与光栅化工作。Compose 桌面端在渲染时并不直接调用 Skia,而是经由其绑定层间接使用。
  • Skija/Skiko:JetBrains 维护的 Skia 绑定项目。Skija 侧重 JVM 侧原生绑定,Skiko 则是 Compose Multiplatform 真正依赖的渲染层(提供SkiaLayerSurfacePictureRecorder等 API)。
  • Compose Multiplatform:本文所在的仓库本体,通过 Maven 坐标引用特定版本的 Skiko,从而获得跨 JVM/原生/Web 的渲染能力。

因此,每次发布新版 Compose 之前,通常都要先完成一次"渲染层升级",这也是 ci/release.md 中四大部分(更新 Skia、发布 Skiko、在 Compose 中更新 Skiko、发布 Compose Desktop)按顺序串成一条流水线的原因。此外,发布环节还依赖 TeamCity CI 上的发布配置(JetBrains 公共项目下 Compose/Skiko 相关的PublishRelease构建配置)以及内部 Docker 镜像,文中相应小节会一并说明。

第一步:更新 Skia(Skija 子模块升级)

Skia 的版本更新发生在Skija 仓库中,而不是 Compose Multiplatform 仓库本身。发布流程的第一步是在 Skija 中推进third_party/skia子模块:

  1. 升级子模块:在 skija 仓库中更新third_party/skia子模块指向的提交。

  2. 验证构建:运行<skija_root>/script/build.sh,确认 Skija 构建没有被破坏。这一步是硬性门禁——只有本地三平台构建通过,才允许进入后续发布环节。

  3. 同步分支与版本变量:如果使用的 Skia 分支发生变化(例如从chrome/m85切换到chrome/m86),需要同步更新三个平台构建脚本中的VER变量:

    • script/build_skia_linux.sh
    • script/build_skia_windows.sh
    • script/build_skia_macos.sh

    VER变量直接决定 CI 拉取哪个 Skia 发行包,分支切换而版本号未更新会导致拉取到错误产物。

  4. 部署到 Bintray:在 TeamCity 的JetBrainsPublicProjects_Compose_Skia_PublishRelease构建配置中点击Deploy(或点击 "..." 自定义发布选项)把 Skia 产物发布出去。

  5. 固定构建:发布完成后在 TeamCity 上Pin该次构建,以保留其产物不被清理策略回收,保证后续 Skiko 构建能够稳定引用。

  6. 在 Skiko 中同步版本:更新skiko仓库skiko/gradle.properties中的以下参数:

    • dependencies.skija.git.commit—— Skija(即 Skia 绑定)的 Git 提交;
    • dependencies.skia.windows—— Windows 平台的 Skia 包版本;
    • dependencies.skia.linux—— Linux 平台的 Skia 包版本;
    • dependencies.skia.macos—— macOS 平台的 Skia 包版本(release.md 原文中该行笔误重复写为windows,按构建脚本与平台划分,第三个应为 macOS 对应的版本参数)。

    验证方式:在<skiko_root>/skiko目录执行./gradlew publishToMavenLocal,把 Skiko 发布到本地 Maven 仓库,确保基于新 Skia 的 Skiko 可以正常构建并被本地方案引用。

  7. 跨平台复查:仅在本机验证往往不够(例如本地是 Linux,无法覆盖 Windows/macOS)。可在 TeamCity 的JetBrainsPublicProjects_Compose_Skiko_BuildCheckManualTrigger构建配置中发起一次全平台构建检查:

    • 点击 "...";
    • 方式一:在Changes标签页选择要验证的分支或提交;
    • 方式二:在General标签页勾选 "run as a personal build" 上传自定义 patch,即可在提交正式代码前用补丁跑一遍全平台构建。

第二步:发布 Skiko

Skiko 是 Compose 依赖链上真正对外发布的一环,发布前必须先确认一切就绪:

  1. 发布就绪检查
    • 与团队成员确认所有必要变更均已合入并发布;
    • 确定本次发布对应的 Git 提交(branch/commit);
    • 验证 sample 项目可正常运行,例如:
      cd skiko && ./gradlew publishToMavenLocal && cd samples/SkijaInjectSample && ./gradlew run
    • 由于个人通常无法覆盖全部平台,跨平台验证可以请对应平台的同事协助测试。
  2. 执行发布:在 TeamCity 的JetBrainsPublicProjects_Compose_Skiko_PublishRelease构建配置中点击Deploy,并设置发布参数:
    • Parameters标签页把 "Skiko Release Version" 设置为新的发布版本号(例如0.1.6);
    • Changes标签页选择要发布的分支/提交;
    • 小技巧:如果时间紧张,可在General标签页勾选 "put the build to the queue top",把该构建插入到构建队列最前面,优先执行。
  3. 确认产物:在 Skiko 的 GitHub Releases 页面检查新版本是否已正确发布。

值得注意的是,发布产物最终落到 JetBrains 的 Space Maven 仓库(https://packages.jetbrains.team/maven/p/ui/dev这类 dev 仓库),这是后续"在 Compose 中更新 Skiko"环节能够拉取到新版本的前提。

第三步:在 Compose 中更新 Skiko

新版本 Skiko 发布后,需要把它引入 Compose Multiplatform 的构建依赖。这一步通过 AOSP(Android Open Source Project)的importMavenArtifacts工具完成——Compose 的 Maven 依赖以 prebuilt 形式保存在 AOSP 的prebuilts/androidx/external仓库中:

  1. 使用<androidx-dev-master>/frameworks/support/development/importMaven/import_maven_artifacts.py脚本下载 Maven 产物:
    # 如果本地 build.gradle.kts 的 repository 段还没有该仓库,需要先添加 # maven("https://packages.jetbrains.team/maven/p/ui/dev") export SKIKO_VERSION="0.1.6" import_maven_artifacts.py --name "org.jetbrains.skiko:skiko-jvm:$SKIKO_VERSION" import_maven_artifacts.py --name "org.jetbrains.skiko:skiko-jvm-runtime-linux:$SKIKO_VERSION" import_maven_artifacts.py --name "org.jetbrains.skiko:skiko-jvm-runtime-windows:$SKIKO_VERSION" import_maven_artifacts.py --name "org.jetbrains.skiko:skiko-jvm-runtime-macos:$SKIKO_VERSION"

    这里需要同时导入skiko-jvm本体与三个平台的 runtime 构件(linux/windows/macos)。它们各自携带对应平台的原生库,是桌面端跨平台运行的基础。

  2. 将变更提交到<androidx-dev-master>/prebuilts/androidx/external仓库,并上传 CL(change list)等待合入。

仓库内的自动化佐证:skikoAospCommit 脚本

仓库的 compose/scripts/skikoAospCommit 脚本把上述"导入 + 提交"过程完全自动化,可作为理解该环节内部细节的参考:

  • 它要求通过环境变量AOSP_COMPOSE_SOURCE指定 AOSP 源码根目录,并把 Skiko 版本作为命令行参数传入(如./updateSkikoInAosp 0.4.15);
  • 脚本会在prebuilts/androidx/externalframeworks/support两个仓库中基于aosp/androidx-main各创建skiko<版本>分支;
  • 通过sed更新frameworks/support/gradle/libs.versions.toml中的skiko = "..."版本号;
  • 随后删除旧的org/jetbrains/skikoprebuilt 目录,并用 Gradle 的 importMaven 任务一次导入完整的 Skiko 构件清单,包括skikoskiko-awt以及 linux/macos/windows 的 x64/arm64 runtime:
    org.jetbrains.skiko:skiko:$SKIKO_VERSION,\ org.jetbrains.skiko:skiko-awt:$SKIKO_VERSION,\ org.jetbrains.skiko:skiko-awt-runtime-linux-x64:$SKIKO_VERSION,\ org.jetbrains.skiko:skiko-awt-runtime-linux-arm64:$SKIKO_VERSION,\ org.jetbrains.skiko:skiko-awt-runtime-macos-x64:$SKIKO_VERSION,\ org.jetbrains.skiko:skiko-awt-runtime-macos-arm64:$SKIKO_VERSION,\ org.jetbrains.skiko:skiko-awt-runtime-windows-x64:$SKIKO_VERSION
  • 最后分别在两个仓库中git commitframeworks/support的提交信息为 "Update Skiko to $SKIKO_VERSION",并附上验证命令./gradlew jvmTest desktopTest -Pandroidx.compose.multiplatformEnabled=true)。

这与 release.md 手写流程一一对应,可作为发布时参考的完整实现。注意该脚本会写 AOSP 侧仓库,仅供维护者使用;本文仅作原理讲解。

第四步:发布 Compose Desktop

当 Compose 侧已经切换到新版本 Skiko、所有测试通过后,即可发布 Compose Desktop 组件本身:

  • 在 TeamCity 的JetBrainsPublicProjects_Skija_JetpackComposeMpp_Dev(即 Compose 构建配置)中启动一次新构建。

这一构建会产出 Compose Multiplatform 桌面端的所有 artifacts,并发布到 JetBrains 的 Maven 仓库。后续开发者只需在build.gradle.kts中声明对应版本号即可使用。

本地验证与发布辅助工具

仓库中还提供了与发布相关的本地工具链,可用于发布前的验证:

  • 本地发布验证:与 Skiko 一样,Compose 自身也可以通过publishToMavenLocal在本地验证。仓库提供了封装脚本 compose/scripts/publishComponentsToMavenLocal,其核心命令为:
    ./gradlew publishToMavenLocal -Pcompose.version="$COMPOSE_CUSTOM_VERSION" -Pcompose.useMavenLocal=true

    通过-Pcompose.version指定自定义版本号、-Pcompose.useMavenLocal=true让依赖解析优先使用本地仓库,即可在完全离线的本地环境验证组件可发布性。

  • 发布辅助库:ci/build-helpers/README.md 说明存在一个专门帮助 CMP 项目及其依赖向 Maven Central 发布 artifacts 的辅助库,例如对 Skiko 执行./gradlew publish即可发布;它会在 CMP 源码发生变更时由 CI 任务自动发布到https://packages.jetbrains.team/maven/p/cmp/dev。本地使用时既可以./gradlew publishToMavenLocal发布到本地,也可以直接从源码以参数化方式执行:
    ./gradlew -p=cli reuploadArtifactsToMavenCentral -Pmaven.central.sign=true \ -Pmaven.central.coordinates=org.jetbrains.compose*:*:%version.COMPOSE%,org.jetbrains.compose.material:material-navigation*:%version.COMPOSE_MATERIAL_NAVIGATION% \ -Pmaven.central.stage=org.jetbrains.compose \ -Pmaven.central.description="Compose %version.COMPOSE% and associated libs" \ -Pmaven.central.staging.close.after.upload=true

发布后的清理:从 Space 仓库删除旧包

发布过程中,JetBrains 的 Space Maven 仓库会积累大量历史版本(尤其是各种-preview-*快照)。仓库提供了专门的清理工具 ci/delete-packages-from-space/README.md,其流程如下:

  1. 环境要求:JDK 9+;
  2. 生成个人 token:在 Space 中创建带ReadRepositoryWriteRepositoryViewProject权限的 token;
  3. 创建配置cp template.local.properties local.properties,然后设置space.server.urlspace.auth.token
  4. 查询 ID:运行./gradlew listProjectsAndPackageRepositories找出space.project.idspace.repo.id并填入配置;
  5. 生成删除清单:运行./gradlew generateListOfPackagesToDelete -Pspace.package.version=0.4.0-preview-*,按版本通配符生成待删包列表(写入build/packages-to-delete.txt);
  6. 人工确认:取消注释要删除的包,再运行./gradlew deletePackages执行删除。

第五步:构建与维护 Docker 镜像

CI 构建离不开容器环境。release.md 中 Docker 镜像部分明确了两类操作:

本地构建

  • Linux 镜像的本地构建说明见 docker/linux/README.md 对应的文档(release.md 原文指向docker/linux/README.mddocker/windows/README.md;当前仓库中可确认存在 Linux 测试镜像的 Dockerfile);
  • Windows 镜像说明对应仓库中的docker/windows/README.md(历史路径,当前仓库已不再包含该目录,说明 Windows 镜像构建已从本仓库移除)。

更新内部镜像

当需要更新 JetBrains 内部 Docker registry 上的镜像时,在对应 TeamCity 构建配置中发起构建:

  • Linux:JetBrainsPublicProjects_Compose_Docker_Linux
  • Windows:JetBrainsPublicProjects_Compose_Docker_Windows

镜像内容参考:Linux 测试镜像 Dockerfile

ci/docker/linux-tests/Dockerfile 展示了 CMP CI 测试环境的完整依赖栈,可以帮助理解"为什么 CI 需要这些基础环境":

  • 基础系统ubuntu:24.04,安装binutilscurlfakerootlibgl-devmavenpython3unzipwgetxvfb(虚拟 X server,无头环境跑 GUI 测试必需)、gitxz-utils等;
  • JDK:OpenJDK 21(openjdk-${JAVA_VERSION}-jdk),并设置JAVA_HOME
  • Node.js:Node 22(供 Web/JS 目标与前端工具链使用);
  • UTF-8 环境LANG=en_US.UTF-8JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8,避免跨平台构建出现编码问题;
  • JetBrains Runtime(JBR):安装jbr_jcef发行版(内含 JCEF,用于 Compose 桌面端嵌入 Chromium 的 WebView 场景);
  • Android SDK:通过 commandline-tools 安装android-37.0平台;
  • 浏览器与驱动:安装固定版本的 Google Chrome + ChromeDriver 与 Firefox + GeckoDriver(供 Web 目标的端到端/UI 测试使用)。

这套镜像内容与 release.md 中"构建 Docker 镜像"的环节互相印证:CI 上的 Compose 构建需要同时覆盖 JVM 桌面、Android 与 Web 目标,因此镜像必须提前备齐 JDK、Android SDK、浏览器驱动与虚拟显示环境。

发布链路中的源码佐证:Skiko 渲染 API 在 Compose 中的使用

release.md 反复强调"更新 Skia/Skiko 后必须验证构建与渲染没有回归"。那么 Skiko 的 API 到底在 Compose 中扮演什么角色?以基准测试模块为例,benchmarks/multiplatform/benchmarks/src/skikoMain/kotlin/MeasureComposable.skiko.kt 直接展示了 Compose 与 Skiko/Skia 的交互方式:

  • 代码直接 importorg.jetbrains.skia.Surfaceorg.jetbrains.skia.Colororg.jetbrains.skia.PictureRecorderorg.jetbrains.skia.Rect,说明 Compose 的 Skiko 目标在渲染层直接对接 Skia 对象;
  • GraphicsContext接口要求实现类提供surface(width, height): Surface(创建 Skia Surface)与awaitGPUCompletion()(等待 GPU 完成,用于 GPU 时间测量);
  • mimicSkikoRender方法按 SkiaLayer 的渲染逻辑模拟一帧渲染:用PictureRecorder录制 Compose 场景绘制命令为Picture,清空画布后drawPicture到 Surface,再flushAndSubmit提交给 GPU——其注释还说明,如果跳过中间 Picture 录制,基准测试结果可能产生 ±10% 的偏差;
  • 文件顶部注释明确该方法复刻自 Skiko 的SkiaLayer.awt.kt渲染逻辑,并提示"如果新版 Skiko 不再使用 picture,这里也需要同步删除"。

这段代码生动地说明:Skia/Skiko 的任何一个渲染行为变化(Surface 语义、Picture 录制、GPU 提交方式)都会直接影响 Compose 的渲染正确性与性能,因此 release.md 中"升级 Skia → 重建 Skiko → 全平台验证"的门禁流程绝非可有可无。

总结:一次完整发布需要执行的关键动作清单

阶段核心动作关键参数/命令验证手段
更新 Skia升级 skija 的third_party/skia子模块VER(三个平台构建脚本)script/build.sh
发布 SkiaTeamCity PublishRelease 配置点 Deploy,并 Pin 构建保留产物可被后续引用
同步 Skiko 依赖更新skiko/gradle.propertiesdependencies.skija.git.commitdependencies.skia.windows/linux/macos./gradlew publishToMavenLocal+ BuildCheck 全平台构建
发布 SkikoTeamCity PublishRelease 点 Deploy"Skiko Release Version" 设置为新版本号sample 项目./gradlew run
Compose 引入新 Skikoimport_maven_artifacts.py导入 artifacts 并提交 prebuiltsSKIKO_VERSION(如0.1.6可参考 skikoAospCommit 自动化脚本
发布 Compose DesktopTeamCity Compose 配置发起新构建本地可用 publishComponentsToMavenLocal 预验证
清理旧包(可选)Space 仓库删除历史版本space.package.version通配符见 delete-packages-from-space
Docker 镜像本地构建或 TeamCity 更新内部镜像Linux/Windows 对应配置见 linux-tests/Dockerfile

整体来看,Compose Multiplatform 的发布是一条"渲染层先行、平台全量验证、CI 统一发布"的严谨流水线:任何一层的版本推进都必须以构建与渲染回归验证为前置条件。对想要参与 Compose 生态贡献、或者在自己的项目中维护基于 Skia/Skiko 渲染栈的开发者而言,理解这条链路,就等于掌握了整个桌面 UI 生态最关键的一根"升级主动脉"。

【免费下载链接】compose-multiplatformCompose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.项目地址: https://gitcode.com/GitHub_Trending/co/compose-multiplatform

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询