Gradle at its core intentionally provides very little for real world automation. All of the useful features, like the ability to compile Java code, are added by plugins. Plugins add new tasks (e.g. JavaCompile), domain objects (e.g. SourceSet), conventions (e.g. Java source is located at src/main/java) as well as extending core objects and objects from other plugins.

In this chapter we discuss how to use plugins and the terminology and concepts surrounding plugins.

What plugins do

Applying a plugin to a project allows the plugin to extend the project’s capabilities. It can do things such as:

  • Extend the Gradle model (e.g. add new DSL elements that can be configured)

  • Configure the project according to conventions (e.g. add new tasks or configure sensible defaults)

  • Apply specific configuration (e.g. add organizational repositories or enforce standards)

By applying plugins, rather than adding logic to the project build script, we can reap a number of benefits. Applying plugins:

  • Promotes reuse and reduces the overhead of maintaining similar logic across multiple projects

  • Allows a higher degree of modularization, enhancing comprehensibility and organization

  • Encapsulates imperative logic and allows build scripts to be as declarative as possible

Types of plugins

There are two general types of plugins in Gradle, binary plugins and script plugins. Binary plugins are written either programmatically by implementing Plugin interface or declaratively using one of Gradle’s DSL languages. Binary plugins can reside within a build script, within the project hierarchy or externally in a plugin jar. Script plugins are additional build scripts that further configure the build and usually implement a declarative approach to manipulating the build. They are typically used within a build although they can be externalized and accessed from a remote location.

A plugin often starts out as a script plugin (because they are easy to write) and then, as the code becomes more valuable, it’s migrated to a binary plugin that can be easily tested and shared between multiple projects or organizations.

Using plugins

To use the build logic encapsulated in a plugin, Gradle needs to perform two steps. First, it needs to resolve the plugin, and then it needs to apply the plugin to the target, usually a Project.

Resolving a plugin means finding the correct version of the jar which contains a given plugin and adding it to the script classpath. Once a plugin is resolved, its API can be used in a build script. Script plugins are self-resolving in that they are resolved from the specific file path or URL provided when applying them. Core binary plugins provided as part of the Gradle distribution are automatically resolved.

Applying a plugin means actually executing the plugin’s Plugin.apply(T) on the Project you want to enhance with the plugin. Applying plugins is idempotent. That is, you can safely apply any plugin multiple times without side effects.

The most common use case for using a plugin is to both resolve the plugin and apply it to the current project. Since this is such a common use case, it’s recommended that build authors use the plugins DSL to both resolve and apply plugins in one step.

Binary plugins

You apply plugins by their plugin id, which is a globally unique identifier, or name, for plugins. Core Gradle plugins are special in that they provide short names, such as 'java' for the core JavaPlugin. All other binary plugins must use the fully qualified form of the plugin id (e.g. com.github.foo.bar), although some legacy plugins may still utilize a short, unqualified form. Where you put the plugin id depends on whether you are using the plugins DSL or the buildscript block.

Locations of binary plugins

A plugin is simply any class that implements the Plugin interface. Gradle provides the core plugins (e.g. JavaPlugin) as part of its distribution which means they are automatically resolved. However, non-core binary plugins need to be resolved before they can be applied. This can be achieved in a number of ways:

For more on defining your own plugins, see Custom Plugins.

Applying plugins with the plugins DSL

The plugins DSL provides a succinct and convenient way to declare plugin dependencies. It works with the Gradle plugin portal to provide easy access to both core and community plugins. The plugins DSL block configures an instance of PluginDependenciesSpec.

To apply a core plugin, the short name can be used:

Example 1. Applying a core plugin
build.gradle
plugins {
    id 'java'
}
build.gradle.kts
plugins {
    java
}

To apply a community plugin from the portal, the fully qualified plugin id must be used:

Example 2. Applying a community plugin
build.gradle
plugins {
    id 'com.jfrog.bintray' version '0.4.1'
}
build.gradle.kts
plugins {
    id("com.jfrog.bintray") version "0.4.1"
}

See PluginDependenciesSpec for more information on using the Plugin DSL.

Limitations of the plugins DSL

This way of adding plugins to a project is much more than a more convenient syntax. The plugins DSL is processed in a way which allows Gradle to determine the plugins in use very early and very quickly. This allows Gradle to do smart things such as:

  • Optimize the loading and reuse of plugin classes.

  • Allow different plugins to use different versions of dependencies.

  • Provide editors detailed information about the potential properties and values in the buildscript for editing assistance.

