From e256cbdae771130565d519843d64f7656bd77989 Mon Sep 17 00:00:00 2001 From: Daniel Santiago Date: Thu, 16 Jan 2025 11:27:25 -0800 Subject: [PATCH] Add shading configurations to dagger-spi and dagger-compiler Currently with the Bazel build kotlin-metadata-jvm is shaded but this is no longer necessary since the move from the kotlinx package and to a stable standard library. RELNOTES=N/A PiperOrigin-RevId: 716311985 --- buildSrc/build.gradle.kts | 15 ++- .../gradle/build/ShadowConventionPlugin.kt | 93 +++++++++++++++++++ .../dagger-compiler/build.gradle.kts | 20 ++-- gradle-projects/dagger-spi/build.gradle.kts | 28 ++++-- gradle/libs.versions.toml | 4 + 5 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 buildSrc/src/main/kotlin/dagger/gradle/build/ShadowConventionPlugin.kt diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 66dc027da2e..d48951f2778 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { implementation(gradleApi()) implementation(libs.kotlin.gradlePlugin) implementation(libs.publishPlugin) + implementation(libs.shadowPlugin) } gradlePlugin { @@ -22,9 +23,15 @@ gradlePlugin { } } plugins { - register("publish") { - id = libs.plugins.dagger.publish.get().pluginId - implementationClass = "dagger.gradle.build.PublishConventionPlugin" - } + register("publish") { + id = libs.plugins.dagger.publish.get().pluginId + implementationClass = "dagger.gradle.build.PublishConventionPlugin" + } + } + plugins { + register("shadow") { + id = libs.plugins.dagger.shadow.get().pluginId + implementationClass = "dagger.gradle.build.ShadowConventionPlugin" + } } } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/dagger/gradle/build/ShadowConventionPlugin.kt b/buildSrc/src/main/kotlin/dagger/gradle/build/ShadowConventionPlugin.kt new file mode 100644 index 00000000000..5c975e49c93 --- /dev/null +++ b/buildSrc/src/main/kotlin/dagger/gradle/build/ShadowConventionPlugin.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2025 The Dagger Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dagger.gradle.build + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.TaskProvider +import org.gradle.jvm.tasks.Jar +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.withType + +class ShadowConventionPlugin : Plugin { + override fun apply(project: Project) { + project.pluginManager.apply(project.getPluginIdByName("shadow")) + + val shadeExtension = project.extensions.create("shading") + + // Configuration for shaded dependencies + val shadedConfiguration = project.configurations.create("shaded") { + isCanBeConsumed = false + isCanBeResolved = true + isTransitive = false // Do not include transitive dependencies of shaded deps + } + + // Shaded dependencies are compile only dependencies + project.configurations.named("compileOnly").configure { extendsFrom(shadedConfiguration) } + + val shadowTask = project.tasks.withType().named("shadowJar") { + // Use no classifier, the shaded jar is the one to be published. + archiveClassifier.set("") + // Set the 'shaded' configuration as the dependencies configuration to shade + configurations = listOf(shadedConfiguration) + // Enable service files merging + mergeServiceFiles() + // Enable package relocation (necessary for project that only relocate but have no + // shaded deps) + isEnableRelocation = true + + shadeExtension.rules.forEach { (from, to) -> + relocate(from, to) + } + } + + // Change the default jar task classifier to avoid conflicting with the shaded one. + project.tasks.withType().named("jar").configure { + archiveClassifier.set("before-shade") + } + + configureOutgoingArtifacts(project, shadowTask) + } + + /** + * Configure Gradle consumers (that use Gradle publishing metadata) of the project to use the + * shaded jar. + * + * This is necessary so that the publishing Gradle module metadata references the shaded jar. + * See https://github.com/GradleUp/shadow/issues/847 + */ + private fun configureOutgoingArtifacts(project: Project, task: TaskProvider) { + project.configurations.configureEach { + if (name == "apiElements" || name == "runtimeElements") { + outgoing.artifacts.clear() + outgoing.artifact(task) + } + } + } +} + +abstract class ShadeExtension { + internal val rules = mutableMapOf() + + fun relocate(fromPackage: String, toPackage: String) { + check(!rules.containsKey(fromPackage)) { + "Duplicate shading rule declared for $fromPackage" + } + rules[fromPackage] = toPackage + } +} \ No newline at end of file diff --git a/gradle-projects/dagger-compiler/build.gradle.kts b/gradle-projects/dagger-compiler/build.gradle.kts index 6cb0ba0ce94..483546a0232 100644 --- a/gradle-projects/dagger-compiler/build.gradle.kts +++ b/gradle-projects/dagger-compiler/build.gradle.kts @@ -3,6 +3,7 @@ import dagger.gradle.build.daggerSources plugins { alias(libs.plugins.dagger.kotlinJvm) alias(libs.plugins.dagger.publish) + alias(libs.plugins.dagger.shadow) } daggerSources { @@ -30,7 +31,6 @@ dependencies { implementation(project(":dagger")) implementation(project(":dagger-spi")) - implementation(libs.auto.common) implementation(libs.auto.value.annotations) annotationProcessor(libs.auto.value.compiler) implementation(libs.auto.service.annotations) @@ -51,12 +51,20 @@ dependencies { annotationProcessor( files(project.rootProject.layout.projectDirectory - .dir("java/dagger/internal/codegen/bootstrap") - .file("bootstrap_compiler_deploy.jar")) + .dir("java/dagger/internal/codegen/bootstrap") + .file("bootstrap_compiler_deploy.jar")) ) - implementation( + + // These dependencies are shaded into dagger-spi + compileOnly(libs.auto.common) + compileOnly( files(project.rootProject.layout.projectDirectory - .dir("java/dagger/internal/codegen/xprocessing") - .file("xprocessing.jar")) + .dir("java/dagger/internal/codegen/xprocessing") + .file("xprocessing.jar")) ) +} + +shading { + relocate("com.google.auto.common", "dagger.spi.internal.shaded.auto.common") + relocate("androidx.room", "dagger.spi.internal.shaded.androidx.room") } \ No newline at end of file diff --git a/gradle-projects/dagger-spi/build.gradle.kts b/gradle-projects/dagger-spi/build.gradle.kts index 38fde9b5429..8e39dcfe8a4 100644 --- a/gradle-projects/dagger-spi/build.gradle.kts +++ b/gradle-projects/dagger-spi/build.gradle.kts @@ -3,6 +3,7 @@ import dagger.gradle.build.daggerSources plugins { alias(libs.plugins.dagger.kotlinJvm) alias(libs.plugins.dagger.publish) + alias(libs.plugins.dagger.shadow) } daggerSources { @@ -16,17 +17,30 @@ daggerSources { ) } -// TODO(danysantiago): Shadow / jarjar: 1. xprocessing, 2. auto-common and 3. kotlin-metadata-jvm dependencies { implementation(project(":dagger")) - implementation(libs.auto.common) + implementation(libs.findBugs) implementation(libs.auto.value.annotations) annotationProcessor(libs.auto.value.compiler) - implementation(libs.findBugs) - implementation(libs.javaPoet) - implementation(libs.javax.inject) + implementation(libs.ksp.api) implementation(libs.guava.failureAccess) implementation(libs.guava.jre) - implementation(libs.ksp.api) -} \ No newline at end of file + implementation(libs.javaPoet) + implementation(libs.javax.inject) + + // These dependencies will be shaded (included) within the artifact of this project and are + // shared with other processors, such as dagger-compiler. + val shaded by configurations.getting + shaded(libs.auto.common) + shaded( + files(project.rootProject.layout.projectDirectory + .dir("java/dagger/internal/codegen/xprocessing") + .file("xprocessing.jar")) + ) +} + +shading { + relocate("com.google.auto.common", "dagger.spi.internal.shaded.auto.common") + relocate("androidx.room", "dagger.spi.internal.shaded.androidx.room") +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8f687aa9643..00025bbbdaa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,6 +10,7 @@ kotlin = "2.0.21" kotlinTarget = "1.9" ksp = "2.0.21-1.0.28" publish = "0.30.0" +shadow = "8.3.5" truth = "1.4.0" [libraries] @@ -37,10 +38,13 @@ kotlinPoet = { module = "com.squareup:kotlinpoet", version = "1.11.0" } ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } publishPlugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "publish" } truth = { module = "com.google.truth:truth", version.ref = "truth" } +shadowPlugin = { module = "com.gradleup.shadow:shadow-gradle-plugin", version.ref = "shadow" } [plugins] binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.17.0" } dagger-kotlinJvm = { id = "dagger.gradle.build.jvm" } dagger-publish = { id = "dagger.gradle.build.publish" } +dagger-shadow = { id = "dagger.gradle.build.shadow" } kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } publish = { id = "com.vanniktech.maven.publish", version.ref = "publish" } +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }