Skip to content

原生發行版本

在這裡,你將了解原生發行版本:如何為所有支援的系統建立安裝程式和軟件包,以及如何以與發行版本相同的設定在本機執行應用程式。

請繼續閱讀以下主題的詳細資訊:

Gradle plugin

本指南主要關注於使用 Compose Multiplatform Gradle 外掛程式來封裝 Compose 應用程式。org.jetbrains.compose 外掛程式提供了用於基本封裝、混淆和 macOS 程式碼簽名的任務。

該外掛程式簡化了使用 jpackage 將應用程式封裝為原生發行版本並在本機執行應用程式的過程。可發行的應用程式是自包含且可安裝的二進位檔案,其中包含了所有必要的 Java 執行階段元件,不需要在目標系統上安裝 JDK。

為了最小化軟件包大小,Gradle 外掛程式使用 jlink 工具,以確保在可發行軟件包中僅綑綁必要的 Java 模組。但是,你仍必須配置 Gradle 外掛程式以指定所需的模組。如需詳細資訊,請參閱 包含 JDK 模組部分。

作為另一種選擇,你可以使用 Conveyor,這是一個非 JetBrains 開發的外部工具。Conveyor 支援線上更新、跨平台編譯以及各種其他功能,但對於非開源專案需要授權。如需詳細資訊,請參閱 Conveyor 文件

Basic tasks

Compose Multiplatform Gradle 外掛程式中的基本可配置單元是 application(請勿與已棄用的 Gradle application 外掛程式混淆)。

application DSL 方法為一組最終二進位檔案定義了共享配置,這意味著它允許你將檔案集合與 JDK 發行版本一起封裝成各種格式的壓縮二進位安裝程式。

以下格式可用於支援的作業系統:

  • macOS.dmg (TargetFormat.Dmg)、.pkg (TargetFormat.Pkg)
  • Windows.exe (TargetFormat.Exe)、.msi (TargetFormat.Msi)
  • Linux.deb (TargetFormat.Deb)、.rpm (TargetFormat.Rpm)

以下是具有基本桌面組態的 build.gradle.kts 檔案範例:

kotlin
import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
    kotlin("jvm")
    id("org.jetbrains.compose")
}

dependencies {
    implementation(compose.desktop.currentOs)
}

compose.desktop {
    application {
        mainClass = "example.MainKt"

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Exe)
        }
    }
}

當你組建專案時,外掛程式會建立以下任務:

Gradle 任務描述
package<FormatName>將應用程式封裝為對應的 FormatName 二進位檔案。目前不支援跨平台編譯,這意味著你只能使用對應的相容作業系統來組建特定格式。例如,要組建 .dmg 二進位檔案,你必須在 macOS 上執行 packageDmg 任務。如果有任何任務與當前作業系統不相容,它們預設會被跳過。
packageDistributionForCurrentOS聚合應用程式的所有封裝任務。這是一個生命週期任務
packageUberJarForCurrentOS建立一個包含當前作業系統所有相依性的單一 jar 檔案。該任務預期將 compose.desktop.currentOS 作為 compileimplementationruntime 相依性使用。
run在本機從 mainClass 中指定的入口點執行應用程式。run 任務會啟動一個具有完整執行階段且未封裝的 JVM 應用程式。與建立具有縮減執行階段的精簡二進位映像檔相比,此方法更快且更易於偵錯。若要執行最終的二進位映像檔,請改用 runDistributable 任務。
createDistributable建立最終的應用程式映像檔而不建立安裝程式。
runDistributable執行預先封裝的應用程式映像檔。

所有可用的任務都列在 Gradle 工具視窗中。執行任務後,Gradle 會在 ${project.buildDir}/compose/binaries 目錄中產生輸出二進位檔案。

Including JDK modules

為了減小可發行版本的大小,Gradle 外掛程式使用 jlink,這有助於僅綑綁必要的 JDK 模組。

目前 Gradle 外掛程式不會自動確定必要的 JDK 模組。雖然這不會導致編譯問題,但未能提供必要的模組可能會導致在執行時出現 ClassNotFoundException

如果在執行封裝後的應用程式或 runDistributable 任務時遇到 ClassNotFoundException,你可以使用 modules DSL 方法包含額外的 JDK 模組:

