Skip to content

Commit

Permalink
Document convention plugins created so far
Browse files Browse the repository at this point in the history
RELNOTES=N/A
PiperOrigin-RevId: 720570889
  • Loading branch information
danysantiago authored and Dagger Team committed Jan 28, 2025
1 parent ae67d23 commit 8263805
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,53 @@ import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.gradle.jvm.toolchain.JavaLanguageVersion

/**
* A convention plugin that sets the default configuration for JVM (Kotlin + Java) projects in
* Dagger's codebase. Individual libraries can override these conventions if necessary.
*
* This plugin can be applied using:
* ```
* plugins {
* alias(libs.plugins.dagger.kotlinJvm)
* }
* ```
*
* Source sets for the project should be configured using the `daggerSources` extension:
* ```
* daggerSources {
* main.setPackages(
* listOf("dagger", "dagger/internal")
* )
* main.setResources(
* mapOf("dagger/r8.pro" to "META-INF/com.android.tools/r8")
* )
* test.setPackages(
* listOf("dagger", "dagger/internal")
* )
* }
* ```
*/
class KotlinJvmConventionPlugin : Plugin<Project> {

override fun apply(project: Project) {
project.pluginManager.apply(project.getPluginIdByName("kotlinJvm"))

project.plugins.withId(project.getPluginIdByName("kotlinJvm")) {
val kotlinProject = project.extensions.getByName("kotlin") as KotlinJvmProjectExtension
kotlinProject.jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(project.getVersionByName("jdk")))
}
kotlinProject.compilerOptions.apply {
languageVersion.set(KotlinVersion.fromVersion(project.getVersionByName("kotlinTarget")))
apiVersion.set(KotlinVersion.fromVersion(project.getVersionByName("kotlinTarget")))
jvmTarget.set(JvmTarget.fromTarget(project.getVersionByName("jvmTarget")))
}

val javaProject = project.extensions.getByName("java") as JavaPluginExtension
javaProject.sourceCompatibility = JavaVersion.toVersion(project.getVersionByName("jvmTarget"))
javaProject.targetCompatibility = JavaVersion.toVersion(project.getVersionByName("jvmTarget"))
}
override fun apply(project: Project) {
project.pluginManager.apply(project.getPluginIdByName("kotlinJvm"))
project.plugins.withId(project.getPluginIdByName("kotlinJvm")) {
val kotlinProject = project.extensions.getByName("kotlin") as KotlinJvmProjectExtension
kotlinProject.jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(project.getVersionByName("jdk")))
}
kotlinProject.compilerOptions.apply {
languageVersion.set(KotlinVersion.fromVersion(project.getVersionByName("kotlinTarget")))
apiVersion.set(KotlinVersion.fromVersion(project.getVersionByName("kotlinTarget")))
jvmTarget.set(JvmTarget.fromTarget(project.getVersionByName("jvmTarget")))
}
val javaProject = project.extensions.getByName("java") as JavaPluginExtension
javaProject.sourceCompatibility = JavaVersion.toVersion(project.getVersionByName("jvmTarget"))
javaProject.targetCompatibility = JavaVersion.toVersion(project.getVersionByName("jvmTarget"))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,53 +21,66 @@ import com.vanniktech.maven.publish.SonatypeHost
import org.gradle.api.Plugin
import org.gradle.api.Project

