diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AbstractDistributions.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AbstractDistributions.kt index e3db8d7d70..3b91115f35 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AbstractDistributions.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AbstractDistributions.kt @@ -5,6 +5,7 @@ package org.jetbrains.compose.desktop.application.dsl +import org.gradle.api.Action import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.ProjectLayout import org.gradle.api.file.RegularFileProperty @@ -36,4 +37,12 @@ abstract class AbstractDistributions { open fun targetFormats(vararg formats: TargetFormat) { targetFormats = EnumSet.copyOf(formats.toList()) } + + internal val additionalLauncherSettings = objects.mapProperty(String::class.java, String::class.java) + + fun additionalLauncher(name: String, fn: Action) { + val settings = AdditionalLauncherArguments() + fn.execute(settings) + additionalLauncherSettings.put(name, settings.getFileContent()) + } } \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AdditionalLauncherArguments.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AdditionalLauncherArguments.kt new file mode 100644 index 0000000000..8be09c60ae --- /dev/null +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/dsl/AdditionalLauncherArguments.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +package org.jetbrains.compose.desktop.application.dsl + +class AdditionalLauncherArguments { + private val options: MutableList = mutableListOf() + + fun add(key: String, value: String) { + if (ValidKeys.contains(key)) { + options.add("$key=$value") + } else { + error("Key \"$key\" is invalid. Valid keys are: ${ValidKeys.joinToString(", ")}") + } + } + + internal fun getFileContent(): String { + return options.joinToString("\n") + } + + companion object { + val ValidKeys = listOf( + "module", "main-jar", "main-class", "description", "arguments", "java-options", "app-version", + "icon", "launcher-as-service", "win-console", "win-shortcut", "win-menu", "linux-app-category", + "linux-shortcut" + ) + } +} \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt index d53ad3dd62..7166da0e74 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt @@ -322,6 +322,7 @@ private fun JvmApplicationContext.configurePackageTask( packageTask.packageVendor.set(packageTask.provider { executables.vendor }) packageTask.packageVersion.set(packageVersionFor(packageTask.targetFormat)) packageTask.licenseFile.set(executables.licenseFile) + packageTask.additionalLaunchers.set(executables.additionalLauncherSettings) } packageTask.destinationDir.set(app.nativeDistributions.outputBaseDir.map { diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt index ad56727c05..dfc3a3c08b 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractJPackageTask.kt @@ -7,6 +7,7 @@ package org.jetbrains.compose.desktop.application.tasks import org.gradle.api.file.* import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* @@ -22,6 +23,7 @@ import org.jetbrains.compose.desktop.application.internal.files.MacJarSignFileCo import org.jetbrains.compose.desktop.application.internal.JvmRuntimeProperties import org.jetbrains.compose.desktop.application.internal.validation.validate import org.jetbrains.compose.internal.utils.* +import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated import java.io.* import java.nio.file.LinkOption import java.util.* @@ -124,6 +126,10 @@ abstract class AbstractJPackageTask @Inject constructor( @get:Optional val packageVersion: Property = objects.nullableProperty() + @get:Input + @get:Optional + val additionalLaunchers: MapProperty = objects.mapProperty(String::class.java, String::class.java) + @get:Input @get:Optional val linuxShortcut: Property = objects.nullableProperty() @@ -273,6 +279,9 @@ abstract class AbstractJPackageTask @Inject constructor( @get:LocalState protected val skikoDir: Provider = project.layout.buildDirectory.dir("compose/tmp/skiko") + @get:LocalState + protected val additionalLaunchersDir: Provider = project.layout.buildDirectory.dir("compose/tmp/launchers") + @get:Internal private val libsDir: Provider = workingDir.map { it.dir("libs") @@ -354,6 +363,12 @@ abstract class AbstractJPackageTask @Inject constructor( cliArg("--app-content", provisioningProfile) } } + + additionalLaunchers.orNull?.forEach { + val fileName = "${name}_${it.key.replace(' ', '_')}.properties" + val file = additionalLaunchersDir.ioFile.resolve(fileName) + cliArg("--add-launcher", "${it.key}=${file.normalizedPath()}") + } } if (targetFormat != TargetFormat.AppImage) { @@ -489,6 +504,15 @@ abstract class AbstractJPackageTask @Inject constructor( } } + fileOperations.clearDirs(additionalLaunchersDir) + additionalLaunchers.orNull?.forEach { + val fileName = "${name}_${it.key.replace(' ', '_')}.properties" + val file = additionalLaunchersDir.ioFile.resolve(fileName).apply { + ensureParentDirsCreated() + writeText(it.value) + } + } + // todo: incremental copy fileOperations.clearDirs(packagedResourcesDir) val destResourcesDir = packagedResourcesDir.ioFile