kotlin
compose.desktop {
    application {
        nativeDistributions {
            modules("java.sql")
            // 或者:includeAllModules = true
        }
    }
}

你可以手動指定所需的模組,或執行 suggestModulessuggestModules 任務使用 jdeps 靜態分析工具來確定可能缺失的模組。請注意,該工具的輸出可能不完整或列出不必要的模組。

如果可發行版本的大小不是關鍵因素且可以忽略,你可以選擇使用 includeAllModules DSL 屬性來包含所有執行階段模組。

Specifying distribution properties

Package version

原生發行軟件包必須具有特定的軟件包版本。若要指定軟件包版本,你可以使用以下 DSL 屬性,按優先級從高到低排列:

  • nativeDistributions.<os>.<packageFormat>PackageVersion 為單一軟件包格式指定版本。
  • nativeDistributions.<os>.packageVersion 為單一目標作業系統指定版本。
  • nativeDistributions.packageVersion 為所有軟件包指定版本。

在 macOS 上,你還可以使用以下 DSL 屬性指定組建版本,同樣按優先級從高到低排列:

  • nativeDistributions.macOS.<packageFormat>PackageBuildVersion 為單一軟件包格式指定組建版本。
  • nativeDistributions.macOS.packageBuildVersion 為所有 macOS 軟件包指定組建版本。

如果你不指定組建版本,Gradle 將使用軟件包版本。如需了解有關 macOS 版本控制的更多資訊,請參閱 CFBundleShortVersionStringCFBundleVersion 文件。

以下是按優先級順序指定軟件包版本的範本:

kotlin
compose.desktop {
    application {
        nativeDistributions {
            // 所有軟件包的版本
            packageVersion = "..." 
          
            macOS {
              // 所有 macOS 軟件包的版本
              packageVersion = "..."
              // 僅限 dmg 軟件包的版本
              dmgPackageVersion = "..." 
              // 僅限 pkg 軟件包的版本
              pkgPackageVersion = "..." 
              
              // 所有 macOS 軟件包的組建版本
              packageBuildVersion = "..."
              // 僅限 dmg 軟件包的組建版本
              dmgPackageBuildVersion = "..." 
              // 僅限 pkg 軟件包的組建版本
              pkgPackageBuildVersion = "..." 
            }
            windows {
              // 所有 Windows 軟件包的版本
              packageVersion = "..."  
              // 僅限 msi 軟件包的版本
              msiPackageVersion = "..."
              // 僅限 exe 軟件包的版本
              exePackageVersion = "..." 
            }
            linux {
              // 所有 Linux 軟件包的版本
              packageVersion = "..."
              // 僅限 deb 軟件包的版本
              debPackageVersion = "..."
              // 僅限 rpm 軟件包的版本
              rpmPackageVersion = "..."
            }
        }
    }
}

要定義軟件包版本,請遵循以下規則:

檔案類型版本格式詳細資訊
dmg, pkgMAJOR[.MINOR][.PATCH]
  • MAJOR 為非負整數
  • MINOR 為選用的非負整數
  • PATCH 為選用的非負整數
msi, exeMAJOR.MINOR.BUILD
  • MAJOR 是最大值為 255 的非負整數
  • MINOR 是最大值為 255 的非負整數
  • BUILD 是最大值為 65535 的非負整數
deb[EPOCH:]UPSTREAM_VERSION[-DEBIAN_REVISION]
  • EPOCH 為選用的非負整數
  • UPSTREAM_VERSION:
    • 只能包含英數字和 ., +, -, ~ 字元
    • 必須以數字開頭
  • DEBIAN_REVISION:
    • 選用項目
    • 只能包含英數字和 ., +, ~ 字元
如需更多詳細資訊,請參閱 Debian 文件
rpm任何格式版本不得包含 -(連字號)字元。

JDK version

該外掛程式使用 jpackage,其要求的 JDK 版本不得低於 JDK 17。指定 JDK 版本時,請確保符合以下至少一項要求:

  • JAVA_HOME 環境變數指向相容的 JDK 版本。

  • 透過 DSL 設定 javaHome 屬性:

    kotlin
    compose.desktop {
        application {
            javaHome = System.getenv("JDK_17")
        }
    }

Output directory