This requires that plugins be specified in a way that Gradle can easily and quickly extract, before executing the rest of the build script. It also requires that the definition of plugins to use be somewhat static.

There are some key differences between the plugins {} block mechanism and the “traditional” apply() method mechanism. There are also some constraints, some of which are temporary limitations while the mechanism is still being developed and some are inherent to the new approach.

Constrained Syntax

The plugins {} block does not support arbitrary code. It is constrained, in order to be idempotent (produce the same result every time) and side effect free (safe for Gradle to execute at any time).

The form is:

build.gradle
plugins {
    id «plugin id»                                            (1)
    id «plugin id» version «plugin version» [apply «false»]   (2)
}
1 for core Gradle plugins or plugins already available to the build script
2 for binary Gradle plugins that need to be resolved
build.gradle.kts
plugins {
    `«plugin id»`                                             (1)
    id(«plugin id»)                                           (2)
    id(«plugin id») version «plugin version» [apply «false»]  (3)
}
1 for core Gradle plugins
2 for core Gradle plugins or plugins already available to the build script
3 for binary Gradle plugins that need to be resolved

Where «plugin id» and «plugin version» must be constant, literal, strings and the apply statement with a boolean can be used to disable the default behavior of applying the plugin immediately (e.g. you want to apply it only in subprojects). No other statements are allowed; their presence will cause a compilation error.

Where «plugin id», in case #1 is a static Kotlin extension property, named after the core plugin ID ; and in cases #2 and #3 is a string. «plugin version» is also a string. The apply statement with a boolean can be used to disable the default behavior of applying the plugin immediately (e.g. you want to apply it only in subprojects).

See plugin version management if you want to use a variable to define a plugin version.

The plugins {} block must also be a top level statement in the buildscript. It cannot be nested inside another construct (e.g. an if-statement or for-loop).

Can only be used in build scripts and settings file

The plugins {} block can currently only be used in a project’s build script and the settings.gradle file. It cannot be used in script plugins or init scripts.

Future versions of Gradle will remove this restriction.

If the restrictions of the plugins {} block are prohibitive, the recommended approach is to apply plugins using the buildscript {} block.

Applying external plugins with same version to subprojects

If you have a multi-project build, you probably want to apply plugins to some or all of the subprojects in your build, but not to the root project. The default behavior of the plugins {} block is to immediately resolve and apply the plugins. But, you can use the apply false syntax to tell Gradle not to apply the plugin to the current project and then use the plugins {} block without the version in subprojects' build scripts:

Example 3. Applying plugins only on certain subprojects
settings.gradle
include 'hello-a'
include 'hello-b'
include 'goodbye-c'
build.gradle
plugins {
    id 'com.example.hello' version '1.0.0' apply false
    id 'com.example.goodbye' version '1.0.0' apply false
}
hello-a/build.gradle
plugins {
    id 'com.example.hello'
}
hello-b/build.gradle
plugins {
    id 'com.example.hello'
}
goodbye-c/build.gradle
plugins {
    id 'com.example.goodbye'
}
settings.gradle.kts
include("hello-a")
include("hello-b")
include("goodbye-c")
build.gradle.kts
plugins {
    id("com.example.hello") version "1.0.0" apply false
    id("com.example.goodbye") version "1.0.0" apply false
}
hello-a/build.gradle.kts
plugins {
    id("com.example.hello")
}
hello-b/build.gradle.kts
plugins {
    id("com.example.hello")
}
goodbye-c/build.gradle.kts
plugins {
    id("com.example.goodbye")
}

Even better - you can encapsulate the versions of external plugins by composing the build logic using your own convention plugins.

Applying plugins from the buildSrc directory

You can apply plugins that reside in a project’s buildSrc directory as long as they have a defined ID. The following example shows how to tie a plugin implementation class — my.MyPlugin — defined in buildSrc to the ID "my-plugin":

Example 4. Defining a buildSrc plugin with an ID
buildSrc/build.gradle
plugins {
    id 'java-gradle-plugin'
}

gradlePlugin {
    plugins {
        myPlugins {
            id = 'my-plugin'
            implementationClass = 'my.MyPlugin'
        }
    }
}
buildSrc/build.gradle.kts
plugins {
    `java-gradle-plugin`
}

gradlePlugin {
    plugins {
        create("myPlugins") {
            id = "my-plugin"
            implementationClass = "my.MyPlugin"
        }
    }
}

The plugin can then be applied by ID as normal:

