From 9c944b52b88c85f9b2e77ef8802b5579c5463644 Mon Sep 17 00:00:00 2001 From: Greg Harris Date: Fri, 28 Jun 2024 14:25:48 -0700 Subject: [PATCH 01/11] Prototype: Configuring publish before shadowJar uses wrong configuration Signed-off-by: Greg Harris --- .../gradle/plugins/shadow/PublishingSpec.groovy | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy index 450f2a698..cf76fd450 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy @@ -97,12 +97,6 @@ class PublishingSpec extends PluginSpecification { shadow 'shadow:b:1.0' } - tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { - archiveClassifier = 'my-classifier' - archiveExtension = 'my-ext' - archiveBaseName = 'maven-all' - } - publishing { publications { shadow(MavenPublication) { publication -> @@ -116,6 +110,12 @@ class PublishingSpec extends PluginSpecification { } } } + + tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { + archiveClassifier = 'my-classifier' + archiveExtension = 'my-ext' + archiveBaseName = 'maven-all' + } """.stripIndent() when: From 83aa1c7cd634ef20e4e6fcbb0ae581f8295cf4d9 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 3 Sep 2024 08:47:58 +0800 Subject: [PATCH 02/11] Tweak test --- .../gradle/plugins/shadow/PublishingSpec.groovy | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy index cf76fd450..83b6afdfa 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy @@ -6,6 +6,7 @@ import groovy.json.JsonSlurper import groovy.xml.XmlSlurper import org.gradle.api.attributes.Bundling import org.gradle.api.attributes.Usage +import spock.lang.Issue class PublishingSpec extends PluginSpecification { @@ -78,6 +79,7 @@ class PublishingSpec extends PluginSpecification { assert dependency.version.text() == '1.0' } + @Issue(["https://github.com/GradleUp/shadow/issues/860", "https://github.com/GradleUp/shadow/issues/945"]) def "publish shadow jar with maven-publish plugin using custom classifier and extension"() { given: repo.module('shadow', 'a', '1.0') @@ -122,8 +124,11 @@ class PublishingSpec extends PluginSpecification { run('publish') then: - File publishedFile = publishingRepo.rootDir.file('shadow/maven-all/1.0/maven-all-1.0-my-classifier.my-ext').canonicalFile - assert publishedFile.exists() + def publishedFiles = publishingRepo.rootDir.file('shadow/maven-all/1.0/').canonicalFile + .listFiles() + .findAll { it.exists() } + .collect { it.name } + assert publishedFiles.contains('maven-all-1.0-my-classifier.my-ext') } def "publish multiproject shadow jar with maven-publish plugin"() { From 413f5e39375bdb7e948c912f5be61a0713a5cf11 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Sun, 2 Apr 2023 04:37:24 +0800 Subject: [PATCH 03/11] Generate an adhoc sw component --- src/docs/publishing/README.md | 4 +- .../plugins/shadow/ShadowExtension.groovy | 71 ++------- .../plugins/shadow/ShadowJavaPlugin.groovy | 51 +++--- .../plugins/shadow/PublishingSpec.groovy | 149 +++++++++++------- .../shadow/util/PluginSpecification.groovy | 7 + 5 files changed, 139 insertions(+), 143 deletions(-) diff --git a/src/docs/publishing/README.md b/src/docs/publishing/README.md index 66da927f0..16c4fb400 100644 --- a/src/docs/publishing/README.md +++ b/src/docs/publishing/README.md @@ -15,8 +15,8 @@ apply plugin: 'com.gradleup.shadow' publishing { publications { - shadow(MavenPublication) { publication -> - project.shadow.component(publication) + shadow(MavenPublication) { + components.shadow } } repositories { diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy index 03a575d54..783ad928c 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy @@ -1,74 +1,23 @@ package com.github.jengelman.gradle.plugins.shadow -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.gradle.api.Project -import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.artifacts.SelfResolvingDependency -import org.gradle.api.file.RegularFile -import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider -import org.gradle.api.publish.maven.MavenPom +import org.gradle.api.component.SoftwareComponentContainer import org.gradle.api.publish.maven.MavenPublication +@Deprecated class ShadowExtension { - private final Provider archive - private final Provider> allDependencies + private final SoftwareComponentContainer components ShadowExtension(Project project) { - archive = project.provider { - def archiveTask = project.tasks.withType(ShadowJar).getByName("shadowJar") - new Archive(archiveTask.archiveFile, archiveTask.archiveClassifier) - } - allDependencies = project.provider { - project.configurations.getByName("shadow").allDependencies.collect { - if ((it instanceof ProjectDependency) || !(it instanceof SelfResolvingDependency)) { - new Dep(it.group, it.name, it.version) - } - } - } + components = project.components } + /** + * @param publication + * @deprecated configure publication using component.shadow directly + */ + @Deprecated void component(MavenPublication publication) { - publication.artifact([ - source : archive.get().file, - classifier: archive.get().classifier.get() - ]) - - // Don't inline this variable, it seems Groovy closure capturing is confused by the field instead of a local variable. - final def allDeps = allDependencies - publication.pom { MavenPom pom -> - pom.withXml { xml -> - def dependenciesNode = xml.asNode().get('dependencies') ?: xml.asNode().appendNode('dependencies') - allDeps.get().each { - def dependencyNode = dependenciesNode.appendNode('dependency') - dependencyNode.appendNode('groupId', it.group) - dependencyNode.appendNode('artifactId', it.name) - dependencyNode.appendNode('version', it.version) - dependencyNode.appendNode('scope', 'runtime') - } - } - } - } - - private class Archive { - Provider file - Property classifier - - Archive(Provider file, Property classifier) { - this.file = file - this.classifier = classifier - } - } - - private class Dep { - String group - String name - String version - - Dep(String group, String name, String version) { - this.group = group - this.name = name - this.version = version - } + publication.from(components.findByName("shadow")) } } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy index d3926974e..9b3aa99e4 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy @@ -8,6 +8,8 @@ import org.gradle.api.attributes.Category import org.gradle.api.attributes.LibraryElements import org.gradle.api.attributes.Usage import org.gradle.api.plugins.JavaPlugin +import org.gradle.api.component.AdhocComponentWithVariants +import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.tasks.SourceSetContainer import org.gradle.configuration.project.ProjectConfigurationActionContainer import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin @@ -19,39 +21,41 @@ class ShadowJavaPlugin implements Plugin { public static final String SHADOW_JAR_TASK_NAME = 'shadowJar' public static final String SHADOW_GROUP = 'Shadow' - private final ProjectConfigurationActionContainer configurationActionContainer + private final SoftwareComponentFactory softwareComponentFactory @Inject - ShadowJavaPlugin(ProjectConfigurationActionContainer configurationActionContainer) { - this.configurationActionContainer = configurationActionContainer + ShadowJavaPlugin(SoftwareComponentFactory softwareComponentFactory) { + this.softwareComponentFactory = softwareComponentFactory } @Override void apply(Project project) { - configureShadowTask(project) + def shadowTask = configureShadowTask(project) project.configurations.compileClasspath.extendsFrom project.configurations.shadow - project.configurations { - shadowRuntimeElements { - canBeConsumed = true - canBeResolved = false - attributes { - it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME)) - it.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) - it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR)) - it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.SHADOWED)) - } - outgoing.artifact(project.tasks.named(SHADOW_JAR_TASK_NAME)) + project.configurations.register("shadowRuntimeElements") { + extendsFrom(project.configurations.shadow) + canBeResolved = false + canBeConsumed = true + attributes { + it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME)) + it.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) + it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR)) + it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.SHADOWED)) } + outgoing.artifact(shadowTask) } - project.configurations.shadowRuntimeElements.extendsFrom project.configurations.shadow + AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") + javaComponent.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + mapToOptional() + } - project.components.java { - addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - mapToOptional() // make it a Maven optional dependency - } + AdhocComponentWithVariants shadow = softwareComponentFactory.adhoc("shadow") + project.components.add(shadow) + shadow.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + mapToMavenScope("runtime") } project.plugins.withType(JavaGradlePluginPlugin).configureEach { @@ -68,9 +72,9 @@ class ShadowJavaPlugin implements Plugin { } } - protected static void configureShadowTask(Project project) { + protected static ShadowJar configureShadowTask(Project project) { SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) - project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> + def taskProvider = project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> shadow.group = SHADOW_GROUP shadow.description = 'Create a combined JAR of project and runtime dependencies' shadow.archiveClassifier.set("all") @@ -91,6 +95,7 @@ class ShadowJavaPlugin implements Plugin { project.configurations.runtimeClasspath : project.configurations.runtime] shadow.exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class') } - project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, project.tasks.named(SHADOW_JAR_TASK_NAME)) + project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, taskProvider.get()) + return taskProvider.get() } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy index 83b6afdfa..82b2f4eba 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy @@ -42,8 +42,8 @@ class PublishingSpec extends PluginSpecification { publishing { publications { - shadow(MavenPublication) { publication -> - project.shadow.component(publication) + shadow(MavenPublication) { + from components.shadow artifactId = 'maven-all' } } @@ -196,8 +196,8 @@ class PublishingSpec extends PluginSpecification { publishing { publications { - shadow(MavenPublication) { publication -> - project.shadow.component(publication) + shadow(MavenPublication) { + from components.shadow artifactId = 'maven-all' } } @@ -255,6 +255,10 @@ class PublishingSpec extends PluginSpecification { java(MavenPublication) { from components.java } + shadow(MavenPublication) { + from components.shadow + artifactId = "maven-all" + } } repositories { maven { @@ -267,59 +271,90 @@ class PublishingSpec extends PluginSpecification { when: run('publish') - then: - File mainJar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.jar').canonicalFile - File shadowJar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0-all.jar').canonicalFile - assert mainJar.exists() - assert shadowJar.exists() - - and: - contains(shadowJar, ['a.properties', 'a2.properties']) - - and: "publishes both a POM file and a Gradle metadata file" - File pom = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.pom').canonicalFile - File gmm = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.module').canonicalFile - pom.exists() - gmm.exists() - - when: "POM file corresponds to a regular Java publication" - def pomContents = new XmlSlurper().parse(pom) - pomContents.dependencies.size() == 2 - - then: - def dependency1 = pomContents.dependencies[0].dependency[0] - dependency1.groupId.text() == 'shadow' - dependency1.artifactId.text() == 'a' - dependency1.version.text() == '1.0' - - def dependency2 = pomContents.dependencies[0].dependency[1] - dependency2.groupId.text() == 'shadow' - dependency2.artifactId.text() == 'b' - dependency2.version.text() == '1.0' - - when: "Gradle module metadata contains the Shadow variants" - def gmmContents = new JsonSlurper().parse(gmm) - - then: - gmmContents.variants.size() == 3 - gmmContents.variants.name as Set == ['apiElements', 'runtimeElements', 'shadowRuntimeElements'] as Set - - def apiVariant = gmmContents.variants.find { it.name == 'apiElements' } - apiVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_API - apiVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL - !apiVariant.dependencies - - def runtimeVariant = gmmContents.variants.find { it.name == 'runtimeElements' } - runtimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME - runtimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL - runtimeVariant.dependencies.size() == 2 - runtimeVariant.dependencies.module as Set == ['a', 'b'] as Set - - def shadowRuntimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } - shadowRuntimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME - shadowRuntimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.SHADOWED - shadowRuntimeVariant.dependencies.size() == 1 - shadowRuntimeVariant.dependencies.module as Set == ['b'] as Set + then: "verify java publication with shadow variant" + assertions { + File jar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.jar').canonicalFile + assert jar.exists() + } + assertions { + File jar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0-all.jar').canonicalFile + assert jar.exists() + contains(jar, ['a.properties', 'a2.properties']) + } + assertions { + File pom = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.pom').canonicalFile + assert pom.exists() + def pomContents = new XmlSlurper().parse(pom) + assert pomContents.dependencies[0].dependency.size() == 2 + + def dependency1 = pomContents.dependencies[0].dependency[0] + assert dependency1.groupId.text() == 'shadow' + assert dependency1.artifactId.text() == 'a' + assert dependency1.version.text() == '1.0' + + def dependency2 = pomContents.dependencies[0].dependency[1] + assert dependency2.groupId.text() == 'shadow' + assert dependency2.artifactId.text() == 'b' + assert dependency2.version.text() == '1.0' + } + + assertions { + File gmm = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.module').canonicalFile + assert gmm.exists() + def gmmContents = new JsonSlurper().parse(gmm) + assert gmmContents.variants.size() == 3 + assert gmmContents.variants.name as Set == ['apiElements', 'runtimeElements', 'shadowRuntimeElements'] as Set + + def apiVariant = gmmContents.variants.find { it.name == 'apiElements' } + assert apiVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_API + assert apiVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL + assert !apiVariant.dependencies + + def runtimeVariant = gmmContents.variants.find { it.name == 'runtimeElements' } + assert runtimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME + assert runtimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL + assert runtimeVariant.dependencies.size() == 2 + assert runtimeVariant.dependencies.module as Set == ['a', 'b'] as Set + + def shadowRuntimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } + assert shadowRuntimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME + assert shadowRuntimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.SHADOWED + assert shadowRuntimeVariant.dependencies.size() == 1 + assert shadowRuntimeVariant.dependencies.module as Set == ['b'] as Set + } + + and: "verify shadow publication" + assertions { + File jar = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0-all.jar').canonicalFile + assert jar.exists() + contains(jar, ['a.properties', 'a2.properties']) + } + + assertions { + File pom = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0.pom').canonicalFile + assert pom.exists() + def pomContents = new XmlSlurper().parse(pom) + assert pomContents.dependencies[0].dependency.size() == 1 + + def dependency1 = pomContents.dependencies[0].dependency[0] + assert dependency1.groupId.text() == 'shadow' + assert dependency1.artifactId.text() == 'b' + assert dependency1.version.text() == '1.0' + } + + assertions { + File gmm = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0.module').canonicalFile + assert gmm.exists() + def gmmContents = new JsonSlurper().parse(gmm) + assert gmmContents.variants.size() == 1 + assert gmmContents.variants.name as Set == ['shadowRuntimeElements'] as Set + + def runtimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } + assert runtimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME + assert runtimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.SHADOWED + assert runtimeVariant.dependencies.size() == 1 + assert runtimeVariant.dependencies.module as Set == ['b'] as Set + } } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy index eb7ffa2fa..5dfde05a9 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy @@ -150,6 +150,13 @@ abstract class PluginSpecification extends Specification { jar.close() } + // Helper method to allow scoping variables into a closure in a spock test + // Prevents variable expansion + // When using this you *must* include explicit `assert` statements as Spock will not do it for you + void assertions(Closure closure) { + closure() + } + AppendableJar buildJar(String path) { return new AppendableJar(file(path)) } From b1af68cc58fcffb3967936fdfb30c7475832fff4 Mon Sep 17 00:00:00 2001 From: Goooler Date: Fri, 13 Sep 2024 15:07:13 +0800 Subject: [PATCH 04/11] Cleanups --- .../gradle/plugins/shadow/ShadowJavaPlugin.groovy | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy index 9b3aa99e4..f34e4f137 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy @@ -11,7 +11,6 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.component.AdhocComponentWithVariants import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.tasks.SourceSetContainer -import org.gradle.configuration.project.ProjectConfigurationActionContainer import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin import javax.inject.Inject @@ -35,27 +34,27 @@ class ShadowJavaPlugin implements Plugin { project.configurations.compileClasspath.extendsFrom project.configurations.shadow project.configurations.register("shadowRuntimeElements") { - extendsFrom(project.configurations.shadow) - canBeResolved = false - canBeConsumed = true - attributes { + it.extendsFrom(project.configurations.shadow) + it.canBeConsumed = true + it.canBeResolved = false + it.attributes { it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME)) it.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR)) it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.SHADOWED)) } - outgoing.artifact(shadowTask) + it.outgoing.artifact(shadowTask) } AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") javaComponent.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - mapToOptional() + it.mapToOptional() } AdhocComponentWithVariants shadow = softwareComponentFactory.adhoc("shadow") project.components.add(shadow) shadow.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - mapToMavenScope("runtime") + it.mapToMavenScope("runtime") } project.plugins.withType(JavaGradlePluginPlugin).configureEach { From ce5a587753879745faf0cad07fd33be00fc47c8f Mon Sep 17 00:00:00 2001 From: Goooler Date: Fri, 13 Sep 2024 15:27:31 +0800 Subject: [PATCH 05/11] Defer more configs --- .../plugins/shadow/ShadowJavaPlugin.groovy | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy index f34e4f137..c37462ce6 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy @@ -11,6 +11,7 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.component.AdhocComponentWithVariants import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskProvider import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin import javax.inject.Inject @@ -29,7 +30,7 @@ class ShadowJavaPlugin implements Plugin { @Override void apply(Project project) { - def shadowTask = configureShadowTask(project) + def shadowTaskProvider = configureShadowTask(project) project.configurations.compileClasspath.extendsFrom project.configurations.shadow @@ -43,12 +44,13 @@ class ShadowJavaPlugin implements Plugin { it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR)) it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.SHADOWED)) } - it.outgoing.artifact(shadowTask) + it.outgoing.artifact(shadowTaskProvider) } - AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") - javaComponent.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - it.mapToOptional() + project.components.named("java") { AdhocComponentWithVariants it -> + it.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + it.mapToOptional() + } } AdhocComponentWithVariants shadow = softwareComponentFactory.adhoc("shadow") @@ -71,7 +73,7 @@ class ShadowJavaPlugin implements Plugin { } } - protected static ShadowJar configureShadowTask(Project project) { + protected static TaskProvider configureShadowTask(Project project) { SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) def taskProvider = project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> shadow.group = SHADOW_GROUP @@ -94,7 +96,7 @@ class ShadowJavaPlugin implements Plugin { project.configurations.runtimeClasspath : project.configurations.runtime] shadow.exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class') } - project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, taskProvider.get()) - return taskProvider.get() + project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, taskProvider) + return taskProvider } } From 9d74601b64dec3c8c7fcc6696fd83fe70ebc3261 Mon Sep 17 00:00:00 2001 From: Goooler Date: Fri, 13 Sep 2024 16:03:19 +0800 Subject: [PATCH 06/11] Note this deprecation --- src/docs/changes/README.md | 2 ++ .../jengelman/gradle/plugins/shadow/ShadowExtension.groovy | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/docs/changes/README.md b/src/docs/changes/README.md index a9dfcd1d3..4e0c062f7 100644 --- a/src/docs/changes/README.md +++ b/src/docs/changes/README.md @@ -7,6 +7,8 @@ **Changed** +- `ShadowExtension.component` has been deprecated, now you can use `component.shadow` instead. + **Fixed** - Stop publishing Shadow self fat jar to Maven repository. ([#967](https://github.com/GradleUp/shadow/pull/967)) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy index 783ad928c..48157f3ba 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy @@ -4,7 +4,6 @@ import org.gradle.api.Project import org.gradle.api.component.SoftwareComponentContainer import org.gradle.api.publish.maven.MavenPublication -@Deprecated class ShadowExtension { private final SoftwareComponentContainer components From 4cbbd4dcf6442bf7853832a38f868957c319115c Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 17 Sep 2024 19:40:05 +0800 Subject: [PATCH 07/11] Revert some defer changes --- .../plugins/shadow/ShadowJavaPlugin.groovy | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy index c37462ce6..f1f2800e4 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy @@ -11,7 +11,6 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.component.AdhocComponentWithVariants import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.tasks.SourceSetContainer -import org.gradle.api.tasks.TaskProvider import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin import javax.inject.Inject @@ -30,26 +29,29 @@ class ShadowJavaPlugin implements Plugin { @Override void apply(Project project) { - def shadowTaskProvider = configureShadowTask(project) + configureShadowTask(project) project.configurations.compileClasspath.extendsFrom project.configurations.shadow - project.configurations.register("shadowRuntimeElements") { - it.extendsFrom(project.configurations.shadow) - it.canBeConsumed = true - it.canBeResolved = false - it.attributes { - it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME)) - it.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) - it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR)) - it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.SHADOWED)) + project.configurations { + shadowRuntimeElements { + canBeConsumed = true + canBeResolved = false + attributes { + it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME)) + it.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) + it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR)) + it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.SHADOWED)) + } + outgoing.artifact(project.tasks.named(SHADOW_JAR_TASK_NAME)) } - it.outgoing.artifact(shadowTaskProvider) } - project.components.named("java") { AdhocComponentWithVariants it -> - it.addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - it.mapToOptional() + project.configurations.shadowRuntimeElements.extendsFrom project.configurations.shadow + + project.components.java { + addVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { + mapToOptional() // make it a Maven optional dependency } } @@ -73,9 +75,9 @@ class ShadowJavaPlugin implements Plugin { } } - protected static TaskProvider configureShadowTask(Project project) { + protected static void configureShadowTask(Project project) { SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) - def taskProvider = project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> + project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> shadow.group = SHADOW_GROUP shadow.description = 'Create a combined JAR of project and runtime dependencies' shadow.archiveClassifier.set("all") @@ -96,7 +98,6 @@ class ShadowJavaPlugin implements Plugin { project.configurations.runtimeClasspath : project.configurations.runtime] shadow.exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class') } - project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, taskProvider) - return taskProvider + project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, project.tasks.named(SHADOW_JAR_TASK_NAME)) } } From 800e5331db657da52d8c9680df9f12b59b1e3fc6 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 17 Sep 2024 20:18:46 +0800 Subject: [PATCH 08/11] Tweak tests and revert styles changes --- .../plugins/shadow/PublishingSpec.groovy | 123 ++++++++++-------- .../shadow/util/PluginSpecification.groovy | 8 +- 2 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy index 82b2f4eba..5ae26c1b3 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy @@ -79,7 +79,10 @@ class PublishingSpec extends PluginSpecification { assert dependency.version.text() == '1.0' } - @Issue(["https://github.com/GradleUp/shadow/issues/860", "https://github.com/GradleUp/shadow/issues/945"]) + @Issue([ + "https://github.com/GradleUp/shadow/issues/860", + "https://github.com/GradleUp/shadow/issues/945", + ]) def "publish shadow jar with maven-publish plugin using custom classifier and extension"() { given: repo.module('shadow', 'a', '1.0') @@ -271,90 +274,96 @@ class PublishingSpec extends PluginSpecification { when: run('publish') - then: "verify java publication with shadow variant" - assertions { - File jar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.jar').canonicalFile - assert jar.exists() - } - assertions { - File jar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0-all.jar').canonicalFile - assert jar.exists() - contains(jar, ['a.properties', 'a2.properties']) - } - assertions { - File pom = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.pom').canonicalFile - assert pom.exists() - def pomContents = new XmlSlurper().parse(pom) - assert pomContents.dependencies[0].dependency.size() == 2 + then: + File mainJar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.jar').canonicalFile + File shadowJar = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0-all.jar').canonicalFile + assert mainJar.exists() + assert shadowJar.exists() - def dependency1 = pomContents.dependencies[0].dependency[0] - assert dependency1.groupId.text() == 'shadow' - assert dependency1.artifactId.text() == 'a' - assert dependency1.version.text() == '1.0' + and: + contains(shadowJar, ['a.properties', 'a2.properties']) - def dependency2 = pomContents.dependencies[0].dependency[1] - assert dependency2.groupId.text() == 'shadow' - assert dependency2.artifactId.text() == 'b' - assert dependency2.version.text() == '1.0' - } + and: "publishes both a POM file and a Gradle metadata file" + File pom = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.pom').canonicalFile + File gmm = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.module').canonicalFile + pom.exists() + gmm.exists() - assertions { - File gmm = publishingRepo.rootDir.file('com/acme/maven/1.0/maven-1.0.module').canonicalFile - assert gmm.exists() - def gmmContents = new JsonSlurper().parse(gmm) - assert gmmContents.variants.size() == 3 - assert gmmContents.variants.name as Set == ['apiElements', 'runtimeElements', 'shadowRuntimeElements'] as Set + when: "POM file corresponds to a regular Java publication" + def pomContents = new XmlSlurper().parse(pom) + pomContents.dependencies.size() == 2 - def apiVariant = gmmContents.variants.find { it.name == 'apiElements' } - assert apiVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_API - assert apiVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL - assert !apiVariant.dependencies + then: + def dependency1 = pomContents.dependencies[0].dependency[0] + dependency1.groupId.text() == 'shadow' + dependency1.artifactId.text() == 'a' + dependency1.version.text() == '1.0' - def runtimeVariant = gmmContents.variants.find { it.name == 'runtimeElements' } - assert runtimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME - assert runtimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL - assert runtimeVariant.dependencies.size() == 2 - assert runtimeVariant.dependencies.module as Set == ['a', 'b'] as Set - - def shadowRuntimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } - assert shadowRuntimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME - assert shadowRuntimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.SHADOWED - assert shadowRuntimeVariant.dependencies.size() == 1 - assert shadowRuntimeVariant.dependencies.module as Set == ['b'] as Set - } + def dependency2 = pomContents.dependencies[0].dependency[1] + dependency2.groupId.text() == 'shadow' + dependency2.artifactId.text() == 'b' + dependency2.version.text() == '1.0' + + when: "Gradle module metadata contains the Shadow variants" + def gmmContents = new JsonSlurper().parse(gmm) + + then: + gmmContents.variants.size() == 3 + gmmContents.variants.name as Set == ['apiElements', 'runtimeElements', 'shadowRuntimeElements'] as Set + + def apiVariant = gmmContents.variants.find { it.name == 'apiElements' } + apiVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_API + apiVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL + !apiVariant.dependencies + + def runtimeVariant = gmmContents.variants.find { it.name == 'runtimeElements' } + runtimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME + runtimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.EXTERNAL + runtimeVariant.dependencies.size() == 2 + runtimeVariant.dependencies.module as Set == ['a', 'b'] as Set + + def shadowRuntimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } + shadowRuntimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME + shadowRuntimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.SHADOWED + shadowRuntimeVariant.dependencies.size() == 1 + shadowRuntimeVariant.dependencies.module as Set == ['b'] as Set and: "verify shadow publication" assertions { - File jar = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0-all.jar').canonicalFile - assert jar.exists() - contains(jar, ['a.properties', 'a2.properties']) + shadowJar = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0-all.jar').canonicalFile + assert shadowJar.exists() + contains(shadowJar, ['a.properties', 'a2.properties']) } assertions { - File pom = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0.pom').canonicalFile + pom = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0.pom').canonicalFile assert pom.exists() - def pomContents = new XmlSlurper().parse(pom) + pomContents = new XmlSlurper().parse(pom) assert pomContents.dependencies[0].dependency.size() == 1 - def dependency1 = pomContents.dependencies[0].dependency[0] + dependency1 = pomContents.dependencies[0].dependency[0] assert dependency1.groupId.text() == 'shadow' assert dependency1.artifactId.text() == 'b' assert dependency1.version.text() == '1.0' + + dependency2 = pomContents.dependencies[0].dependency[1] + dependency2.groupId.text() == 'shadow' + dependency2.artifactId.text() == 'b' + dependency2.version.text() == '1.0' } assertions { - File gmm = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0.module').canonicalFile + gmm = publishingRepo.rootDir.file('com/acme/maven-all/1.0/maven-all-1.0.module').canonicalFile assert gmm.exists() - def gmmContents = new JsonSlurper().parse(gmm) + gmmContents = new JsonSlurper().parse(gmm) assert gmmContents.variants.size() == 1 assert gmmContents.variants.name as Set == ['shadowRuntimeElements'] as Set - def runtimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } + runtimeVariant = gmmContents.variants.find { it.name == 'shadowRuntimeElements' } assert runtimeVariant.attributes[Usage.USAGE_ATTRIBUTE.name] == Usage.JAVA_RUNTIME assert runtimeVariant.attributes[Bundling.BUNDLING_ATTRIBUTE.name] == Bundling.SHADOWED assert runtimeVariant.dependencies.size() == 1 assert runtimeVariant.dependencies.module as Set == ['b'] as Set } - } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy index 5dfde05a9..9e5fc66f4 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy @@ -150,9 +150,11 @@ abstract class PluginSpecification extends Specification { jar.close() } - // Helper method to allow scoping variables into a closure in a spock test - // Prevents variable expansion - // When using this you *must* include explicit `assert` statements as Spock will not do it for you + /** + * Helper method to allow scoping variables into a closure in a spock test + * Prevents variable expansion + * When using this you *must* include explicit `assert` statements as Spock will not do it for you + */ void assertions(Closure closure) { closure() } From 54cb4d13b604d2b450dc5d11e5cd3ee7769fd94e Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 17 Sep 2024 20:31:15 +0800 Subject: [PATCH 09/11] Still mark ShadowExtension Deprecated --- .../jengelman/gradle/plugins/shadow/ShadowExtension.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy index 48157f3ba..53fc8b38d 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy @@ -4,6 +4,7 @@ import org.gradle.api.Project import org.gradle.api.component.SoftwareComponentContainer import org.gradle.api.publish.maven.MavenPublication +@Deprecated class ShadowExtension { private final SoftwareComponentContainer components @@ -12,8 +13,7 @@ class ShadowExtension { } /** - * @param publication - * @deprecated configure publication using component.shadow directly + * @deprecated configure publication using component.shadow directly. */ @Deprecated void component(MavenPublication publication) { From 6bc0b34af868392e6d7db76a006426185301d450 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 17 Sep 2024 20:35:39 +0800 Subject: [PATCH 10/11] Note PR link --- src/docs/changes/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/changes/README.md b/src/docs/changes/README.md index 4e0c062f7..6d38e2b34 100644 --- a/src/docs/changes/README.md +++ b/src/docs/changes/README.md @@ -7,7 +7,7 @@ **Changed** -- `ShadowExtension.component` has been deprecated, now you can use `component.shadow` instead. +- `ShadowExtension.component` has been deprecated, now you can use `component.shadow` instead. ([#956](https://github.com/GradleUp/shadow/pull/956)) **Fixed** From dc4f895aed316c6d7777037579e7728aef43a77c Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 17 Sep 2024 20:39:17 +0800 Subject: [PATCH 11/11] Revert debugging --- .../jengelman/gradle/plugins/shadow/PublishingSpec.groovy | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy index 5ae26c1b3..bc6221a1b 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/PublishingSpec.groovy @@ -127,11 +127,8 @@ class PublishingSpec extends PluginSpecification { run('publish') then: - def publishedFiles = publishingRepo.rootDir.file('shadow/maven-all/1.0/').canonicalFile - .listFiles() - .findAll { it.exists() } - .collect { it.name } - assert publishedFiles.contains('maven-all-1.0-my-classifier.my-ext') + File publishedFile = publishingRepo.rootDir.file('shadow/maven-all/1.0/maven-all-1.0-my-classifier.my-ext').canonicalFile + assert publishedFile.exists() } def "publish multiproject shadow jar with maven-publish plugin"() {