From 724e0eaaffb2d585614d5e794bb768effcbf7a07 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 13 Sep 2025 19:51:51 +0800 Subject: [PATCH 1/6] Patch and test `binaries.executable` --- .../plugins/shadow/KotlinPluginsTest.kt | 32 +++++++++++++++++++ .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 25 +++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt index ad41a3b9d..9baa2997b 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt @@ -268,6 +268,38 @@ class KotlinPluginsTest : BasePluginTest() { ) } + @Test + fun compatKmpApplicationDsl() { + writeClass(sourceSet = "jvmMain", withImports = true, jvmLang = JvmLang.Kotlin) + projectScript.appendText( + """ + kotlin { + jvm { + binaries { + executable { + it.mainClass.set('my.Main') + } + } + } + sourceSets { + jvmMain { + dependencies { + implementation 'junit:junit:3.8.2' + } + } + } + } + """.trimIndent(), + ) + + val result = run(runShadowPath) + + assertThat(result.output).contains( + "Hello, World! (foo) from Main", + "Refs: junit.framework.Test", + ) + } + private fun compileOnlyStdlib(exclude: Boolean): String { return if (exclude) { // Disable the stdlib dependency added via `implementation`. diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index 6f2e16030..a0208459e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -1,10 +1,14 @@ package com.github.jengelman.gradle.plugins.shadow +import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.SHADOW_RUN_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.internal.isAtLeastKgpVersion import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.registerShadowJarCommon +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.plugins.ApplicationPlugin +import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.bundling.Jar import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension @@ -23,6 +27,7 @@ public abstract class ShadowKmpPlugin : Plugin { } configureShadowJar(target) + addRunTask(target) } } @@ -44,4 +49,24 @@ public abstract class ShadowKmpPlugin : Plugin { } } } + + private fun Project.addRunTask(target: KotlinJvmTarget) { + if (!isAtLeastKgpVersion(2, 1, 20)) return + + tasks.register(SHADOW_RUN_TASK_NAME, JavaExec::class.java) { task -> + task.description = "Runs this project as a JVM application using the shadow jar" + task.group = ApplicationPlugin.APPLICATION_GROUP + + task.classpath = files(tasks.shadowJar) + + @OptIn(ExperimentalKotlinGradlePluginApi::class) + target.binaries { + executable { dsl -> + task.mainModule.set(dsl.mainModule) + task.mainClass.set(dsl.mainClass) + task.jvmArguments.convention(dsl.applicationDefaultJvmArgs) + } + } + } + } } From 91a63a2aa857d355ea9f65498b79512e6bad8137 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 13 Sep 2025 20:59:45 +0800 Subject: [PATCH 2/6] Try to get `binariesDsl` via reflection --- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index a0208459e..56f9d8f5b 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -5,6 +5,8 @@ import com.github.jengelman.gradle.plugins.shadow.internal.isAtLeastKgpVersion import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.registerShadowJarCommon import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar +import kotlin.reflect.full.memberProperties +import kotlin.reflect.jvm.isAccessible import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.ApplicationPlugin @@ -12,6 +14,7 @@ import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.bundling.Jar import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmBinariesDsl import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget public abstract class ShadowKmpPlugin : Plugin { @@ -59,13 +62,15 @@ public abstract class ShadowKmpPlugin : Plugin { task.classpath = files(tasks.shadowJar) - @OptIn(ExperimentalKotlinGradlePluginApi::class) - target.binaries { - executable { dsl -> - task.mainModule.set(dsl.mainModule) - task.mainClass.set(dsl.mainClass) - task.jvmArguments.convention(dsl.applicationDefaultJvmArgs) - } + val binariesDsl = target::class.memberProperties + .single { it.name == "binariesDsl" } + .apply { isAccessible = true } + .getter.call(target) as KotlinJvmBinariesDsl + + binariesDsl.executable { dsl -> + task.mainModule.set(dsl.mainModule) + task.mainClass.set(dsl.mainClass) + task.jvmArguments.convention(dsl.applicationDefaultJvmArgs) } } } From 6fd6f567ce2f9dcfd03b90ce3a02353f48d69c94 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 13 Sep 2025 21:02:52 +0800 Subject: [PATCH 3/6] Revert "Try to get `binariesDsl` via reflection" --- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index 56f9d8f5b..a0208459e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -5,8 +5,6 @@ import com.github.jengelman.gradle.plugins.shadow.internal.isAtLeastKgpVersion import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.registerShadowJarCommon import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar -import kotlin.reflect.full.memberProperties -import kotlin.reflect.jvm.isAccessible import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.ApplicationPlugin @@ -14,7 +12,6 @@ import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.bundling.Jar import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmBinariesDsl import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget public abstract class ShadowKmpPlugin : Plugin { @@ -62,15 +59,13 @@ public abstract class ShadowKmpPlugin : Plugin { task.classpath = files(tasks.shadowJar) - val binariesDsl = target::class.memberProperties - .single { it.name == "binariesDsl" } - .apply { isAccessible = true } - .getter.call(target) as KotlinJvmBinariesDsl - - binariesDsl.executable { dsl -> - task.mainModule.set(dsl.mainModule) - task.mainClass.set(dsl.mainClass) - task.jvmArguments.convention(dsl.applicationDefaultJvmArgs) + @OptIn(ExperimentalKotlinGradlePluginApi::class) + target.binaries { + executable { dsl -> + task.mainModule.set(dsl.mainModule) + task.mainClass.set(dsl.mainClass) + task.jvmArguments.convention(dsl.applicationDefaultJvmArgs) + } } } } From 75a91d44846d14bb599220b5820f21109e6cea9f Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 13 Sep 2025 21:58:48 +0800 Subject: [PATCH 4/6] Register `runShadow` in `afterEvaluate` --- .../plugins/shadow/KotlinPluginsTest.kt | 2 +- .../plugins/shadow/ShadowApplicationPlugin.kt | 19 +++++++--- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 37 +++++++++---------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt index 9baa2997b..7fc931548 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt @@ -292,7 +292,7 @@ class KotlinPluginsTest : BasePluginTest() { """.trimIndent(), ) - val result = run(runShadowPath) + val result = run(runShadowPath, "--args='foo'") assertThat(result.output).contains( "Hello, World! (foo) from Main", diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt index f5b05ad69..81504abad 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt @@ -8,6 +8,7 @@ import com.github.jengelman.gradle.plugins.shadow.internal.javaPluginExtension import com.github.jengelman.gradle.plugins.shadow.internal.javaToolchainService import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar import java.io.IOException +import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.Plugin import org.gradle.api.Project @@ -35,12 +36,7 @@ public abstract class ShadowApplicationPlugin : Plugin { } protected open fun Project.addRunTask() { - tasks.register(SHADOW_RUN_TASK_NAME, JavaExec::class.java) { task -> - task.description = "Runs this project as a JVM application using the shadow jar" - task.group = ApplicationPlugin.APPLICATION_GROUP - - task.classpath = files(tasks.shadowJar) - + registerRunShadowCommon { task -> with(applicationExtension) { task.mainModule.convention(mainModule) task.mainClass.convention(mainClass) @@ -146,5 +142,16 @@ public abstract class ShadowApplicationPlugin : Plugin { @get:JvmSynthetic public inline val TaskContainer.installShadowDist: TaskProvider get() = named(SHADOW_INSTALL_TASK_NAME, Sync::class.java) + + internal fun Project.registerRunShadowCommon( + action: Action, + ): TaskProvider { + return tasks.register(SHADOW_RUN_TASK_NAME, JavaExec::class.java) { task -> + task.description = "Runs this project as a JVM application using the shadow jar" + task.group = ApplicationPlugin.APPLICATION_GROUP + task.classpath = files(tasks.shadowJar) + action.execute(task) + } + } } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index a0208459e..9a7727b01 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -1,13 +1,11 @@ package com.github.jengelman.gradle.plugins.shadow -import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.SHADOW_RUN_TASK_NAME +import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.registerRunShadowCommon import com.github.jengelman.gradle.plugins.shadow.internal.isAtLeastKgpVersion import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.registerShadowJarCommon -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.plugins.ApplicationPlugin import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.bundling.Jar import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi @@ -27,7 +25,14 @@ public abstract class ShadowKmpPlugin : Plugin { } configureShadowJar(target) - addRunTask(target) + } + + // TODO: https://youtrack.jetbrains.com/issue/KT-77499 + afterEvaluate { + if (!isAtLeastKgpVersion(2, 1, 20)) return@afterEvaluate + @Suppress("EagerGradleConfiguration") // TODO: https://issuetracker.google.com/issues/444825893 + val runJvmTask = tasks.findByName("runJvm") as? JavaExec ?: return@afterEvaluate + addRunTask(runJvmTask) } } @@ -50,22 +55,14 @@ public abstract class ShadowKmpPlugin : Plugin { } } - private fun Project.addRunTask(target: KotlinJvmTarget) { - if (!isAtLeastKgpVersion(2, 1, 20)) return - - tasks.register(SHADOW_RUN_TASK_NAME, JavaExec::class.java) { task -> - task.description = "Runs this project as a JVM application using the shadow jar" - task.group = ApplicationPlugin.APPLICATION_GROUP - - task.classpath = files(tasks.shadowJar) - - @OptIn(ExperimentalKotlinGradlePluginApi::class) - target.binaries { - executable { dsl -> - task.mainModule.set(dsl.mainModule) - task.mainClass.set(dsl.mainClass) - task.jvmArguments.convention(dsl.applicationDefaultJvmArgs) - } + private fun Project.addRunTask(runJvmTask: JavaExec) { + registerRunShadowCommon { task -> + with(runJvmTask) { + task.mainModule.convention(mainModule) + task.mainClass.convention(mainClass) + task.jvmArguments.convention(jvmArguments) + task.modularity.inferModulePath.convention(modularity.inferModulePath) + task.javaLauncher.convention(javaLauncher) } } } From 56d70e929de211254e050f08d322d14150be7de3 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 14 Sep 2025 17:52:00 +0800 Subject: [PATCH 5/6] Register `startShadowScripts` from `startScriptsForJvm` --- .../plugins/shadow/ShadowApplicationPlugin.kt | 20 ++++++---- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 37 ++++++++++++++++++- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt index 81504abad..6d565ea9e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt @@ -48,13 +48,8 @@ public abstract class ShadowApplicationPlugin : Plugin { } protected open fun Project.addCreateScriptsTask() { - tasks.register(SHADOW_SCRIPTS_TASK_NAME, CreateStartScripts::class.java) { task -> - task.description = "Creates OS specific scripts to run the project as a JVM application using the shadow jar" - task.group = ApplicationPlugin.APPLICATION_GROUP - - task.classpath = files(tasks.shadowJar) - - @Suppress("InternalGradleApiUsage") // Usages of conventionMapping. + registerStartShadowScriptsCommon { task -> + @Suppress("InternalGradleApiUsage", "DuplicatedCode") // Usages of conventionMapping. with(applicationExtension) { task.mainModule.convention(mainModule) task.mainClass.convention(mainClass) @@ -153,5 +148,16 @@ public abstract class ShadowApplicationPlugin : Plugin { action.execute(task) } } + + internal fun Project.registerStartShadowScriptsCommon( + action: Action, + ): TaskProvider { + return tasks.register(SHADOW_SCRIPTS_TASK_NAME, CreateStartScripts::class.java) { task -> + task.description = "Creates OS specific scripts to run the project as a JVM application using the shadow jar" + task.group = ApplicationPlugin.APPLICATION_GROUP + task.classpath = files(tasks.shadowJar) + action.execute(task) + } + } } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index 9a7727b01..ea37e28a0 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -1,12 +1,16 @@ package com.github.jengelman.gradle.plugins.shadow import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.registerRunShadowCommon +import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.registerStartShadowScriptsCommon import com.github.jengelman.gradle.plugins.shadow.internal.isAtLeastKgpVersion import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.registerShadowJarCommon +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar +import java.util.Locale import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.application.CreateStartScripts import org.gradle.api.tasks.bundling.Jar import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension @@ -15,6 +19,8 @@ import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget public abstract class ShadowKmpPlugin : Plugin { override fun apply(project: Project): Unit = with(project) { + var jvmTarget: KotlinJvmTarget? = null + extensions.getByType(KotlinMultiplatformExtension::class.java).targets.configureEach { target -> if (target !is KotlinJvmTarget) return@configureEach @Suppress("EagerGradleConfiguration") @@ -25,14 +31,24 @@ public abstract class ShadowKmpPlugin : Plugin { } configureShadowJar(target) + jvmTarget = target } // TODO: https://youtrack.jetbrains.com/issue/KT-77499 afterEvaluate { if (!isAtLeastKgpVersion(2, 1, 20)) return@afterEvaluate + jvmTarget ?: return@afterEvaluate + val targetNameCap = jvmTarget.targetName.replaceFirstChar { it.titlecase(Locale.US) } + + @Suppress("EagerGradleConfiguration") // TODO: https://issuetracker.google.com/issues/444825893 + (tasks.findByName("run$targetNameCap") as? JavaExec)?.let { + addRunTask(it) + } ?: return@afterEvaluate + // This task must exist if the runJvmTask exists. @Suppress("EagerGradleConfiguration") // TODO: https://issuetracker.google.com/issues/444825893 - val runJvmTask = tasks.findByName("runJvm") as? JavaExec ?: return@afterEvaluate - addRunTask(runJvmTask) + (tasks.getByName("startScriptsFor$targetNameCap") as CreateStartScripts).let { + addCreateScriptsTask(it) + } } } @@ -56,6 +72,9 @@ public abstract class ShadowKmpPlugin : Plugin { } private fun Project.addRunTask(runJvmTask: JavaExec) { + tasks.shadowJar.configure { task -> + task.mainClass.convention(runJvmTask.mainClass) + } registerRunShadowCommon { task -> with(runJvmTask) { task.mainModule.convention(mainModule) @@ -66,4 +85,18 @@ public abstract class ShadowKmpPlugin : Plugin { } } } + + private fun Project.addCreateScriptsTask(startScriptsTask: CreateStartScripts) { + registerStartShadowScriptsCommon { task -> + @Suppress("InternalGradleApiUsage", "DuplicatedCode") // Usages of conventionMapping. + with(startScriptsTask) { + task.mainModule.convention(mainModule) + task.mainClass.convention(mainClass) + task.conventionMapping.map("applicationName", ::getApplicationName) + task.conventionMapping.map("outputDir") { layout.buildDirectory.dir("scriptsShadow").get().asFile } + task.conventionMapping.map("executableDir", ::getExecutableDir) + task.conventionMapping.map("defaultJvmOpts", ::getDefaultJvmOpts) + } + } + } } From e19ab20e9467fdfcf1de0b97a2b770c8b128afd2 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 14 Sep 2025 18:39:06 +0800 Subject: [PATCH 6/6] Register shadow distribution --- .../plugins/shadow/ShadowApplicationPlugin.kt | 28 +++++++++++++------ .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 18 ++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt index 6d565ea9e..b21e24d5e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt @@ -12,7 +12,9 @@ import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.distribution.Distribution import org.gradle.api.plugins.ApplicationPlugin +import org.gradle.api.provider.Provider import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.Sync import org.gradle.api.tasks.TaskContainer @@ -87,7 +89,7 @@ public abstract class ShadowApplicationPlugin : Plugin { } protected open fun Project.configureDistribution() { - distributions.register(DISTRIBUTION_NAME) { dist -> + registerShadowDistributionCommon { dist -> dist.distributionBaseName.convention( provider { // distributionBaseName defaults to `$project.name-$distribution.name`, applicationName defaults to project.name @@ -96,12 +98,6 @@ public abstract class ShadowApplicationPlugin : Plugin { }, ) dist.contents { distSpec -> - distSpec.from(file("src/dist")) - distSpec.into("lib") { lib -> - lib.from(tasks.shadowJar) - // Reflects the value of the `Class-Path` attribute in the JAR manifest. - lib.from(configurations.shadow) - } // Defaults to bin dir. distSpec.into(provider(applicationExtension::getExecutableDir)) { bin -> bin.from(tasks.startShadowScripts) @@ -122,7 +118,7 @@ public abstract class ShadowApplicationPlugin : Plugin { /** * Reflects the number of 755. */ - private const val UNIX_SCRIPT_PERMISSIONS = "rwxr-xr-x" + internal const val UNIX_SCRIPT_PERMISSIONS = "rwxr-xr-x" public const val DISTRIBUTION_NAME: String = SHADOW @@ -159,5 +155,21 @@ public abstract class ShadowApplicationPlugin : Plugin { action.execute(task) } } + + internal fun Project.registerShadowDistributionCommon( + action: Action, + ): Provider { + return distributions.register(DISTRIBUTION_NAME) { dist -> + dist.contents { distSpec -> + distSpec.from(file("src/dist")) + distSpec.into("lib") { lib -> + lib.from(tasks.shadowJar) + // Reflects the value of the `Class-Path` attribute in the JAR manifest. + lib.from(configurations.shadow) + } + } + action.execute(dist) + } + } } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index ea37e28a0..4d072658e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -1,7 +1,10 @@ package com.github.jengelman.gradle.plugins.shadow +import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.UNIX_SCRIPT_PERMISSIONS import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.registerRunShadowCommon +import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.registerShadowDistributionCommon import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.registerStartShadowScriptsCommon +import com.github.jengelman.gradle.plugins.shadow.ShadowApplicationPlugin.Companion.startShadowScripts import com.github.jengelman.gradle.plugins.shadow.internal.isAtLeastKgpVersion import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.SHADOW_JAR_TASK_NAME import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.registerShadowJarCommon @@ -49,6 +52,7 @@ public abstract class ShadowKmpPlugin : Plugin { (tasks.getByName("startScriptsFor$targetNameCap") as CreateStartScripts).let { addCreateScriptsTask(it) } + configureDistribution() } } @@ -99,4 +103,18 @@ public abstract class ShadowKmpPlugin : Plugin { } } } + + private fun Project.configureDistribution() { + registerShadowDistributionCommon { dist -> + dist.contents { distSpec -> + // Should use KotlinJvmBinaryDsl.applicationDistribution instead. + distSpec.into("bin") { bin -> + bin.from(tasks.startShadowScripts) + bin.filePermissions { permissions -> permissions.unix(UNIX_SCRIPT_PERMISSIONS) } + } + // TODO: we can't access KotlinJvmBinaryDsl instance for now. +// distSpec.with(KotlinJvmBinaryDsl.applicationDistribution) + } + } + } }