Example 5. Applying a plugin from buildSrc
build.gradle
plugins {
    id 'my-plugin'
}
build.gradle.kts
plugins {
    id("my-plugin")
}

Plugin Management

The pluginManagement {} block may only appear in either the settings.gradle file, where it must be the first block in the file, or in an Initialization Script.

Example 6. Configuring pluginManagement per-project and globally
settings.gradle
pluginManagement {
    plugins {
    }
    resolutionStrategy {
    }
    repositories {
    }
}
rootProject.name = 'plugin-management'
init.gradle
settingsEvaluated { settings ->
    settings.pluginManagement {
        plugins {
        }
        resolutionStrategy {
        }
        repositories {
        }
    }
}
settings.gradle.kts
pluginManagement {
    plugins {
    }
    resolutionStrategy {
    }
    repositories {
    }
}
rootProject.name = "plugin-management"
init.gradle.kts
settingsEvaluated {
    pluginManagement {
        plugins {
        }
        resolutionStrategy {
        }
        repositories {
        }
    }
}
Custom Plugin Repositories

By default, the plugins {} DSL resolves plugins from the public Gradle Plugin Portal. Many build authors would also like to resolve plugins from private Maven or Ivy repositories because the plugins contain proprietary implementation details, or just to have more control over what plugins are available to their builds.

To specify custom plugin repositories, use the repositories {} block inside pluginManagement {}:

Example 7. Example: Using plugins from custom plugin repositories.
settings.gradle
pluginManagement {
    repositories {
        maven {
            url './maven-repo'
        }
        gradlePluginPortal()
        ivy {
            url './ivy-repo'
        }
    }
}
settings.gradle.kts
pluginManagement {
    repositories {
        maven(url = "./maven-repo")
        gradlePluginPortal()
        ivy(url = "./ivy-repo")
    }
}

This tells Gradle to first look in the Maven repository at ../maven-repo when resolving plugins and then to check the Gradle Plugin Portal if the plugins are not found in the Maven repository. If you don’t want the Gradle Plugin Portal to be searched, omit the gradlePluginPortal() line. Finally, the Ivy repository at ../ivy-repo will be checked.

Plugin Version Management

A plugins {} block inside pluginManagement {} allows all plugin versions for the build to be defined in a single location. Plugins can then be applied by id to any build script via the plugins {} block.

One benefit of setting plugin versions this way is that the pluginManagement.plugins {} does not have the same constrained syntax as the build script plugins {} block. This allows plugin versions to be taken from gradle.properties, or loaded via another mechanism.

Example 8. Example: Managing plugin versions via pluginManagement.
settings.gradle
pluginManagement {
  plugins {
        id 'com.example.hello' version "${helloPluginVersion}"
    }
}
build.gradle
plugins {
    id 'com.example.hello'
}
gradle.properties
helloPluginVersion=1.0.0
settings.gradle.kts
pluginManagement {
  val helloPluginVersion: String by settings
  plugins {
    id("com.example.hello") version "${helloPluginVersion}"
  }
}
build.gradle.kts
plugins {
    id("com.example.hello")
}
gradle.properties
helloPluginVersion=1.0.0

The plugin version is loaded from gradle.properties and configured in the settings script, allowing the plugin to be added to any project without specifying the version.

Plugin Resolution Rules

Plugin resolution rules allow you to modify plugin requests made in plugins {} blocks, e.g. changing the requested version or explicitly specifying the implementation artifact coordinates.

To add resolution rules, use the resolutionStrategy {} inside the pluginManagement {} block:

Example 9. Plugin resolution strategy.
settings.gradle
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.namespace == 'com.example') {
                useModule('com.example:sample-plugins:1.0.0')
            }
        }
    }
    repositories {
        maven {
            url './maven-repo'
        }
        gradlePluginPortal()
        ivy {
            url './ivy-repo'
        }
    }
}
settings.gradle.kts
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.namespace == "com.example") {
                useModule("com.example:sample-plugins:1.0.0")
            }
        }
    }
    repositories {
        maven {
            url = uri("./maven-repo")
        }
        gradlePluginPortal()
        ivy {
            url = uri("./ivy-repo")
        }
    }
}

This tells Gradle to use the specified plugin implementation artifact instead of using its built-in default mapping from plugin ID to Maven/Ivy coordinates.

Custom Maven and Ivy plugin repositories must contain plugin marker artifacts in addition to the artifacts which actually implement the plugin. For more information on publishing plugins to custom repositories read Gradle Plugin Development Plugin.

