89 lines
3.7 KiB
Markdown
89 lines
3.7 KiB
Markdown
---
|
|
title: Gradle Goodness - Shared Configuration With Conventions Plugin
|
|
source: https://blog.jdriven.com/2021/02/gradle-goodness-shared-configuration-with-conventions-plugin/
|
|
tags:
|
|
- IT/Development/Gradle
|
|
- IT/Development/Kotlin
|
|
- IT/Development/Groovy
|
|
---
|
|
|
|
When we have a multi-module project in Gradle we sometimes want to have dependencies, task configuration and other settings shared between the multiple modules. We can use the `subprojects` or `allprojects` blocks, but the downside is that it is not clear from the build script of the subproject where the configuration comes from. We must remember it is set from another build script, but there is no reference in the subproject to that connection. It is better to use a plugin with shared configuration and use that plugin in the subprojects. We call this a conventions plugin. This way it is explicitly visible in a subproject that the shared settings come from a plugin. Also it allows Gradle to optimize the build configuration.
|
|
|
|
The easiest way to implement the shared configuration in a plugin is using a so-called precompiled script plugin. This type of plugin can be written as a build script using the Groovy or Kotlin DSL with a filename ending with `.gradle` or `.gradle.kts`. The name of the plugin is the first part of the filename before `.gradle` or `.gradle.kts`. In our subproject we can add the plugin to our build script to apply the shared configuration. For a multi-module project we can create such a plugin in the `buildSrc` directory. For a Groovy plugin we place the file in `src/main/groovy`, for a Kotlin plugin we place it in `src/main/kotlin`.
|
|
|
|
In the following example we write a script plugin using the Kotlin DSL to apply the `java-library` plugin to a project, set some common dependencies used by all projects, configure the `Test` tasks and set the Java toolchain. First we create a `build.gradle.kts` file in the `buildSrc` directory in the root of our multi-module project and apply the `kotlin-dsl` plugin:
|
|
|
|
```kotlin
|
|
// File: buildSrc/build.gradle.kts
|
|
plugins {
|
|
`kotlin-dsl`
|
|
}
|
|
|
|
repositories.mavenCentral()
|
|
```
|
|
|
|
Next we create the conventions plugin with our shared configuration:
|
|
|
|
```kotlin
|
|
// File: buildSrc/src/main/kotlin/java-project-conventions.gradle.kts
|
|
plugins {
|
|
`java-library`
|
|
}
|
|
|
|
group = "mrhaki.sample"
|
|
version = "1.0"
|
|
|
|
repositories {
|
|
mavenCentral()
|
|
}
|
|
|
|
dependencies {
|
|
val log4jVersion: String by extra("2.14.0")
|
|
val junitVersion: String by extra("5.3.1")
|
|
val assertjVersion: String by extra("3.19.0")
|
|
|
|
// Logging
|
|
implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}")
|
|
implementation("org.apache.logging.log4j:log4j-core:${log4jVersion}")
|
|
|
|
// Testing
|
|
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
|
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
|
|
testImplementation("org.assertj:assertj-core:${assertjVersion}")
|
|
}
|
|
|
|
java {
|
|
toolchain {
|
|
languageVersion.set(JavaLanguageVersion.of(15))
|
|
}
|
|
}
|
|
|
|
tasks.withType<Test> {
|
|
useJUnitPlatform()
|
|
}
|
|
```
|
|
|
|
The id of our new plugin is `java-project-conventions` and we can use it in our build script for a subproject as:
|
|
|
|
```kotlin
|
|
// File: rest-api/build.gradle.kts
|
|
plugins {
|
|
id("java-project-conventions") // apply shared config
|
|
application // apply the Gradle application plugin
|
|
}
|
|
|
|
dependencies {
|
|
val vertxVersion: String by extra("4.0.2")
|
|
|
|
implementation(project(":domain")) // project dependency
|
|
implementation("io.vertx:vertx-core:${vertxVersion}")
|
|
}
|
|
|
|
application {
|
|
mainClass.set("com.mrhaki.web.Api")
|
|
}
|
|
```
|
|
|
|
The `rest-api` project will have all the configuration and tasks from `java-library` plugin as configured in the `java-project-conventions` plugin, so we can build it as a Java project.
|
|
|
|
Written with Gradle 6.8.2. |