You can open this sample inside an IDE using the IntelliJ native importer or Eclipse Buildship. |
This sample shows how precompiled script plugins can be used to compose build logic using built-in Gradle plugins, external Gradle plugins and other utility classes.
Use case
As an example, let’s say a multi module project produces multiple Java libraries that use shared internal modules as an implementation detail. We want to apply a set of code quality checking rules to all the submodules and configure some aspects specific to library artifacts.
This is achieved by layering two separate plugins in project’s buildSrc
module:
-
com.example.java-convention
- configures conventions that are generic for any Java project in the organization. -
com.example.library
- adds publishing configuration to publish to the organization’s repository and checks for mandatory content in a README.
All plugins created in this sample contain functional tests that use TestKit to verify their behavior.
This sample does not have any project source code and only lays out a hypothetical project structure where two library modules depend on a shared internal module.
The internal module uses com.example.java-convention
plugin:
plugins {
id 'com.example.java-convention'
}
dependencies {
// internal module dependencies
}
plugins {
id("com.example.java-convention")
}
dependencies {
// internal module dependencies
}
The two libraries use com.example.library
plugin that in turn uses com.example.java-convention
.
plugins {
id 'com.example.library'
}
dependencies {
implementation project(':internal-module')
}
plugins {
id 'com.example.library'
}
dependencies {
implementation project(':internal-module')
}
plugins {
id("com.example.library")
}
dependencies {
implementation(project(":internal-module"))
}
plugins {
id("com.example.library")
}
dependencies {
implementation(project(":internal-module"))
}
Things to note
Applying an external plugin in precompiled script plugin
The com.example.java-convention
plugin uses SpotBugs plugin to perform static code analysis.
SpotBugs is an external plugin - external plugins need to be added as implementation dependencies before they can be applied in a precompiled script plugin:
repositories {
gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}
dependencies {
implementation 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.0.5'
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
}
repositories {
gradlePluginPortal() // so that external plugins can be resolved in dependencies section
}
dependencies {
implementation("gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.0.5")
testImplementation("junit:junit:4.13")
}
-
The dependency artifact coordinates (GAV) for a plugin can be different from the plugin id.
-
The Gradle Plugin Portal (
gradlePluginPortal()
) is added as a repository for plugin dependencies. -
The plugin version is determined from the dependency version. Precompiled script plugins cannot supply a different version for now.
Once the dependency is added, the external plugin can be applied in precompiled script plugin by id:
plugins {
id 'java'
id 'checkstyle'
// NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
id 'com.github.spotbugs'
}
plugins {
java
checkstyle
// NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
id("com.github.spotbugs")
}
Applying other precompiled script plugins
Precompiled script plugins can apply other precompiled script plugins.
The com.example.library
plugin applies the com.example.java-convention
plugin:
plugins {
id 'java-library'
id 'maven-publish'
id 'com.example.java-convention'
}
plugins {
`java-library`
`maven-publish`
id("com.example.java-convention")
}
Using classes from the main source set
Precompiled script plugins can use classes defined in the main source set of the plugins project.
In this sample, com.example.library
plugin uses a custom task class from buildSrc/src/main/java
to configure library README checks:
def readmeCheck = tasks.register('readmeCheck', com.example.ReadmeVerificationTask) {
// Expect the README in the project directory
readme = layout.projectDirectory.file("README.md")
// README must contain a Service API header
readmePatterns = ['^## API$', '^## Changelog$']
}
val readmeCheck by tasks.registering(com.example.ReadmeVerificationTask::class) {
readme.set(layout.projectDirectory.file("README.md"))
readmePatterns.set(listOf("^## API$", "^## Changelog$"))
}
For more details on authoring custom Gradle plugins, consult the user manual.