/**
* A convention plugin that sets the default configuration for published projects in Dagger's
* codebase. The plugin configures the POM information of Maven artifacts to publish and the name of
* the project is used as artifact id.
*
* This plugin can be applied using:
* ```
* plugins {
* alias(libs.plugins.dagger.publish)
* }
* ```
*/
class PublishConventionPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply(project.getPluginIdByName("publish"))
override fun apply(project: Project) {
project.pluginManager.apply(project.getPluginIdByName("publish"))

project.plugins.withId(project.getPluginIdByName("publish")) {
val publishExtension = project.extensions.getByName("mavenPublishing") as MavenPublishBaseExtension
publishExtension.apply {
coordinates(
groupId = "com.google.dagger",
artifactId = project.name,
version = project.findProperty("PUBLISH_VERSION").toString()
)
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
pom {
name.set(project.name.asPomName())
description.set("A fast dependency injector for Android and Java.")
url.set("https://github.com/google/dagger")
scm {
url.set("https://github.com/google/dagger/")
connection.set("scm:git:git://github.com/google/dagger.git")
}
issueManagement {
system.set("GitHub Issues")
url.set("https://github.com/google/dagger/issues")
}
licenses {
license {
name.set("The Apache Software License, Version 2.0")
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
organization {
name.set("Google, Inc.")
url.set("https://www.google.com")
}
}
project.plugins.withId(project.getPluginIdByName("publish")) {
val publishExtension =
project.extensions.getByName("mavenPublishing") as MavenPublishBaseExtension
publishExtension.apply {
coordinates(
groupId = "com.google.dagger",
artifactId = project.name,
version = project.findProperty("PUBLISH_VERSION").toString(),
)
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
pom {
name.set(project.name.asPomName())
description.set("A fast dependency injector for Android and Java.")
url.set("https://github.com/google/dagger")
scm {
url.set("https://github.com/google/dagger/")
connection.set("scm:git:git://github.com/google/dagger.git")
}
issueManagement {
system.set("GitHub Issues")
url.set("https://github.com/google/dagger/issues")
}
licenses {
license {
name.set("The Apache Software License, Version 2.0")
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
organization {
name.set("Google, Inc.")
url.set("https://www.google.com")
}
}
}
}
}

/**
* Converts the Gradle project name to a more appropriate name for the POM file.
*
* For example: 'dagger-compiler' to 'Dagger Compiler'
*/
private fun String.asPomName(): String {
val parts = split("-").map { first().uppercaseChar() + drop(1) }
return parts.joinToString(separator = " ")
}
}
/**
* Converts the Gradle project name to a more appropriate name for the POM file.
*
* For example: 'dagger-compiler' to 'Dagger Compiler'
*/
private fun String.asPomName(): String {
val parts = split("-").map { first().uppercaseChar() + drop(1) }
return parts.joinToString(separator = " ")
}
}
127 changes: 74 additions & 53 deletions buildSrc/src/main/kotlin/dagger/gradle/build/ShadowConventionPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,70 +24,91 @@ import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.withType

/**
* A convention plugin that sets the default configurations for projects with shading (also know as
* jarjaring or shadowing) in Dagger's codebase.
*
* This plugin can be applied using:
* ```
* plugins {
* alias(libs.plugins.dagger.shadow)
* }
* ```
*
* Shaded dependencies are specify via a configuration created by the plugin:
* ```
* dependencies {
* shaded(libs.auto.common)
* }
* ```
*
* Relocation rules can be specify via an extension created by the plugin:
* ```
* shading {
* relocate("com.google.auto.common", "dagger.spi.internal.shaded.auto.common")
* }
* ```
*/
class ShadowConventionPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply(project.getPluginIdByName("shadow"))
override fun apply(project: Project) {
project.pluginManager.apply(project.getPluginIdByName("shadow"))

val shadeExtension = project.extensions.create<ShadeExtension>("shading")
val shadeExtension = project.extensions.create<ShadeExtension>("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
}
// 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) }
// Shaded dependencies are compile only dependencies
project.configurations.named("compileOnly").configure { extendsFrom(shadedConfiguration) }

val shadowTask = project.tasks.withType<ShadowJar>().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
val shadowTask =
project.tasks.withType<ShadowJar>().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)
}
}
shadeExtension.rules.forEach { (from, to) -> relocate(from, to) }
}

// Change the default jar task classifier to avoid conflicting with the shaded one.
project.tasks.withType<Jar>().named("jar").configure {
archiveClassifier.set("before-shade")
}
// Change the default jar task classifier to avoid conflicting with the shaded one.
project.tasks.withType<Jar>().named("jar").configure { archiveClassifier.set("before-shade") }

configureOutgoingArtifacts(project, shadowTask)
}
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<ShadowJar>) {
project.configurations.configureEach {
if (name == "apiElements" || name == "runtimeElements") {
outgoing.artifacts.clear()
outgoing.artifact(task)
}
}
/**
* 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<ShadowJar>) {
project.configurations.configureEach {
if (name == "apiElements" || name == "runtimeElements") {
outgoing.artifacts.clear()
outgoing.artifact(task)
}
}
}
}

abstract class ShadeExtension {
internal val rules = mutableMapOf<String, String>()
internal val rules = mutableMapOf<String, String>()

fun relocate(fromPackage: String, toPackage: String) {
check(!rules.containsKey(fromPackage)) {
"Duplicate shading rule declared for $fromPackage"
}
rules[fromPackage] = toPackage
}
}
fun relocate(fromPackage: String, toPackage: String) {
check(!rules.containsKey(fromPackage)) { "Duplicate shading rule declared for $fromPackage" }
rules[fromPackage] = toPackage
}
}

0 comments on commit 8263805

Please sign in to comment.