From 1f5c4e213a14a869145fd254439f51cd87257e71 Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Fri, 10 Apr 2026 09:43:23 -0400 Subject: [PATCH 1/2] Replace SetProperty with ConfigurableFileCollection on ShadowJar Add addConfiguration(), setConfigurations(), clearConfigurations() methods that maintain both the CC-safe ConfigurableFileCollection and an internal Configuration list for DependencyFilter compatibility. --- .../gradle/plugins/shadow/JavaPluginsTest.kt | 8 ++--- .../gradle/plugins/shadow/PublishingTest.kt | 2 +- .../gradle/plugins/shadow/RelocationTest.kt | 2 +- .../gradle/plugins/shadow/ShadowJavaPlugin.kt | 2 +- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 6 ++-- .../gradle/plugins/shadow/tasks/ShadowJar.kt | 33 ++++++++++++++++--- .../plugins/shadow/ShadowPropertiesTest.kt | 2 +- 7 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index 7123ba48a..1d05b6109 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -714,7 +714,7 @@ class JavaPluginsTest : BasePluginTest() { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'test' from sourceSets.named('test').map { it.output } - configurations = project.configurations.named('testRuntimeClasspath').map { [it] } + setConfigurations([project.configurations.testRuntimeClasspath]) manifest { attributes '$mainClassAttributeKey': 'my.Main' } @@ -751,7 +751,7 @@ class JavaPluginsTest : BasePluginTest() { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'test' from sourceSets.named('test').map { it.output } - configurations = project.configurations.named('testRuntimeClasspath').map { [it] } + setConfigurations([project.configurations.testRuntimeClasspath]) manifest { attributes '$mainClassAttributeKey': 'my.Main' } @@ -795,7 +795,7 @@ class JavaPluginsTest : BasePluginTest() { def $dependencyShadowJar = tasks.register('$dependencyShadowJar', ${ShadowJar::class.java.name}) { description = 'Create a shadow JAR of all dependencies' archiveClassifier = 'dep' - configurations = project.configurations.named('runtimeClasspath').map { [it] } + setConfigurations([project.configurations.runtimeClasspath]) } """ .trimIndent() @@ -1185,7 +1185,7 @@ class JavaPluginsTest : BasePluginTest() { } $shadowJarTask { - configurations = [project.configurations.runtimeClasspath] + setConfigurations([project.configurations.runtimeClasspath]) } configurations.runtimeClasspath { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt index 754ce1caf..1a419d9f5 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt @@ -305,7 +305,7 @@ class PublishingTest : BasePluginTest() { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'tests' from sourceSets.named('test').map { it.output } - configurations = project.configurations.named('testRuntimeClasspath').map { [it] } + setConfigurations([project.configurations.testRuntimeClasspath]) } """ .trimIndent(), diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index 68d23bc75..ee2a853ea 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -466,7 +466,7 @@ class RelocationTest : BasePluginTest() { implementation 'junit:junit:3.8.2' } $shadowJarTask { - configurations = [] + clearConfigurations() relocate('', 'foo/') } """ diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt index 68aae0281..c164b08e7 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt @@ -42,7 +42,7 @@ constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Pl val taskProvider = registerShadowJarCommon(tasks.named("jar", Jar::class.java)) { task -> task.from(sourceSets.named("main").map { it.output }) - task.configurations.convention(provider { listOf(runtimeConfiguration) }) + task.addConfiguration(runtimeConfiguration) } artifacts.add(configurations.shadow.name, taskProvider) } 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 5cb4fe242..eb2209ccd 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 @@ -36,10 +36,8 @@ public abstract class ShadowKmpPlugin : Plugin { val kotlinJvmMain = target.compilations.named("main") registerShadowJarCommon(tasks.named(target.artifactsTaskName, Jar::class.java)) { task -> task.from(kotlinJvmMain.map { it.output.allOutputs }) - task.configurations.convention( - provider { - listOf(configurations.getByName(kotlinJvmMain.get().runtimeDependencyConfigurationName)) - } + task.addConfiguration( + configurations.getByName(kotlinJvmMain.get().runtimeDependencyConfigurationName) ) if (!isAtLeastKgp("1.9.0")) return@registerShadowJarCommon diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt index 3bb828c73..ae7e8a849 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt @@ -72,6 +72,9 @@ public abstract class ShadowJar : Jar() { project.configurations.findByName(ShadowBasePlugin.CONFIGURATION_NAME) ?: project.files() } + @Transient + private val _sourceConfigurations = mutableListOf() + init { group = LifecycleBasePlugin.BUILD_GROUP description = "Create a combined JAR of project and runtime dependencies" @@ -101,7 +104,7 @@ public abstract class ShadowJar : Jar() { @get:Classpath public open val toMinimize: ConfigurableFileCollection = objectFactory.fileCollection { minimizeJar.map { - if (it) (dependencyFilterForMinimize.resolve(configurations.get()) - apiJars) else emptySet() + if (it) (dependencyFilterForMinimize.resolve(_sourceConfigurations) - apiJars) else emptySet() } } @@ -132,12 +135,34 @@ public abstract class ShadowJar : Jar() { @get:Nested public open val relocators: SetProperty = objectFactory.setProperty() /** - * The configurations to include dependencies from. + * The resolved files from configurations to include dependencies from. + * + * Do not add to this file collection directly. Use [addConfiguration], [setConfigurations], + * or [clearConfigurations] instead, so that dependency filtering works correctly. * * Defaults to a set that contains `runtimeClasspath` or `runtime` configuration. */ @get:Classpath - public open val configurations: SetProperty = objectFactory.setProperty() + public open val configurations: ConfigurableFileCollection = objectFactory.fileCollection() + + /** Add a [Configuration] whose dependencies should be shadowed. */ + public open fun addConfiguration(config: Configuration) { + _sourceConfigurations.add(config) + configurations.from(config) + } + + /** Replace all configurations with the given set. */ + public open fun setConfigurations(configs: Iterable) { + _sourceConfigurations.clear() + configurations.setFrom() + configs.forEach { addConfiguration(it) } + } + + /** Remove all configurations. */ + public open fun clearConfigurations() { + _sourceConfigurations.clear() + configurations.setFrom() + } @get:Input public open val dependencyFilter: Property = @@ -146,7 +171,7 @@ public abstract class ShadowJar : Jar() { /** Final dependencies to be shadowed. */ @get:Classpath public open val includedDependencies: ConfigurableFileCollection = objectFactory.fileCollection { - dependencyFilter.zip(configurations) { df, cs -> df.resolve(cs) } + dependencyFilter.map { df -> df.resolve(_sourceConfigurations) } } /** diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt index d5bf5e8f4..fb05e4b74 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt @@ -154,7 +154,7 @@ class ShadowPropertiesTest { assertThat(mainClass.orNull).isNull() assertThat(relocationPrefix.get()).isEqualTo(ShadowBasePlugin.SHADOW) - assertThat(configurations.get()).containsOnly(runtimeConfiguration) + assertThat(configurations.files).isEqualTo(runtimeConfiguration.files) } } From ea3e9a52fbc17247c49d0c9a34b50b77ded74bdb Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 15 Apr 2026 10:55:14 +0800 Subject: [PATCH 2/2] Rework --- api/shadow.api | 4 ++- docs/configuration/dependencies/README.md | 6 ++-- docs/configuration/relocation/README.md | 6 ++-- docs/custom-tasks/README.md | 8 ++--- docs/publishing/README.md | 6 ++-- .../gradle/plugins/shadow/JavaPluginsTest.kt | 8 ++--- .../gradle/plugins/shadow/PublishingTest.kt | 2 +- .../gradle/plugins/shadow/RelocationTest.kt | 3 +- .../gradle/plugins/shadow/ShadowJavaPlugin.kt | 2 +- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 6 ++-- .../plugins/shadow/tasks/DependencyFilter.kt | 26 +++++++++++++++ .../gradle/plugins/shadow/tasks/ShadowJar.kt | 32 ++----------------- .../plugins/shadow/ShadowPropertiesTest.kt | 4 ++- 13 files changed, 61 insertions(+), 52 deletions(-) diff --git a/api/shadow.api b/api/shadow.api index 46f49e233..43ec17f8c 100644 --- a/api/shadow.api +++ b/api/shadow.api @@ -160,6 +160,7 @@ public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks public abstract fun project (Ljava/lang/Object;)Lorg/gradle/api/specs/Spec; public abstract fun resolve (Ljava/util/Collection;)Lorg/gradle/api/file/FileCollection; public abstract fun resolve (Lorg/gradle/api/artifacts/Configuration;)Lorg/gradle/api/file/FileCollection; + public abstract fun resolve (Lorg/gradle/api/file/ConfigurableFileCollection;)Lorg/gradle/api/file/FileCollection; } public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter$AbstractDependencyFilter : com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter { @@ -175,6 +176,7 @@ public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/Dependenc public fun resolve (Ljava/util/Collection;)Lorg/gradle/api/file/FileCollection; protected abstract fun resolve (Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;)V public fun resolve (Lorg/gradle/api/artifacts/Configuration;)Lorg/gradle/api/file/FileCollection; + public fun resolve (Lorg/gradle/api/file/ConfigurableFileCollection;)Lorg/gradle/api/file/FileCollection; } public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/FindResourceInClasspath : org/gradle/api/DefaultTask, org/gradle/api/tasks/util/PatternFilterable { @@ -225,7 +227,7 @@ public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar public fun getAddMultiReleaseAttribute ()Lorg/gradle/api/provider/Property; public fun getApiJars ()Lorg/gradle/api/file/ConfigurableFileCollection; protected abstract fun getArchiveOperations ()Lorg/gradle/api/file/ArchiveOperations; - public fun getConfigurations ()Lorg/gradle/api/provider/SetProperty; + public fun getConfigurations ()Lorg/gradle/api/file/ConfigurableFileCollection; public fun getDependencyFilter ()Lorg/gradle/api/provider/Property; public fun getDuplicatesStrategy ()Lorg/gradle/api/file/DuplicatesStrategy; public fun getEnableAutoRelocation ()Lorg/gradle/api/provider/Property; diff --git a/docs/configuration/dependencies/README.md b/docs/configuration/dependencies/README.md index 2b62f575f..f837189d4 100644 --- a/docs/configuration/dependencies/README.md +++ b/docs/configuration/dependencies/README.md @@ -9,7 +9,7 @@ merging can be configured using the [`configurations`][ShadowJar.configurations] ```kotlin tasks.shadowJar { - configurations = project.configurations.compileClasspath.map { listOf(it) } + configurations.setFrom(project.configurations.compileClasspath) } ``` @@ -17,7 +17,7 @@ merging can be configured using the [`configurations`][ShadowJar.configurations] ```groovy tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { - configurations = project.configurations.named('compileClasspath').map { [it] } + configurations.setFrom project.configurations.named('compileClasspath') } ``` @@ -27,7 +27,7 @@ This means any dependency declared in the `runtimeOnly` configuration would be * > Note the literal use of [`project.configurations`][Project.configurations] when setting the > [`configurations`][ShadowJar.configurations] attribute of a [`ShadowJar`][ShadowJar] task. -> This is **required**. It may be tempting to specify `configurations = [configurations.compileClasspath]` but this will +> This is **required**. It may be tempting to specify `configurations.setFrom(configurations.compileClasspath)` but this will > not have the intended effect, as `configurations.compile` will try to delegate to the > [`configurations`][ShadowJar.configurations] property of the [`ShadowJar`][ShadowJar] task instead of the `project` diff --git a/docs/configuration/relocation/README.md b/docs/configuration/relocation/README.md index 0f64e9b6a..991ef5b93 100644 --- a/docs/configuration/relocation/README.md +++ b/docs/configuration/relocation/README.md @@ -227,7 +227,8 @@ relocating), you can try out the trick like: ```kotlin tasks.shadowJar { // Empty configurations list will exclude all dependencies. - configurations = emptyList() + configurations.unset() + configurations.unsetConvention() relocate("com.example", "shadow.com.example") } ``` @@ -237,7 +238,8 @@ relocating), you can try out the trick like: ```groovy tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { // Empty configurations list will exclude all dependencies. - configurations = [] + configurations.unset() + configurations.unsetConvention() relocate 'com.example', 'shadow.com.example' } ``` diff --git a/docs/custom-tasks/README.md b/docs/custom-tasks/README.md index a9e56b138..3b30fa80c 100644 --- a/docs/custom-tasks/README.md +++ b/docs/custom-tasks/README.md @@ -13,7 +13,7 @@ the output. archiveClassifier = "test" from(sourceSets.test.map { it.output }) - configurations = project.configurations.testRuntimeClasspath.map { listOf(it) } + configurations.setFrom(project.configurations.testRuntimeClasspath) manifest { // Optionally, set the main class for the JAR. @@ -36,7 +36,7 @@ the output. archiveClassifier = 'test' from sourceSets.named('test').map { it.output } - configurations = project.configurations.named('testRuntimeClasspath').map { [it] } + configurations.setFrom project.configurations.named('testRuntimeClasspath') manifest { // Optionally, set the main class for the JAR. @@ -67,7 +67,7 @@ source code. This is accomplished by creating a custom [`ShadowJar`][ShadowJar] tasks.registering(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) { description = "Create a shadow JAR of all dependencies" archiveClassifier = "dep" - configurations = project.configurations.runtimeClasspath.map { listOf(it) } + configurations.setFrom(project.configurations.runtimeClasspath) } ``` @@ -77,7 +77,7 @@ source code. This is accomplished by creating a custom [`ShadowJar`][ShadowJar] tasks.register('dependencyShadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { description = 'Create a shadow JAR of all dependencies' archiveClassifier = 'dep' - configurations = project.configurations.named('runtimeClasspath').map { [it] } + configurations.setFrom project.configurations.named('runtimeClasspath') } ``` diff --git a/docs/publishing/README.md b/docs/publishing/README.md index 06112ad68..3ddcd7082 100644 --- a/docs/publishing/README.md +++ b/docs/publishing/README.md @@ -160,7 +160,7 @@ published artifact. No other dependencies are automatically configured for inclusion in the POM file. For example, excluded dependencies are **not** automatically added to the POM file or if the configuration for merging are modified by specifying -`shadowJar.configurations = [configurations.myConfiguration]`, there is no automatic +`shadowJar.configurations.setFrom(configurations.myConfiguration)`, there is no automatic configuration of the POM file. This automatic configuration occurs _only_ when using the above methods for @@ -402,7 +402,7 @@ It is possible to publish a custom [`ShadowJar`][ShadowJar] task's output via th description = "Create a combined JAR of project and test dependencies" archiveClassifier = "tests" from(sourceSets.test.map { it.output }) - configurations = project.configurations.testRuntimeClasspath.map { listOf(it) } + configurations.setFrom(project.configurations.testRuntimeClasspath) } dependencies { @@ -434,7 +434,7 @@ It is possible to publish a custom [`ShadowJar`][ShadowJar] task's output via th description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'tests' from sourceSets.named('test').map { it.output } - configurations = project.configurations.named('testRuntimeClasspath').map { [it] } + configurations.setFrom project.configurations.named('testRuntimeClasspath') } dependencies { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index 1d05b6109..e9c7f2813 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -714,7 +714,7 @@ class JavaPluginsTest : BasePluginTest() { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'test' from sourceSets.named('test').map { it.output } - setConfigurations([project.configurations.testRuntimeClasspath]) + configurations.setFrom project.configurations.named('testRuntimeClasspath') manifest { attributes '$mainClassAttributeKey': 'my.Main' } @@ -751,7 +751,7 @@ class JavaPluginsTest : BasePluginTest() { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'test' from sourceSets.named('test').map { it.output } - setConfigurations([project.configurations.testRuntimeClasspath]) + configurations.setFrom project.configurations.named('testRuntimeClasspath') manifest { attributes '$mainClassAttributeKey': 'my.Main' } @@ -795,7 +795,7 @@ class JavaPluginsTest : BasePluginTest() { def $dependencyShadowJar = tasks.register('$dependencyShadowJar', ${ShadowJar::class.java.name}) { description = 'Create a shadow JAR of all dependencies' archiveClassifier = 'dep' - setConfigurations([project.configurations.runtimeClasspath]) + configurations.setFrom project.configurations.named('runtimeClasspath') } """ .trimIndent() @@ -1185,7 +1185,7 @@ class JavaPluginsTest : BasePluginTest() { } $shadowJarTask { - setConfigurations([project.configurations.runtimeClasspath]) + configurations.setFrom project.configurations.runtimeClasspath } configurations.runtimeClasspath { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt index 1a419d9f5..881777969 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt @@ -305,7 +305,7 @@ class PublishingTest : BasePluginTest() { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'tests' from sourceSets.named('test').map { it.output } - setConfigurations([project.configurations.testRuntimeClasspath]) + configurations.setFrom project.configurations.named('testRuntimeClasspath') } """ .trimIndent(), diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index ee2a853ea..a3fad6456 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -466,7 +466,8 @@ class RelocationTest : BasePluginTest() { implementation 'junit:junit:3.8.2' } $shadowJarTask { - clearConfigurations() + configurations.unset() + configurations.unsetConvention() relocate('', 'foo/') } """ diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt index c164b08e7..1ebd78d04 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt @@ -42,7 +42,7 @@ constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Pl val taskProvider = registerShadowJarCommon(tasks.named("jar", Jar::class.java)) { task -> task.from(sourceSets.named("main").map { it.output }) - task.addConfiguration(runtimeConfiguration) + task.configurations.convention(provider { runtimeConfiguration }) } artifacts.add(configurations.shadow.name, taskProvider) } 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 eb2209ccd..104913ae7 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 @@ -36,8 +36,10 @@ public abstract class ShadowKmpPlugin : Plugin { val kotlinJvmMain = target.compilations.named("main") registerShadowJarCommon(tasks.named(target.artifactsTaskName, Jar::class.java)) { task -> task.from(kotlinJvmMain.map { it.output.allOutputs }) - task.addConfiguration( - configurations.getByName(kotlinJvmMain.get().runtimeDependencyConfigurationName) + task.configurations.convention( + provider { + configurations.getByName(kotlinJvmMain.get().runtimeDependencyConfigurationName) + } ) if (!isAtLeastKgp("1.9.0")) return@registerShadowJarCommon diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt index 93291853a..b22ab7af4 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt @@ -7,6 +7,7 @@ import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.ResolvedDependency +import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection import org.gradle.api.provider.Provider import org.gradle.api.specs.Spec @@ -22,6 +23,13 @@ public interface DependencyFilter : Serializable { */ public fun resolve(configurations: Collection): FileCollection + /** + * Resolve a [ConfigurableFileCollection] against the [include]/[exclude] rules in the filter. + * + * Any [Configuration] sources within the collection are resolved individually and combined. + */ + public fun resolve(configurations: ConfigurableFileCollection): FileCollection + /** Exclude dependencies that match the provided [spec]. */ public fun exclude(spec: Spec) @@ -68,6 +76,24 @@ public interface DependencyFilter : Serializable { .reduceOrNull { acc, fileCollection -> acc + fileCollection } ?: project.files() } + override fun resolve(configurations: ConfigurableFileCollection): FileCollection { + val extracted = configurations.from.flatMap { source -> extractConfigurations(source) } + return resolve(extracted) + } + + private fun extractConfigurations(source: Any): List = + when (source) { + is Configuration -> listOf(source) + is Provider<*> -> + when (val value = source.orNull) { + is Configuration -> listOf(value) + is Iterable<*> -> value.filterIsInstance() + else -> emptyList() + } + is Iterable<*> -> source.filterIsInstance() + else -> emptyList() + } + override fun exclude(spec: Spec) { excludeSpecs.add(spec) } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt index ae7e8a849..4c80e9ecf 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt @@ -34,7 +34,6 @@ import org.apache.tools.zip.Zip64Mode import org.apache.tools.zip.ZipOutputStream import org.gradle.api.Action import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.CopySpec @@ -72,9 +71,6 @@ public abstract class ShadowJar : Jar() { project.configurations.findByName(ShadowBasePlugin.CONFIGURATION_NAME) ?: project.files() } - @Transient - private val _sourceConfigurations = mutableListOf() - init { group = LifecycleBasePlugin.BUILD_GROUP description = "Create a combined JAR of project and runtime dependencies" @@ -104,7 +100,7 @@ public abstract class ShadowJar : Jar() { @get:Classpath public open val toMinimize: ConfigurableFileCollection = objectFactory.fileCollection { minimizeJar.map { - if (it) (dependencyFilterForMinimize.resolve(_sourceConfigurations) - apiJars) else emptySet() + if (it) (dependencyFilterForMinimize.resolve(configurations) - apiJars) else emptySet() } } @@ -135,35 +131,13 @@ public abstract class ShadowJar : Jar() { @get:Nested public open val relocators: SetProperty = objectFactory.setProperty() /** - * The resolved files from configurations to include dependencies from. - * - * Do not add to this file collection directly. Use [addConfiguration], [setConfigurations], - * or [clearConfigurations] instead, so that dependency filtering works correctly. + * The configurations to include dependencies from. * * Defaults to a set that contains `runtimeClasspath` or `runtime` configuration. */ @get:Classpath public open val configurations: ConfigurableFileCollection = objectFactory.fileCollection() - /** Add a [Configuration] whose dependencies should be shadowed. */ - public open fun addConfiguration(config: Configuration) { - _sourceConfigurations.add(config) - configurations.from(config) - } - - /** Replace all configurations with the given set. */ - public open fun setConfigurations(configs: Iterable) { - _sourceConfigurations.clear() - configurations.setFrom() - configs.forEach { addConfiguration(it) } - } - - /** Remove all configurations. */ - public open fun clearConfigurations() { - _sourceConfigurations.clear() - configurations.setFrom() - } - @get:Input public open val dependencyFilter: Property = objectFactory.property(DefaultDependencyFilter(project)) @@ -171,7 +145,7 @@ public abstract class ShadowJar : Jar() { /** Final dependencies to be shadowed. */ @get:Classpath public open val includedDependencies: ConfigurableFileCollection = objectFactory.fileCollection { - dependencyFilter.map { df -> df.resolve(_sourceConfigurations) } + dependencyFilter.map { df -> df.resolve(configurations) } } /** diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt index fb05e4b74..abdab567d 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt @@ -33,6 +33,7 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin.API_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME +import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskContainer import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.AbstractArchiveTask @@ -154,7 +155,8 @@ class ShadowPropertiesTest { assertThat(mainClass.orNull).isNull() assertThat(relocationPrefix.get()).isEqualTo(ShadowBasePlugin.SHADOW) - assertThat(configurations.files).isEqualTo(runtimeConfiguration.files) + assertThat(configurations.from.map { (it as Provider<*>).get() }) + .containsOnly(runtimeConfiguration) } }