Compose Multiplatform Desktop JVM support library for building cross-platform desktop applications with declarative UI framework based on Jetpack Compose
—
The desktop application configuration provides a comprehensive DSL for configuring JVM desktop applications, including packaging, distribution, and platform-specific settings.
abstract class DesktopExtension @Inject constructor(
private val objectFactory: ObjectFactory
) : ExtensionAware {
val application: JvmApplication
val nativeApplication: NativeApplication
fun application(fn: Action<JvmApplication>)
fun nativeApplication(fn: Action<NativeApplication>)
}abstract class JvmApplication {
abstract var mainClass: String?
abstract val mainJar: RegularFileProperty
abstract var javaHome: String
abstract val args: MutableList<String>
abstract val jvmArgs: MutableList<String>
abstract val nativeDistributions: JvmApplicationDistributions
abstract val buildTypes: JvmApplicationBuildTypes
abstract fun from(from: SourceSet)
abstract fun from(from: KotlinTarget)
abstract fun disableDefaultConfiguration()
abstract fun dependsOn(vararg tasks: Task)
abstract fun dependsOn(vararg tasks: String)
abstract fun fromFiles(vararg files: Any)
abstract fun args(vararg args: String)
abstract fun jvmArgs(vararg jvmArgs: String)
abstract fun nativeDistributions(fn: Action<JvmApplicationDistributions>)
abstract fun buildTypes(fn: Action<JvmApplicationBuildTypes>)
}compose.desktop {
application {
mainClass = "com.example.MainKt"
args("--debug", "--verbose")
jvmArgs("-Xmx2g", "-Xms512m")
from(sourceSets.main.get())
dependsOn("processResources")
}
}abstract class JvmApplicationDistributions : AbstractDistributions() {
var modules: ArrayList<String>
var includeAllModules: Boolean
var targetFormats: Set<TargetFormat>
val linux: LinuxPlatformSettings
val macOS: JvmMacOSPlatformSettings
val windows: WindowsPlatformSettings
fun modules(vararg modules: String)
fun targetFormats(vararg formats: TargetFormat)
fun linux(fn: Action<LinuxPlatformSettings>)
fun macOS(fn: Action<JvmMacOSPlatformSettings>)
fun windows(fn: Action<WindowsPlatformSettings>)
fun fileAssociation(
mimeType: String,
extension: String,
description: String,
linuxIconFile: File? = null,
windowsIconFile: File? = null,
macOSIconFile: File? = null,
)
}The default JVM modules included in distributions:
internal val DEFAULT_RUNTIME_MODULES = arrayOf(
"java.base",
"java.desktop",
"java.logging",
"jdk.crypto.ec"
)compose.desktop {
application {
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "MyDesktopApp"
packageVersion = "1.0.0"
description = "My awesome desktop application"
copyright = "© 2024 My Company"
vendor = "My Company"
modules("java.base", "java.desktop", "java.logging", "java.sql")
// Or include all modules
includeAllModules = true
// File associations
fileAssociation(
mimeType = "application/myapp-document",
extension = "myapp",
description = "MyApp Document"
)
}
}
}abstract class LinuxPlatformSettings : JvmPlatformSettings() {
abstract var debMaintainer: String
abstract var debDescription: String
abstract var debPreInst: String?
abstract var debPostInst: String?
abstract var debPreRm: String?
abstract var debPostRm: String?
abstract var debCopyright: String?
abstract var debLauncher: String?
abstract var debPackageVersion: String
abstract var menuGroup: String
abstract var rpmLicenseType: String
abstract var rpmPackageVersion: String
abstract var rpmDescription: String
abstract var rpmSummary: String
abstract var rpmPreInst: String?
abstract var rpmPostInst: String?
abstract var rpmPreRm: String?
abstract var rpmPostRm: String?
abstract var appRelease: String
abstract var appCategory: String
abstract var shortcut: Boolean
}Usage example:
compose.desktop {
application {
nativeDistributions {
linux {
packageName = "my-desktop-app"
debMaintainer = "maintainer@example.com"
debDescription = "My awesome desktop application"
debCopyright = "© 2024 My Company"
debPackageVersion = "1.0.0"
menuGroup = "Development"
rpmLicenseType = "MIT"
rpmDescription = "My awesome desktop application"
rpmSummary = "Desktop application built with Compose"
appCategory = "Development"
shortcut = true
fileAssociation(
mimeType = "application/myapp-document",
extension = "myapp",
description = "MyApp Document",
iconFile = File("src/main/resources/linux-icon.png")
)
}
}
}
}abstract class JvmMacOSPlatformSettings : JvmPlatformSettings() {
abstract var bundleID: String
abstract var packageBuildVersion: String
abstract var dmgPackageVersion: String
abstract var dmgPackageBuildVersion: String
abstract var pkgPackageVersion: String
abstract var pkgPackageBuildVersion: String
abstract var dockName: String
abstract var setDockIconPath: String?
abstract var appStore: Boolean
abstract var appCategory: String?
abstract val signing: MacOSSigningSettings
abstract val notarization: MacOSNotarizationSettings
abstract val runtime: MacOSRuntimeSettings
abstract fun signing(fn: Action<MacOSSigningSettings>)
abstract fun notarization(fn: Action<MacOSNotarizationSettings>)
abstract fun runtime(fn: Action<MacOSRuntimeSettings>)
}
abstract class MacOSSigningSettings {
abstract val sign: Property<Boolean>
abstract val identity: Property<String>
abstract val keychain: Property<String>
abstract val prefix: Property<String>
abstract val options: ListProperty<String>
}
abstract class MacOSNotarizationSettings {
abstract val notarize: Property<Boolean>
abstract val appleID: Property<String>
abstract val password: Property<String>
abstract val teamID: Property<String>
abstract val ascProvider: Property<String>
}
abstract class MacOSRuntimeSettings {
abstract val jvmArgs: ListProperty<String>
}Usage example:
compose.desktop {
application {
nativeDistributions {
macOS {
packageName = "MyDesktopApp"
bundleID = "com.example.mydesktopapp"
packageBuildVersion = "1.0.0"
packageVersion = "1.0.0"
dmgPackageVersion = "1.0.0"
dmgPackageBuildVersion = "1.0.0"
dockName = "My App"
appCategory = "public.app-category.productivity"
signing {
sign.set(true)
identity.set("Developer ID Application: My Company")
keychain.set("/path/to/keychain")
}
notarization {
notarize.set(true)
appleID.set("developer@example.com")
password.set("app-specific-password")
teamID.set("TEAM123456")
}
runtime {
jvmArgs.add("-Xmx2g")
jvmArgs.add("-Xms512m")
}
fileAssociation(
mimeType = "application/myapp-document",
extension = "myapp",
description = "MyApp Document",
iconFile = File("src/main/resources/macos-icon.icns")
)
}
}
}
}abstract class WindowsPlatformSettings : JvmPlatformSettings() {
abstract var console: Boolean
abstract var dirChooser: Boolean
abstract var perUserInstall: Boolean
abstract var menuGroup: String
abstract var upgradeUuid: String?
abstract var msiPackageVersion: String
abstract var exePackageVersion: String
abstract var shortcut: Boolean
abstract var menu: Boolean
abstract var installationPath: String?
abstract var appUserModelId: String?
}Usage example:
compose.desktop {
application {
nativeDistributions {
windows {
packageName = "MyDesktopApp"
packageVersion = "1.0.0"
msiPackageVersion = "1.0.0"
exePackageVersion = "1.0.0"
console = false
dirChooser = true
perUserInstall = false
menuGroup = "My Company\\Applications"
shortcut = true
menu = true
installationPath = "C:\\Program Files\\MyApp"
iconFile.set(project.file("src/main/resources/windows-icon.ico"))
upgradeUuid = "unique-upgrade-uuid"
fileAssociation(
mimeType = "application/myapp-document",
extension = "myapp",
description = "MyApp Document",
iconFile = File("src/main/resources/windows-icon.ico")
)
}
}
}
}abstract class JvmApplicationBuildTypes @Inject constructor(
objects: ObjectFactory
) {
val release: JvmApplicationBuildType
fun release(fn: Action<JvmApplicationBuildType>)
}
abstract class JvmApplicationBuildType @Inject constructor(
internal val classifier: String,
objects: ObjectFactory,
) {
val proguard: ProguardSettings
fun proguard(fn: Action<ProguardSettings>)
}compose.desktop {
application {
buildTypes {
release {
proguard {
isEnabled.set(true)
configurationFiles.from("proguard-rules.pro")
optimize.set(true)
obfuscate.set(true)
}
}
}
}
}abstract class NativeApplication {
// Configuration for native (non-JVM) applications
}Configure native applications:
compose.desktop {
nativeApplication {
// Native application configuration
}
}When you configure a desktop application, the plugin automatically creates tasks:
run - Run the applicationcreateDistributable - Create a distributable directorypackageDmg - Create macOS DMG packagepackageMsi - Create Windows MSI installerpackageDeb - Create Linux DEB packagepackageRpm - Create Linux RPM packagepackageUberJarForCurrentOS - Create uber JAR for current OSrunRelease - Run release build (with ProGuard if enabled)createReleaseDistributable - Create release distributablepackageReleaseDmg - Create release DMG packageInstall with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-desktop--desktop-jvm