Compose Multiplatform 桌面分发打包工具对比:内置 jlink/jpackage 任务与第三方方案的深度剖析
Compose Multiplatform 桌面分发打包工具对比内置 jlink/jpackage 任务与第三方方案的深度剖析【免费下载链接】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本文基于仓库中 packaging-tools-comparison.md 教程展开对照 Compose Multiplatform Gradle 插件的源码实现讲清桌面应用分发链路中两条路线的边界一是插件内置的jlink/jpackage打包任务能覆盖哪些基本需求、受哪些 JDK 与平台限制二是第三方工具 Conveyor 在自动更新、跨平台构建等场景下提供了哪些增量能力帮助你在发布 Compose Desktop 应用时做出有依据的工具选型。一、内置 Gradle 打包任务覆盖基本分发需求Compose Multiplatform 的 Compose Gradle 插件源码位于 gradle-plugins/compose 目录把桌面应用的打包构建直接挂到了 Gradle 任务体系上。官方教程 packaging-tools-comparison.md 对内置能力的概括是三点为 Windows 生成 MSI 文件或 NSIS 安装器 EXE为 macOS 生成签名的应用 bundle为 Linux 生成 DEB/RPM 包使用jlink捆绑 JVM在每个操作系统上自定义打包选项。下面结合源码逐项拆解这些能力在插件中的真实落地方式。1.1 支持的打包格式与任务命名所有可打包格式定义在 TargetFormat.kt 的枚举中每个格式都绑定了目标操作系统这直接决定了“格式与构建机 OS 必须匹配”的约束枚举值格式 ID目标 OS产物AppImageapp-image构建机当前 OS目录形态的应用镜像无文件扩展名DebdebLinuxDEB 包RpmrpmLinuxRPM 包DmgdmgmacOSDMG 镜像PkgpkgmacOSPKG 安装器ExeexeWindowsNSIS 安装器 EXEMsimsiWindowsMSI 安装器枚举中的isCompatibleWithCurrentOS属性按currentOS targetOS判定兼容性。任务名遵循 JvmTasks.kt 中注释声明的[动作][构建类型][对象]模式例如runDistributable、runReleaseDistributable、packageDmg、packageReleaseDmg——即在package前缀后拼上构建类型如Release与格式名。1.2 用 jlink 捆绑 JVMjlink环节由 AbstractJLinkTask.kt 实现它从 JDK 安装目录调用jlink工具组装出一个只含应用所需模块的精简 runtime。从源码看其命令行参数的拼装逻辑makeArgs方法如下--add-modules每个模块单独追加一次。模块集合来自两处——若includeAllModules为 true则从JvmRuntimeProperties由前置的 JDK 探测任务生成中读取该 JDK 的全部可用模块否则使用用户在 distributions DSL 中显式声明的modules列表--strip-debug、--no-header-files、--no-man-pages、--strip-native-commands这四项默认均为true即默认剥离调试信息、头文件、man 页面和本地命令以减小 runtime 体积--compress对应可选的compressionLevel取值定义见 RuntimeCompressionLevel.kt用于在输出时压缩 runtime 中的 jar/class 文件--generate-cds-archive可选地生成 JRE CDS 归档以加速启动源码中明确校验了它与--strip-native-commands互斥二者同时开启会直接抛错--output指向任务的输出目录。该任务标注了DisableCachingByDefault原因注释写明它依赖平台特定的 JDK 工具输出取决于本机的 JDK 安装情况因此默认不参与跨构建缓存。1.3 jpackage 的调用细节安装器以及 app image由 AbstractJPackageTask.kt 调用jpackage生成。从源码的makeArgs方法可以看到完整的参数组织方式应用镜像相关参数创建 app image、或不带--app-image的安装器时传入--input指向插件预先准备好的libs工作目录--runtime-image指向 jlink 产物--main-jar/--main-class指定启动入口--arguments透传应用启动参数javaOption透传 JVM 参数两个对 Compose 渲染至关重要的系统属性-Dskiko.library.path$APPDIR告知 Skiko 原生库位置以及应用资源目录属性。安装器相关参数由已有 app image 生成安装器时传入--app-image、--install-dir对应 DSL 中的installationPath、--license-file--file-associations源码会把 DSL 里fileAssociation(mimeType, extension, description, iconFile)声明的每种文件关联写成形如FAext.properties的临时文件内容为mime-type/extension/description/icon四个键值再逐一传给 jpackage。这一机制在 AbstractPlatformSettings 中定义三个平台的设置基类都继承自它。平台分支参数按currentOS分别追加这也是“任务与构建机 OS 绑定”的直接证据Linux--linux-shortcut、--linux-package-name、--linux-app-release、--linux-app-category、--linux-deb-maintainer、--linux-menu-group、--linux-rpm-license-typeWindows--win-dir-chooser、--win-per-user-install、--win-shortcut、--win-menu、--win-menu-group、--win-upgrade-uuidmacOS--mac-package-name、--mac-package-identifierbundleID、--mac-app-store、--mac-app-category、--mac-entitlements以及签名相关的--mac-sign、--mac-signing-key-user-name、--mac-signing-keychain、--mac-package-signing-prefix。所有格式统一的公共参数包括--type 格式id、--dest、--name、--icon、--description、--copyright、--app-version、--vendor。此外源码还处理了两个工程细节一是多模块项目中 jar 简单名冲突问题mangleJarFilesNames默认为 true会给拷贝进 libs 目录的 jar 名追加内容哈希避免:data:utils与:ui:utils这类同名片段互相覆盖二是 Skiko 原生库的特殊处理——打包前会扫描并解出 Skiko AWT runtime jar 内的目标平台原生条目stripAndUnpackSkikoNatives把无关平台的.so/.dll/.dylib剔除减小安装体积。1.4 各平台的 DSL 配置项各平台的可配置项定义在 PlatformSettings.kt与 jpackage 参数一一对应全部通过jvmApplication { nativeDistributions { ... } }下的windows { ... }、linux { ... }、macos { ... }块配置入口见 JvmApplication.kt 中声明的nativeDistributions属性。三平台共有iconFile、packageVersion、installationPath、fileAssociation(...)。WindowsWindowsPlatformSettingsconsole默认 false是否显示控制台窗口dirChooser默认 true安装时是否允许选择目录perUserInstall默认 false按用户安装而非按机器安装shortcut默认 false/menu默认 false设置menuGroup后自动置真/menuGroup桌面快捷方式与开始菜单项upgradeUuidMSI 升级识别 UUIDmsiPackageVersion/exePackageVersion分别为 MSI 与 EXE 指定包版本。LinuxLinuxPlatformSettingsshortcut默认 false、packageName、appRelease、appCategory、debMaintainer、menuGroup、rpmLicenseType、debPackageVersion、rpmPackageVersion。macOSJvmMacOSPlatformSettings除继承自AbstractMacOSPlatformSettings的packageName、packageBuildVersion、dmgPackageVersion、dmgPackageBuildVersion、appCategory、minimumSystemVersion、bundleID推荐反向 DNS 风格如com.mycompany.myapp只允许字母数字、连字符与点外JVM 应用还有dockName、setDockNameSameAsPackageName、appStore、entitlementsFile/runtimeEntitlementsFile、pkgPackageVersion/pkgPackageBuildVersion、provisioningProfile/runtimeProvisioningProfile以及infoPlist { extraKeysRawXml }用于向自动生成的 Info.plist 注入额外 XML 键。1.5 Windows 平台的前置依赖WiX Toolsetjpackage 生成 MSI 依赖 WiX Toolset。插件对这一依赖做了自动化处理逻辑在 wixToolset.kt 中若设置了WIX_PATH环境变量并指向有效目录则直接使用本地的 WiX 安装否则注册downloadWix/unzipWix任务自动下载 WiX 3.11 的二进制发行包并解压到构建目录Windows 打包任务会自动依赖它若设置 Gradle 属性compose.desktop.application.downloadWixfalse则跳过自动下载此时需自行准备 WiX 环境。1.6 JDK 要求与运行环境校验打包前的 JDK 校验由 AbstractCheckNativeDistributionRuntime.kt 完成关键约束有三条最低版本MIN_JAVA_RUNTIME_VERSION 17构建 JDK 主版本低于 17 会直接报“minimum required JDK version is 17”错误工具完整性校验 JDK 的bin目录下同时存在java、jlink、jpackage三个可执行文件缺失即报“Failed to check JDK distribution”发行商检查在 macOS 上若探测到 Homebrew 的 JDK会因已知的打包问题而报错建议改用其他发行商的 JDK如 Amazon Corretto或在gradle.properties中加compose.desktop.application.checkJdkVendorfalse自担风险继续。该任务同时会运行java --list-modules收集全部模块名并写入JvmRuntimeProperties供后续includeAllModules的 jlink 任务读取。1.7 macOS 签名与公证macOS 平台的签名/公证通过 DSL 暴露signing { sign, identity, keychain, prefix }定义见 MacOSSigningSettings.kt默认值可被compose.desktop.application.macSign*等 Gradle 属性覆盖以及notarization { ... }。从 AbstractJPackageTask 的macSigner逻辑可以看出行为边界仅当构建机是 macOS 时才会创建签名器启用sign时使用配置了证书身份的MacSignerImpl否则使用NoCertificateSigner无证书签名打包完成后modifyRuntimeOnMacOsIfNeeded会对 app image 内的 runtime 逐个重签所有可执行文件与 dylib再签 runtime 与整个.app并把 provisioning profile 写入Contents/runtime/Contents/embedded.provisionprofile生成安装器时签名信息会翻译为--mac-sign等 jpackage 参数让安装器内容在生成阶段就带签名。1.8 为什么内置任务无法跨平台构建教程中提到“内置任务必须从每个目标 OS 上运行”这一点在源码中得到印证AbstractJPackageTask.makeArgs中的平台参数全部由currentOS分支决定Linux/Windows/macOS 各一组WiX 配置函数开头就有check(currentOS OS.Windows)非 Windows 环境直接报错macOS 签名器在非 macOS 环境下恒为null。也就是说插件的任务体系把“格式—构建机 OS”强绑定在了一起在 macOS 上跑打包只会产出 macOS 格式在 Windows 上只产出 Windows 格式。若要同时分发多平台就得为每个目标平台各准备一台构建机或 CI runner这正是第三方方案切入的痛点。二、第三方方案Conveyor 提供的增量能力packaging-tools-comparison.md 介绍的第二条路线是 Hydraulic 公司的Conveyor工具。它与 Compose Gradle 插件集成针对内置任务覆盖不到的场景提供了一组能力教程原文列出的九项如下在线更新Online updates插件生成的包需要用户手动重装来更新Conveyor 生成的包在 Windows/macOS 上可以后台静默自更新在 Linux 上则走 apt 等系统包管理通道跨构建Cross-building从任意 OS开发笔记本或 CI 机器为所有支持的目标生成、签名、公证包而内置任务必须逐平台各开一台构建机自签名包Self-signed packages不需要购买签名证书但代价是用户安装时要复制/粘贴终端命令下载页Download pages生成静态 HTML自动探测用户的操作系统与 CPU 架构并给出对应下载项图标转换Icon conversion内置任务要求开发者手工把图标转成各平台格式如 Windows 的.ico、macOS 的.icnsConveyor 代劳这一步体积优化Size optimization使用jdeps剔除未使用的 JDK 模块以缩小下载体积内置 jlink 方案通过模块列表实现类似目标jdeps 是从依赖分析角度补强可访问性Accessibility通过 Java Accessibility Bridge 自动加入屏幕阅读器支持对企业 IT 部门友好Windows 侧采用 MSIX——微软 Windows 10/11 的当代打包系统与 Windows 网络管理工具深度集成CLI 支持包内可附带附属命令行工具。教程还特别提示以上并非完整功能清单且 Licensing 模型为开源项目免费商业项目度过引入期后需要购买许可证。选型时应以其官方文档与定价页为准确认最新功能与费用条款。三、如何选型内置任务 vs Conveyor结合教程与源码证据可以把两条路线的适用边界归纳如下优先使用内置 Gradle 任务当你的场景满足只需基础分发产物MSI/EXE、签名 app bundle、DEB/RPM且接受“每个目标平台各备一台构建机”本地或 CI 均可需要精细控制打包参数jlink 的压缩级别与 CDS 归档、jpackage 的各平台安装器选项、fileAssociation文件关联、Info.plist 注入infoPlist { extraKeysRawXml }等插件 DSL 已完整暴露PlatformSettings.kt希望零外部商业依赖构建链路完全由 JDK 17 的jlink/jpackage与插件任务组成。考虑引入 Conveyor当你的产品形态需要静默在线更新能力或面向 Linux 的 apt 分发通道单一构建环境如一台 CI 机器产出全部平台、签名与公证产物不想维护签名证书自签名路线或需要开箱即用的下载页、图标转换、MSIX 打包需要附带 CLI 工具或企业级 Windows 部署MSIX 网络管理工具集成。需要注意的是无论选择哪条路线JVM 捆绑、图标、版本号、安装路径这些基础输入都是共通的——内置任务把这些暴露为 DSL 属性与 jpackage 参数Conveyor 则以工具自身的工作流承接。两者并非互斥替代关系Conveyor 同样以“与 Compose Gradle 插件集成”的方式工作。四、小结与延伸阅读本文以 tutorials/Native_distributions_and_local_execution/packaging-tools-comparison.md 为主线对照 Compose Multiplatform 仓库源码核实了内置打包链路的关键实现格式与 OS 绑定关系见 TargetFormat.kt任务命名规则见 JvmTasks.ktjlink参数组装见 AbstractJLinkTask.ktjpackage参数组装、Skiko 原生库瘦身、macOS 重签逻辑见 AbstractJPackageTask.ktWindows WiX 自动下载见 wixToolset.ktJDK 17 与jlink/jpackage工具校验、Homebrew JDK 告警见 AbstractCheckNativeDistributionRuntime.kt三平台 DSL 配置项含 macOS 签名/公证入口见 PlatformSettings.kt 与 MacOSSigningSettings.kt。掌握上述内容后你可以先跑通内置的package构建类型格式任务完成基础分发再依据是否涉及自动更新、跨平台 CI 与 MSIX 等企业需求评估是否引入 Conveyor 补齐能力短板。【免费下载链接】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),仅供参考