Permalink
Switch branches/tags
Find file Copy path
e703632 Mar 16, 2018
2 contributors

Users who have contributed to this file

@eskatos @bamboo
145 lines (115 sloc) 4.64 KB

Configuring Plugins in the Gradle Kotlin DSL

When writing your build logic in groovy you will often see code like this:

pmd {
    consoleOutput = true
    sourceSets = [sourceSets.main, sourceSets.test]
    reportsDir = file("$project.buildDir/reports/pmd")
    ruleSetFiles = files(new File(rootDir, "pmd-ruleset.xml"))
    ruleSets = []
}

findbugs {
    sourceSets = [sourceSets.main, sourceSets.test]
    excludeFilter = new File(rootDir, "findBugsSuppressions.xml")
    effort = "max"
}

These configuration blocks are used by plugins to configure tasks that they add to your build.

They are added as extensions like this:

project.extensions.create("greeting", GreetingPluginExtension)

Now, in your build.gradle you can use the config like this:

greeting {
    // Various config options here...
}

You can read more about this part of the gradle API here.

When using the Gradle Kotlin DSL it is heavily recommended to apply Gradle plugins declaratively using the plugins {} block. This will enable type-safe extension accessors you will use to configure plugins.

plugins {
    // Gradle built-in
    `application`
    // From the Gradle Plugin Portal
    id("com.bmuschko.docker-java-application") version "3.1.0"
}

// Type-safe accessor for the extension contributed by the `application` plugin
application {
    mainClassName = "samples.HelloWorld"
}

// Type-safe accessor for the extension contributed by the Docker plugin
registryCredentials {
    url = "https://docker.acme.com/v1/"
}

Plugins fetched from another source than the Gradle Plugin Portal may or may not be usable with the plugins {} block depending on how they have been published. If you're publishing plugins, please use the Gradle built-in java-gradle-plugin plugin that automates publication of supplementary data to make your plugins usable with the plugins {} block.

For example, the Android Gradle Plugin plugins are not published to the Gradle Plugin Portal and the metadata required to resolve plugin identifiers to resolvable artifacts is not published. The following snippets will use the Android Gradle Plugin to demonstrate how to enable the use of the plugins {} block anyway.

The goal here is to instruct your build how to map the com.android.application plugin identifier to a resolvable artifact. This is done in two steps.

First add a plugin repository in your settings.gradle.kts file for the whole build:

pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
    }
}

Then, map the plugin id to the corresponding artifact coordinates, still in your settings.gradle.kts file:

pluginManagement {
    // ...
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "com.android.application") {
                useModule("com.android.tools.build:gradle:${requested.version}")
            }
        }
    }    
}

You can now apply the com.android.application plugin using the plugins {} block and benefit from the type-safe plugin extension accessors, in your build.gradle.kts file:

plugins {
    id("com.android.application") version "3.0.0"
}

android {
    buildToolsVersion("27.0.0")
    compileSdkVersion(27)
}

See the Plugin Management section of the Gradle documentation for more information.

The same can be applied to resolving plugins from composite builds. Composite builds do not expose plugin markers yet. This can be worked around by mapping the plugin id to the corresponding artifact coordinates using a plugin resolution strategy, just like above.

If you can't use the plugins {} block, you need to apply the plugin imperatively (using the buildscript block and apply<PluginType>() or apply(plugin = "id")) and to know the type of the extension.

The following groovy block of code:

greeting {
    // Various config options here...
}

would now become:

configure<GreetingPluginExtension> {
    // Various config options here...
}

If GreetingPluginExtension is not in the base package you will need to import the class.

In order to determine what class you need to use in your configure<...> call you may need to examine the plugins source code to determine which object is being used to configure the plugin. There may be more than one object for some plugins.