若要為原生發行版本使用自訂輸出目錄,請配置 outputBaseDir 屬性,如下所示:

kotlin
compose.desktop {
    application {
        nativeDistributions {
            outputBaseDir.set(project.layout.buildDirectory.dir("customOutputDir"))
        }
    }
}

Launcher properties

若要調整應用程式啟動流程,你可以自訂以下屬性:

屬性描述
mainClass包含 main 方法的類別完全限定名稱。
args應用程式 main 方法的引數。
jvmArgs應用程式 JVM 的引數。

以下是配置範例:

kotlin
compose.desktop {
    application {
        mainClass = "MainKt"
        args += listOf("-customArgument")
        jvmArgs += listOf("-Xmx2G")
    }
}

Metadata

nativeDistributions DSL 區塊中,你可以配置以下屬性:

屬性描述預設值
packageName應用程式名稱。Gradle 專案的 名稱 (name)
packageVersion應用程式版本。Gradle 專案的 版本 (version)
description應用程式描述。
copyright應用程式的版權資訊。
vendor應用程式廠商。
licenseFile應用程式的授權檔案。

以下是配置範例:

kotlin
compose.desktop {
    application {
        nativeDistributions {
            packageName = "ExampleApp"
            packageVersion = "0.1-SNAPSHOT"
            description = "Compose Multiplatform App"
            copyright = "© 2024 My Name. All rights reserved."
            vendor = "Example vendor"
            licenseFile.set(project.file("LICENSE.txt"))
        }
    }
}

Managing resources

若要封裝並載入資源,你可以使用 Compose Multiplatform 資源程式庫、JVM 資源載入,或將檔案加入封裝後的應用程式。

Resources library

為專案設置資源最直接的方法是使用資源程式庫。透過資源程式庫,你可以在所有支援平台的共通程式碼中存取資源。有關詳細資訊,請參閱多平台資源

JVM resource loading

用於桌面的 Compose Multiplatform 在 JVM 平台上運作,這意味著你可以使用 java.lang.Class API 從 .jar 檔案中載入資源。你可以透過 Class::getResourceClass::getResourceAsStream 存取 src/main/resources 目錄中的檔案。

Adding files to packaged application

在某些情況下,從 .jar 檔案載入資源可能不太切合實際,例如當你擁有特定平台的資產,且只需要在 macOS 軟件包中包含檔案,而不需要在 Windows 中包含時。

在這些情況下,你可以配置 Gradle 外掛程式以在安裝目錄中包含額外的資源檔案。使用 DSL 指定資源根目錄,如下所示:

kotlin
compose.desktop {
    application {
        mainClass = "MainKt"
        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageVersion = "1.0.0"

            appResourcesRootDir.set(project.layout.projectDirectory.dir("resources"))
        }
    }
}

在上面的範例中,資源根目錄被定義為 <PROJECT_DIR>/resources

Gradle 外掛程式將按以下方式包含來自資源子目錄的檔案:

  1. 通用資源: 位於 <RESOURCES_ROOT_DIR>/common 中的檔案將包含在所有軟件包中,無論目標作業系統或架構為何。

  2. 作業系統特定資源: 位於 <RESOURCES_ROOT_DIR>/<OS_NAME> 中的檔案將僅包含在為特定作業系統組建的軟件包中。<OS_NAME> 的有效值為:windowsmacoslinux

  3. 作業系統與架構特定資源: 位於 <RESOURCES_ROOT_DIR>/<OS_NAME>-<ARCH_NAME> 中的檔案將僅包含在為作業系統和 CPU 架構特定組合組建的軟件包中。<ARCH_NAME> 的有效值為:x64arm64。例如,<RESOURCES_ROOT_DIR>/macos-arm64 中的檔案將僅包含在專為 Apple 晶片 Mac 設計的軟件包中。

你可以使用 compose.application.resources.dir 系統屬性存取包含的資源:

kotlin
import java.io.File

val resourcesDir = File(System.getProperty("compose.application.resources.dir"))

fun main() {
    println(resourcesDir.resolve("resource.txt").readText())
}

Custom source sets

