Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework excluding Gradle APIs for java-gradle-plugin #948

Merged
merged 9 commits into from
Aug 31, 2024
7 changes: 0 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,6 @@ tasks.withType(Test).configureEach {
)
}

// Remove the gradleApi so it isn't merged into the jar file.
// This is required because 'java-gradle-plugin' adds gradleApi() to the 'api' configuration.
// See https://github.com/gradle/gradle/blob/972c3e5c6ef990dd2190769c1ce31998a9402a79/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/JavaGradlePluginPlugin.java#L161
configurations.named(JavaPlugin.API_CONFIGURATION_NAME) {
dependencies.remove(project.dependencies.gradleApi())
}

tasks.named('shadowJar', ShadowJar) {
from rootProject.file('LICENSE')
from rootProject.file('NOTICE')
Expand Down
1 change: 0 additions & 1 deletion gradle/dependencies.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
dependencies {
compileOnly localGroovy()
compileOnly gradleApi()
shadow 'org.codehaus.groovy:groovy-backports-compat23:3.0.8'

implementation 'org.jdom:jdom2:2.0.6.1'
Expand Down
4 changes: 1 addition & 3 deletions src/docs/configuration/relocation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,4 @@ In versions before 8.1.0 it was necessary to configure a separate `ConfigureShad
> Configuring package auto relocation can add significant time to the shadow process as it will process all dependencies
in the configurations declared to be shadowed. By default, this is the `runtime` or `runtimeClasspath` configurations.
Be mindful that some Gradle plugins will automatically add dependencies to your class path. You may need to remove these
dependencies if you do not intend to shadow them into your library. The `java-gradle-plugin` would normally cause such
problems if it were not for the special handling that Shadow provides as described in
[Special Handling of the Java Gradle Plugin Development Plugin](/plugins/#special-handling-of-the-java-gradle-plugin-gevelopmeny-plugin).
dependencies if you do not intend to shadow them into your library.
10 changes: 0 additions & 10 deletions src/docs/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,6 @@ Starting with this version, plugin projects that apply both Shadow and the Gradl
automatically configured to publish the output of the `shadowJar` tasks as the consumable artifact for the plugin.
See the [Gradle Plugin Publish docs](https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#shadow_dependencies) for details.

## Special Handling of the Java Gradle Plugin Development Plugin

The Java Gradle Plugin Development plugin, `java-gradle-plugin`, automatically adds the full Gradle API to the `compile`
configuration; thus overriding a possible assignment of `gradleApi()` to the `shadow` configuration. Since it is never
a good idea to include the Gradle API when creating a Gradle plugin, the dependency is removed so that it is not
included in the resultant shadow jar. Virtually:

// needed to prevent inclusion of gradle-api into shadow JAR
configurations.compile.dependencies.remove dependencies.gradleApi()

## Automatic package relocation with Shadow prior to v8.1.0

Prior to Shadow v8.1.0, Shadow handled this by introducing a new task type `ConfigureShadowRelocation`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import org.gradle.api.attributes.Bundling
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.tasks.SourceSetContainer
import org.gradle.configuration.project.ProjectConfigurationActionContainer
import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin

import javax.inject.Inject

Expand Down Expand Up @@ -51,6 +53,19 @@ class ShadowJavaPlugin implements Plugin<Project> {
mapToOptional() // make it a Maven optional dependency
}
}

project.plugins.withType(JavaGradlePluginPlugin).configureEach {
// Remove the gradleApi so it isn't merged into the jar file.
// This is required because 'java-gradle-plugin' adds gradleApi() to the 'api' configuration.
// See https://github.com/gradle/gradle/blob/972c3e5c6ef990dd2190769c1ce31998a9402a79/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/JavaGradlePluginPlugin.java#L161
project.configurations.named(JavaPlugin.API_CONFIGURATION_NAME) {
it.dependencies.remove(project.dependencies.gradleApi())
}
// Compile only gradleApi() to make sure the plugin can compile against Gradle API.
project.configurations.named(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME) {
it.dependencies.add(project.dependencies.gradleApi())
}
}
}

protected static void configureShadowTask(Project project) {
Expand All @@ -75,9 +90,6 @@ class ShadowJavaPlugin implements Plugin<Project> {
shadow.configurations = [project.configurations.findByName('runtimeClasspath') ?
project.configurations.runtimeClasspath : project.configurations.runtime]
shadow.exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class')
shadow.dependencies {
exclude(dependency(project.dependencies.gradleApi()))
}
}
project.artifacts.add(ShadowBasePlugin.CONFIGURATION_NAME, project.tasks.named(SHADOW_JAR_TASK_NAME))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,36 @@ class ShadowPluginSpec extends PluginSpecification {
assert result.output.contains('TestApp: Hello World! (foo)')
}

@Issue("https://github.com/GradleUp/shadow/pull/459")
def 'exclude gradleApi() by default'() {
given:
buildFile.text = getDefaultBuildScript('java-gradle-plugin')

file('src/main/java/my/plugin/MyPlugin.java') << """
package my.plugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class MyPlugin implements Plugin<Project> {
public void apply(Project project) {
System.out.println("MyPlugin: Hello World!");
}
}
""".stripIndent()
file('src/main/resources/META-INF/gradle-plugins/my.plugin.properties') << """
implementation-class=my.plugin.MyPlugin
""".stripIndent()

when:
run('shadowJar')

then:
assert output.exists()

and:
JarFile jar = new JarFile(output)
assert jar.entries().collect().findAll { it.name.endsWith('.class') }.size() == 1
}

private String escapedPath(File file) {
file.path.replaceAll('\\\\', '\\\\\\\\')
}
Expand Down