對於希望將 Compose Multiplatform Desktop 應用部構建發佈的開發者而言,跨平台打包、簽名、更新機制等環節常常是巨大的挑戰。本文將深入探討 Conveyor 這一強大的打包工具,並以我的開源項目 CrossPaste 為例,為您詳細解析其在實際項目中的應用,幫助您輕鬆實現應用的跨平台發佈。
1. 為什麼選擇 Conveyor?
Conveyor 是一個出色的工具,它旨在讓桌面應用的發佈像發佈 Web 應用一樣簡單。對於 Compose Multiplatform 項目來説,選擇 Conveyor 有以下關鍵優勢:
• 官方推薦與緊密集成:Compose Multiplatform 的開源項目 文檔 中直接提及並列舉了 Conveyor 一些列強大功能,這表明它是一個官方推薦的打包工具。Conveyor 特別為 JVM 應用提供了優化,包括捆綁 jlink 優化的 JVM、自定義原生啓動器以及大量針對桌面應用的可用性改進。
• 跨平台打包與自更新:Conveyor 能夠為 Windows、macOS 和 Linux 生成並簽名自更新的軟件包,而且無需您擁有這些操作系統即可完成。它支持平台原生的包格式和更新系統,提供 Chrome 風格的靜默後台更新和 Web 風格的同步啓動更新,以及高級增量更新功能。這意味着您的應用可以自動更新,且無需修改代碼。
• 簡化複雜流程:Conveyor 極大地簡化了代碼簽名、公證、圖標生成等繁瑣過程。它甚至可以從任何操作系統為所有支持的 OS 簽名/公證應用。
• 出色的 CI/CD 支持:您可以在任何 Linux 構建代理上為所有支持的平台直接打包和部署您的應用,而無需 Mac/Windows 工作機。
• 免費與定價模式:Conveyor 對開源應用免費,對商業應用則採用簡單的按項目定價模式。由於 CrossPaste 是一個開源項目,這使其成為一個經濟高效的選擇。
conveyor 的安裝
使用前你必須先安裝 conveyor,https://conveyor.hydraulic.dev/ 它們提供了 macOS、Windows、Linux 多平台安裝包,按照提示安裝完畢後,打開應用將 conveyor 命令添加到環境變量即可
2. CrossPaste 中的實踐案例
CrossPaste 是一個旨在實現跨設備剪貼板通用同步的開源項目。
接下來以 CrossPaste 項目的配置為例子詳細講解 conveyor 如何使用
conveyor.conf
include "#!./gradlew -q printConveyorConfig -PappEnv=PRODUCTION"
include file("extract-native-libraries.conf")
app {
compression-level = high
contact-email = "compile.future@gmail.com"
license = "AGPL-3.0-or-later"
display-name = "CrossPaste"
rdns-name = "com.crosspaste"
url-schemes = [ crosspaste ]
vcs-url = "https://github.com/CrossPaste/crosspaste-desktop"
site {
consistency-checks = warn
}
jvm {
mac.amd64.inputs += "app/jbr/jbrsdk-21.0.7-osx-x64-b968.13.tar.gz"
mac.aarch64.inputs += "app/jbr/jbrsdk-21.0.7-osx-aarch64-b968.13.tar.gz"
windows.amd64.inputs += "app/jbr/jbrsdk-21.0.7-windows-x64-b968.13.tar.gz"
linux.amd64.inputs += "app/jbr/jbrsdk-21.0.7-linux-x64-b968.13.tar.gz"
}
mac {
bundle-extras += "app/script/mac_start.sh" -> "bin/start.sh"
icons = "app/src/desktopMain/composeResources/drawable/crosspaste_mac.png"
info-plist.CFBundleIdentifier = "com.crosspaste.mac"
info-plist.LSMinimumSystemVersion = 13.0.0
info-plist.LSUIElement = true
updates = background
sparkle-options.SUScheduledCheckInterval = 3600
}
windows {
inputs += "app/script/win_start.bat" -> "bin/start.bat"
icons = "app/src/desktopMain/composeResources/drawable/crosspaste.png"
updates = {
launch-check-frequency = 1
block-start = false
automatic-updates = true
}
}
linux {
debian.distribution.name = jammy
install-path = /usr/lib/crosspaste
icons = "app/src/desktopMain/composeResources/drawable/crosspaste.png"
root-inputs += "app/script/linux_start.sh" -> "/usr/lib/crosspaste/bin/start.sh"
}
}
conveyor.compatibility-level = 18
3.1 基礎信息獲取與配置
Conveyor 可以從您的 build.gradle.kts 中獲取基礎信息,避免重複配置。CrossPaste 的配置通過以下方式引入 Gradle 信息:
• include "#!./gradlew -q printConveyorConfig -PappEnv=PRODUCTION":這條命令讓 Conveyor 在構建時執行 Gradle 任務,獲取項目的基本配置信息。
• include file("extract-native-libraries.conf"):這用於處理 Mac 在沙箱內運行應用時,需要提前標記可執行文件的問題,以防止應用被 macOS 禁用。在 extract-native-libraries.conf 中,可以看到 app.jvm.extract-native-libraries = true 的配置,以及針對 jna.nosys 和 skiko.library.path 的系統屬性設置。
3.2 應用通用配置 (app 區塊)
在 conveyor.conf 的 app 區塊中,定義了應用的通用元數據和行為:
• compression-level = high:指定包的壓縮級別。
• contact-email = "compile.future@gmail.com":聯繫郵箱。
• license = "AGPL-3.0-or-later":應用許可證。
• display-name = "CrossPaste":應用顯示名稱。
• rdns-name = "com.crosspaste":反向域名,通常用於唯一標識應用。
• url-schemes = [ crosspaste ]:定義應用支持的 URL scheme。
• vcs-url = "https://github.com/CrossPaste/crosspaste-desktop":版本控制系統 URL,指向 GitHub 倉庫。
• conveyor.compatibility-level = 18:指定 Conveyor 的兼容性級別,實際也就是 conveyor 的大版本號。
3.3 JVM 特定配置
Conveyor 可以捆綁具體的 JDK,來確保應用在不同系統上的運行環境一致性。CrossPaste 選擇使用 JBR (JetBrains Runtime) 作為運行環境,JBR 作為 Jetbrains 一系列 IDE 桌面應用的環境,經過了長期使用驗證,並且官方維護合併了許多桌面環境補丁,相比作為服務器環境的很多開源 JDK 版本,它更適合桌面環境,因此也推薦大家選擇 JBR
通過 jvm.mac.amd64.inputs 等配置指定了不同操作系統和架構的 JBR 路徑:
• mac.amd64.inputs += "app/jbr/jbrsdk-21.0.7-osx-x64-b968.13.tar.gz"
• mac.aarch64.inputs += "app/jbr/jbrsdk-21.0.7-osx-aarch64-b968.13.tar.gz"
• windows.amd64.inputs += "app/jbr/jbrsdk-21.0.7-windows-x64-b968.13.tar.gz"
• linux.amd64.inputs += "app/jbr/jbrsdk-21.0.7-linux-x64-b968.13.tar.gz"
這些 JBR 文件通常是通過 Gradle 腳本(如 CrossPaste 的 build.gradle.kts 中的 getJbrReleases 和 downJbrReleases 函數)下載到本地 jbr 目錄的。
3.4 平台特定配置
Conveyor 允許為每個平台定製詳細的配置,以確保應用能夠完美融入目標操作系統環境。
• macOS (mac 區塊):
bundle-extras += "app/script/mac_start.sh" -> "bin/start.sh":捆綁額外的啓動腳本。icons = "app/src/desktopMain/composeResources/drawable/crosspaste_mac.png":應用圖標路徑。info-plist.CFBundleIdentifier = "com.crosspaste.mac":CFBundleIdentifier,用於唯一標識 Mac 應用。info-plist.LSMinimumSystemVersion = 13.0.0:最低系統版本要求。info-plist.LSUIElement = true:設置為 true 表示應用不在 Dock 中顯示圖標,通常用於後台工具或無界面應用。在build.gradle.kts中,Compose Desktop 也提供了infoPlist區塊來配置這些 Info.plist 條目。updates = background:啓用後台更新。Conveyor 為 macOS 輸出包含 Sparkle 框架的.app包,appcast.rss文件用於廣告更新。sparkle-options.SUScheduledCheckInterval = 3600:設置 Sparkle 檢查更新的頻率(單位秒)。- 公證 (Notarization):Mac 應用的公證配置,這些敏感信息通常通過環境變量傳入。
• Windows (windows 區塊):
inputs += "app/script/win_start.bat" -> "bin/start.bat":捆綁啓動腳本。icons = "app/src/desktopMain/composeResources/drawable/crosspaste.png":應用圖標路徑。-
updates:Windows 的更新配置:launch-check-frequency = 1:啓動時檢查更新頻率。block-start = false:不阻塞啓動。automatic-updates = true:啓用自動更新。
- Conveyor 使用 Windows 內置的 MSIX 打包技術,它支持增量下載、後台自動升級和輕量級容器化,確保應用安裝和卸載的潔淨性。
- Microsoft Store 集成:同樣,商店相關的敏感信息通過環境變量設置。
• Linux (linux 區塊):
debian.distribution.name = jammy:指定 Debian/Ubuntu 的發行版,注意此配置直接影響應用與系統的兼容性,不宜選擇過高。install-path = /usr/lib/crosspaste:應用安裝路徑。icons = "app/src/desktopMain/composeResources/drawable/crosspaste.png":應用圖標路徑。root-inputs += "app/script/linux_start.sh" -> "/usr/lib/crosspaste/bin/start.sh":捆綁啓動腳本並指定其在根文件系統中的安裝路徑。- Conveyor 會為 Debian/Ubuntu 生成
.deb包,並將其放在一個 apt 倉庫中。安裝.deb包會自動安裝倉庫描述文件,從而實現依賴解析和後續更新。
3.5 Gradle 構建腳本中的 Conveyor 整合
CrossPaste 的 build.gradle.kts 文件展示了 Compose Multiplatform 項目如何與 Conveyor 插件協同工作:
• alias(libs.plugins.conveyor):在 plugins 部分聲明 Conveyor Gradle 插件。
• JBR 管理:getJbrReleases 和 downJbrReleases 函數負責從 jbr.yaml 文件中讀取 JBR 的下載 URL 和 SHA512 校驗和,並下載 JBR 包到指定目錄。這些 JBR 文件隨後被 Conveyor 捆綁到最終的應用包中。
• JVM 參數 (jvmArgs):在 nativeDistributions 配置中,可以為所有平台添加 JVM 啓動參數,例如 --add-opens 用於模塊開放,以及設置系統屬性如 loggerLevel、appEnv、java.net.preferIPv4Stack 等。
• 平台特定構建邏輯:
- macOS Swift 編譯:CrossPaste 在
build.gradle.kts中定義了compileSwift任務,用於編譯MacosApi.swift生成libMacosApi.dylib,這個動態庫對於實現原生 macOS API 交互至關重要。desktopJar和desktopTest任務都依賴於此編譯步驟。 targetFormats(TargetFormat.Dmg):macOS 目標格式設置為 DMG。targetFormats(TargetFormat.Msi):Windows 目標格式設置為 MSI。targetFormats(TargetFormat.Deb):Linux 目標格式設置為 Deb。
4. 運行與構建 Conveyor 任務
Conveyor 是一個構建系統,它通過配置和任務來生成最終的應用包和下載站點。
• 生成打包後的應用目錄/Bundle 並執行:
conveyor run- 加速運行 (跳過簽名):
conveyor -Kapp.sign = false run
• 將應用目錄輸出到 output 文件夾:
conveyor make app
• 為所有可用平台構建下載站點:
conveyor make site- 生成的下載站點包含各種元數據文件、軟件包和一個簡單的 HTML 下載頁面,所有文件都必須上傳以確保更新和增量生成正常工作。
5. 增量更新:優化用户體驗
Conveyor 的核心優勢之一是其增量更新功能。當 Conveyor 打包的應用在 Windows 和 macOS 上更新時,它們不會從頭下載整個應用,而是僅下載已安裝版本與最新版本之間的差異。這大大節省了帶寬和更新時間。
• Windows:MSIX 包會自動進行增量更新。即使用户已經安裝了其他通過 Microsoft Store 或 Conveyor 構建的應用,新應用的首次安裝也可以複用這些已安裝應用的文件或數據塊,從而顯著提升首次運行時間和降低下載放棄率。
• macOS:Conveyor 會自動生成增量補丁文件(*.delta 文件),並作為站點文件的一部分。這些文件支持 Sparkle 框架進行增量更新。
• Linux:通過 Debian/Ubuntu 的 apt 倉庫機制,用户可以通過 apt-get update; apt-get upgrade 命令無縫更新應用。
6. 結語
Conveyor 為 Compose Multiplatform Desktop 應用提供了一站式的打包、分發和更新解決方案,極大地簡化了桌面應用開發的複雜性。通過 CrossPaste 這樣一個真實世界的開源項目,您可以更直觀地理解 Conveyor 的強大功能和靈活配置。
如果您正在尋求構建和打包 Compose Multiplatform Desktop 應用的解決方案,強烈建議您嘗試 Conveyor。
🔥 助力 CrossPaste 項目!
如果您覺得 CrossPaste 這個項目對您有幫助,或者您對跨平台剪貼板同步工具感興趣,請訪問 【CrossPaste 的 GitHub 倉庫併為它點亮一顆 Star!您的支持是我們持續開發和維護的最大動力。
👉 CrossPaste GitHub 倉庫
此外,CrossPaste 致力於提供無縫的跨設備體驗,目前已推出適用於 Android 設備的付費應用。雖然本文的資料主要側重於桌面應用打包,但 CrossPaste 的願景是實現所有設備間的剪貼板無縫同步。如果您希望在您的 Android 設備上體驗更便捷的剪貼板功能,請前往應用 Google Play CrossPaste 瞭解並下載。