如果你使用 org.jetbrains.kotlin.jvmorg.jetbrains.kotlin.multiplatform 外掛程式,則可以依賴預設組態:

  • 使用 org.jetbrains.kotlin.jvm 的配置包含來自 main 原始碼集的內容。
  • 使用 org.jetbrains.kotlin.multiplatform 的配置包含來自單一 JVM 目標的內容。如果你定義了多個 JVM 目標,預設配置將被停用。在這種情況下,你需要手動配置外掛程式,或指定單一目標(見下文)。

如果預設配置不明確或不足,你可以透過多種方式進行自訂:

使用 Gradle 原始碼集

plugins {
    kotlin("jvm")
    id("org.jetbrains.compose")
}
val customSourceSet = sourceSets.create("customSourceSet")
compose.desktop {
    application {
        from(customSourceSet)
    }
}

使用 Kotlin JVM 目標

plugins {
    kotlin("multiplatform")
    id("org.jetbrains.compose")
} 
kotlin {
    jvm("customJvmTarget") {}
}
compose.desktop {
    application {
        from(kotlin.targets["customJvmTarget"])
    }
}

手動配置:

  • 使用 disableDefaultConfiguration 停用預設設定。
  • 使用 fromFiles 指定要包含的檔案。
  • 指定 mainJar 檔案屬性以指向包含主類別的 .jar 檔案。
  • 使用 dependsOn 將任務相依性加入所有外掛程式任務。
compose.desktop {
    application {
        disableDefaultConfiguration()
        fromFiles(project.fileTree("libs/") { include("**/*.jar") })
        mainJar.set(project.file("main.jar"))
        dependsOn("mainJarTask")
    }
}

Application icon

請確保你的應用程式圖示具有以下作業系統特定的格式:

  • macOS 使用 .icns
  • Windows 使用 .ico
  • Linux 使用 .png
kotlin
compose.desktop {
    application {
        nativeDistributions {
            macOS {
                iconFile.set(project.file("icon.icns"))
            }
            windows {
                iconFile.set(project.file("icon.ico"))
            }
            linux {
                iconFile.set(project.file("icon.png"))
            }
        }
    }
}

Platform-specific options

特定平台設定可以使用對應的 DSL 區塊進行配置:

compose.desktop {
    application {
        nativeDistributions {
            macOS {
                // macOS 選項
            }
            windows {
                // Windows 選項
            }
            linux {
                // Linux 選項
            }
        }
    }
}

下表描述了所有受支援的特定平台選項。不建議使用未記錄的屬性。

