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:

internal-module/build.gradle
plugins {
    id 'com.example.java-convention'
}

dependencies {
    // internal module dependencies
}
internal-module/build.gradle.kts
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.

library-a/build.gradle
plugins {
    id 'com.example.library'
}

dependencies {
    implementation project(':internal-module')
}
library-b/build.gradle
plugins {
    id 'com.example.library'
}

dependencies {
    implementation project(':internal-module')
}
library-a/build.gradle.kts
plugins {
    id("com.example.library")
}

dependencies {
    implementation(project(":internal-module"))
}
library-b/build.gradle.kts
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:

buildSrc/build.gradle
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'
}
buildSrc/build.gradle.kts
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.12")
}
  • 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:

buildSrc/src/main/groovy/com.example.java-convention.gradle
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'
}
buildSrc/src/main/kotlin/com.example.java-convention.gradle.kts
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:

buildSrc/src/main/groovy/com.example.library.gradle
plugins {
    id 'java-library'
    id 'maven-publish'
    id 'com.example.java-convention'
}
buildSrc/src/main/kotlin/com.example.library.gradle.kts
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:

buildSrc/src/main/groovy/com.example.library.gradle
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$']
}
buildSrc/src/main/kotlin/com.example.library.gradle.kts
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.