See PluginManagementSpec for complete documentation for using the pluginManagement {} block.

Plugin Marker Artifacts

Since the plugins {} DSL block only allows for declaring plugins by their globally unique plugin id and version properties, Gradle needs a way to look up the coordinates of the plugin implementation artifact. To do so, Gradle will look for a Plugin Marker Artifact with the coordinates plugin.id:plugin.id.gradle.plugin:plugin.version. This marker needs to have a dependency on the actual plugin implementation. Publishing these markers is automated by the java-gradle-plugin.

For example, the following complete sample from the sample-plugins project shows how to publish a com.example.hello plugin and a com.example.goodbye plugin to both an Ivy and Maven repository using the combination of the java-gradle-plugin, the maven-publish plugin, and the ivy-publish plugin.

Example 10. Complete Plugin Publishing Sample
build.gradle
plugins {
    id 'java-gradle-plugin'
    id 'maven-publish'
    id 'ivy-publish'
}

group 'com.example'
version '1.0.0'

gradlePlugin {
    plugins {
        hello {
            id = 'com.example.hello'
            implementationClass = 'com.example.hello.HelloPlugin'
        }
        goodbye {
            id = 'com.example.goodbye'
            implementationClass = 'com.example.goodbye.GoodbyePlugin'
        }
    }
}

publishing {
    repositories {
        maven {
            url '../../consuming/maven-repo'
        }
        ivy {
            url '../../consuming/ivy-repo'
        }
    }
}
build.gradle.kts
plugins {
    `java-gradle-plugin`
    `maven-publish`
    `ivy-publish`
}

group = "com.example"
version = "1.0.0"

gradlePlugin {
    plugins {
        create("hello") {
            id = "com.example.hello"
            implementationClass = "com.example.hello.HelloPlugin"
        }
        create("goodbye") {
            id = "com.example.goodbye"
            implementationClass = "com.example.goodbye.GoodbyePlugin"
        }
    }
}

publishing {
    repositories {
        maven {
            url = uri("../../consuming/maven-repo")
        }
        ivy {
            url = uri("../../consuming/ivy-repo")
        }
    }
}

Running gradle publish in the sample directory creates the following Maven repository layout (the Ivy layout is similar):

plugin markers

Legacy Plugin Application

With the introduction of the plugins DSL, users should have little reason to use the legacy method of applying plugins. It is documented here in case a build author cannot use the plugins DSL due to restrictions in how it currently works.

Applying Binary Plugins

Example 11. Applying a binary plugin
build.gradle
apply plugin: 'java'
build.gradle.kts
apply(plugin = "java")

Plugins can be applied using a plugin id. In the above case, we are using the short name ‘java’ to apply the JavaPlugin.

Rather than using a plugin id, plugins can also be applied by simply specifying the class of the plugin:

Example 12. Applying a binary plugin by type
build.gradle
apply plugin: JavaPlugin
build.gradle.kts
apply<JavaPlugin>()

The JavaPlugin symbol in the above sample refers to the JavaPlugin. This class does not strictly need to be imported as the org.gradle.api.plugins package is automatically imported in all build scripts (see Default imports).

Furthermore, it is not necessary to append .class to identify a class literal in Groovy as it is in Java.

Furthermore, one need to append the ::class suffix to identify a class literal in Kotlin instead of .class in Java.

Applying plugins with the buildscript block

Binary plugins that have been published as external jar files can be added to a project by adding the plugin to the build script classpath and then applying the plugin. External jars can be added to the build script classpath using the buildscript {} block as described in External dependencies for the build script.

Example 13. Applying a plugin with the buildscript block
build.gradle
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1'
    }
}

apply plugin: 'com.jfrog.bintray'
build.gradle.kts
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath("com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1")
    }
}

apply(plugin = "com.jfrog.bintray")

Script plugins

Example 14. Applying a script plugin
build.gradle
apply from: 'other.gradle'
build.gradle.kts
apply(from = "other.gradle.kts")

Script plugins are automatically resolved and can be applied from a script on the local filesystem or at a remote location. Filesystem locations are relative to the project directory, while remote script locations are specified with an HTTP URL. Multiple script plugins (of either form) can be applied to a given target.

Finding community plugins

Gradle has a vibrant community of plugin developers who contribute plugins for a wide variety of capabilities. The Gradle plugin portal provides an interface for searching and exploring community plugins.

More on plugins

This chapter aims to serve as an introduction to plugins and Gradle and the role they play. For more information on the inner workings of plugins, see Custom Plugins.