平台選項描述
所有平台iconFile.set(File("PATH_TO_ICON"))指定應用程式特定平台圖示的路徑。詳情請參閱應用程式圖示部分。
packageVersion = "1.0.0"設定特定平台的軟件包版本。詳情請參閱軟件包版本部分。
installationPath = "PATH_TO_INST_DIR"指定預設安裝目錄的絕對路徑或相對路徑。在 Windows 上,你還可以使用 dirChooser = true 以在安裝期間啟用路徑自訂。
LinuxpackageName = "custom-package-name"覆寫預設應用程式名稱。
debMaintainer = "[email protected]"指定軟件包維護者的電子郵件。
menuGroup = "my-example-menu-group"為應用程式定義選單群組。
appRelease = "1"為 rpm 軟件包設定發佈 (release) 值,或為 deb 軟件包設定修訂 (revision) 值。
appCategory = "CATEGORY"為 rpm 軟件包分配群組值,或為 deb 軟件包分配區段值。
rpmLicenseType = "TYPE_OF_LICENSE"指示 rpm 軟件包的授權類型。
debPackageVersion = "DEB_VERSION"設定 deb 特定的軟件包版本。詳情請參閱軟件包版本部分。
rpmPackageVersion = "RPM_VERSION"設定 rpm 特定的軟件包版本。詳情請參閱軟件包版本部分。
macOSbundleID 指定唯一的應用程式識別碼,只能包含英數字元 (A-Z, a-z, 0-9)、連字號 (-) 和句點 (.)。建議使用反向 DNS 表示法 (com.mycompany.myapp)。
packageName應用程式名稱。
dockName 應用程式在選單列、「關於 <App>」選單項目和 Dock 中顯示的名稱。預設值為 packageName
minimumSystemVersion 執行應用程式所需的最基本 macOS 版本。詳情請參閱 LSMinimumSystemVersion
signing, notarization, provisioningProfile, runtimeProvisioningProfile 請參閱 macOS 發行版本的簽名與公證教學。
appStore = true指定是否為 Apple App Store 組建並簽名應用程式。至少需要 JDK 17。
appCategory Apple App Store 的應用程式類別。為 App Store 組建時,預設值為 public.app-category.utilities,否則為 Unknown。有關有效類別的清單,請參閱 LSApplicationCategoryType
entitlementsFile.set(File("PATH_ENT")) 指定簽名時使用的權利 (entitlements) 檔案路徑。提供自訂檔案時,請確保添加 Java 應用程式所需的權利。有關為 App Store 組建時使用的預設檔案,請參閱 sandbox.plist。請注意,此預設檔案可能因 JDK 版本而異。如果未指定檔案,外掛程式將使用 jpackage 提供的預設權利。詳情請參閱 macOS 發行版本的簽名與公證教學。
runtimeEntitlementsFile.set(File("PATH_R_ENT")) 指定簽名 JVM 執行階段時使用的權利檔案路徑。提供自訂檔案時,請確保添加 Java 應用程式所需的權利。有關為 App Store 組建時使用的預設檔案,請參閱 sandbox.plist。請注意,此預設檔案可能因 JDK 版本而異。如果未指定檔案,外掛程式將使用 jpackage 提供的預設權利。詳情請參閱 macOS 發行版本的簽名與公證教學。
dmgPackageVersion = "DMG_VERSION" 設定 DMG 特定的軟件包版本。詳情請參閱軟件包版本部分。
pkgPackageVersion = "PKG_VERSION" 設定 PKG 特定的軟件包版本。詳情請參閱軟件包版本部分。
packageBuildVersion = "DMG_VERSION" 設定軟件包組建版本。詳情請參閱軟件包版本部分。
dmgPackageBuildVersion = "DMG_VERSION" 設定 DMG 特定的軟件包組建版本。詳情請參閱軟件包版本部分。
pkgPackageBuildVersion = "PKG_VERSION" 設定 PKG 特定的軟件包組建版本。詳情請參閱軟件包版本部分。
infoPlist請參閱 macOS 上的 Info.plist部分。
Windowsconsole = true為應用程式添加主控台啟動器。
dirChooser = true允許在安裝期間自訂安裝路徑。
perUserInstall = true允許按使用者 (per-user) 安裝應用程式。
menuGroup = "start-menu-group"將應用程式加入指定的「開始」功能表群組。
upgradeUuid = "UUID"指定一個唯一的 ID,當版本高於已安裝版本時,允許使用者透過安裝程式更新應用程式。單一應用程式的此值必須保持不變。詳情請參閱 How To: Generate a GUID
msiPackageVersion = "MSI_VERSION"設定 MSI 特定的軟件包版本。詳情請參閱軟件包版本部分。
exePackageVersion = "EXE_VERSION"設定 EXE 特定的軟件包版本。詳情請參閱軟件包版本部分。

macOS-specific configuration

Signing and notarization on macOS

現代 macOS 版本不允許使用者執行從網際網路下載的未簽名應用程式。如果你嘗試執行此類應用程式,將會遇到以下錯誤:「YourApp 已損壞,無法開啟。你應該退出磁碟映像檔」。

若要了解如何簽名並公證你的應用程式,請參閱我們的教學

Information property list on macOS

雖然 DSL 支援基本的特定平台自訂,但仍可能存在超出所提供功能的情況。如果你需要指定 DSL 中未表示的 Info.plist 值,可以包含一段原始 XML 作為暫時解決方法。此 XML 將被附加到應用程式的 Info.plist 中。

Example: Deep linking

  1. build.gradle.kts 檔案中定義自訂 URL 配置 (scheme):
compose.desktop {
    application {
        mainClass = "MainKt"
        nativeDistributions {
            targetFormats(TargetFormat.Dmg)
            packageName = "Deep Linking Example App"
            macOS {
                bundleID = "org.jetbrains.compose.examples.deeplinking"
                infoPlist {
                    extraKeysRawXml = macExtraPlistKeys
                }
            }
        }
    }
}

val macExtraPlistKeys: String
    get() = """
      <key>CFBundleURLTypes</key>
      <array>
        <dict>
          <key>CFBundleURLName</key>
          <string>Example deep link</string>
          <key>CFBundleURLSchemes</key>
          <array>
            <string>compose</string>
          </array>
        </dict>
      </array>
    """
  1. src/main/main.kt 檔案中使用 java.awt.Desktop 類別設置 URI 處理常式:
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.window.singleWindowApplication
import java.awt.Desktop

fun main() {
    var text by mutableStateOf("Hello, World!")

    try {
        Desktop.getDesktop().setOpenURIHandler { event ->
            text = "Open URI: " + event.uri
        }
    } catch (e: UnsupportedOperationException) {
        println("setOpenURIHandler is unsupported")
    }

    singleWindowApplication {
        MaterialTheme {
            Text(text)
        }
    }
}
  1. 執行 runDistributable 任務:./gradlew runDistributable

結果,像 compose://foo/bar 這樣的連結現在可以從瀏覽器重新導向到你的應用程式。

Minification and obfuscation

Compose Multiplatform Gradle 外掛程式包含對 ProGuard 的內建支援。ProGuard 是一套用於程式碼縮減與混淆的開源工具

對於每個 預設 封裝任務(不含 ProGuard),Gradle 外掛程式都提供了一個 發佈 (release) 任務(含 ProGuard):

Gradle 任務描述

預設:createDistributable

發佈:createReleaseDistributable

建立一個綑綁了 JDK 和資源的應用程式映像檔。

預設:runDistributable

發佈:runReleaseDistributable

執行一個綑綁了 JDK 和資源的應用程式映像檔。

預設:run

發佈:runRelease

使用 Gradle JDK 執行未封裝的應用程式 .jar

預設:package<FORMAT_NAME>

發佈:packageRelease<FORMAT_NAME>

將應用程式映像檔封裝到 <FORMAT_NAME> 檔案中。

預設:packageDistributionForCurrentOS

發佈:packageReleaseDistributionForCurrentOS

將應用程式映像檔封裝成與當前作業系統相容的格式。

預設:packageUberJarForCurrentOS

發佈:packageReleaseUberJarForCurrentOS

將應用程式映像檔封裝到 Uber (fat) `.jar` 中。

預設:notarize<FORMAT_NAME>

發佈:notarizeRelease<FORMAT_NAME>

上傳 <FORMAT_NAME> 應用程式映像檔以進行公證(僅限 macOS)。

預設:checkNotarizationStatus

發佈:checkReleaseNotarizationStatus

檢查公證是否成功(僅限 macOS)。

預設配置會啟用一些預先定義的 ProGuard 規則:

  • 應用程式映像檔會被縮減,這意味著未使用的類別將被移除。
  • compose.desktop.application.mainClass 被用作入口點。
  • 包含多條 keep 規則以確保 Compose 執行階段保持功能正常。

在大多數情況下,你不需要任何額外的配置即可獲得縮減後的應用程式。然而,ProGuard 可能無法追蹤位元組碼中的某些用法,例如,當一個類別透過反射使用時。如果你遇到僅在 ProGuard 處理後才發生的問題,你可能需要添加自訂規則。

若要指定自訂組態檔案,請使用 DSL,如下所示:

kotlin
compose.desktop {
    application {
        buildTypes.release.proguard {
            configurationFiles.from(project.file("compose-desktop.pro"))
        }
    }
}

有關 ProGuard 規則和配置選項的更多資訊,請參閱 Guardsquare 手冊

混淆功能預設是停用的。若要啟用,請透過 Gradle DSL 設定以下屬性:

kotlin
compose.desktop {
    application {
        buildTypes.release.proguard {
            obfuscate.set(true)
        }
    }
}

ProGuard 的優化功能預設是啟用的。若要停用,請透過 Gradle DSL 設定以下屬性:

kotlin
compose.desktop {
    application {
        buildTypes.release.proguard {
            optimize.set(false)
        }
    }
}

產生 Uber JAR 預設是停用的,ProGuard 會為每個輸入的 .jar 產生一個對應的 .jar 檔案。若要啟用,請透過 Gradle DSL 設定以下屬性:

kotlin
compose.desktop {
    application {
        buildTypes.release.proguard {
            joinOutputJars.set(true)
        }
    }
}

What's next?

探索關於桌面組件的教學。