Table of Contents
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.
Applying a plugin to a project allows the plugin to extend the project's capabilities. It can do things such as:
By applying plugins, rather than adding logic to the project build script, we can reap a number of benefits. Applying plugins:
There are two general types of plugins in Gradle, script plugins and binary plugins.
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. Binary plugins are classes that implement the Plugin
interface and adopt a programmatic
approach to manipulating the build. Binary plugins can reside within a build script, within the project hierarchy or externally
in a plugin jar.
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.
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 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. The feature is technically still incubating, but it works well, and should be used by most users.
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.
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.
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:
buildSrc
project”).For more on defining your own plugins, see Chapter 41, Writing Custom Plugins.
The plugins DSL is currently incubating. Please be aware that the DSL and other configuration may change in later Gradle versions.
The new 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:
To apply a community plugin from the portal, the fully qualified plugin id must be used:
Example 27.3. Applying a community plugin
build.gradle
plugins { id "com.jfrog.bintray" version "0.4.1" }
See PluginDependenciesSpec
for more information on using the Plugin 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:
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 new plugin 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.
The new plugins {}
block does not support arbitrary Groovy 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:
plugins { id «plugin id» version «plugin version» [apply «false»] }
Where «plugin version»
and «plugin id»
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.
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).
The plugins {}
block can currently only be used in a project's build script. It cannot be used in
script plugins, the settings.gradle file or init scripts.
Future versions of Gradle will remove this restriction.
If the restrictions of the new syntax are prohibitive, the recommended approach is to apply plugins using the buildscript {} block.
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
or master
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 apply plugin: «plugin version»
in the
subprojects
block:
Example 27.4. Applying plugins only on certain subprojects.
settings.gradle
include 'helloA' include 'helloB' include 'goodbyeC'
build.gradle
plugins { id "org.gradle.sample.hello" version "1.0.0" apply false id "org.gradle.sample.goodbye" version "1.0.0" apply false } subprojects { subproject -> if (subproject.name.startsWith("hello")) { apply plugin: 'org.gradle.sample.hello' } if (subproject.name.startsWith("goodbye")) { apply plugin: 'org.gradle.sample.goodbye' } }
If you then run gradle hello
you'll see that only the helloA and helloB subprojects had the hello plugin
applied.
gradle/subprojects/docs/src/samples/plugins/multiproject $> gradle hello Parallel execution is an incubating feature. :helloA:hello :helloB:hello Hello! Hello! BUILD SUCCESSFUL
The pluginRepositories {}
DSL is currently incubating.
Please be aware that the DSL and other configuration may change in later Gradle versions.
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, add a pluginRepositories {}
block to the settings.gradle
file:
Example 27.5. Using plugins from custom plugin repositories.
settings.gradle
pluginRepositories { 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.
The pluginRepositories {}
block may only appear in the settings.gradle
file, and must be the first block in the file.
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 Chapter 42, The Java Gradle Plugin Development Plugin.
See PluginRepositoriesSpec
for complete documentation for using the
pluginRepositories {}
block.
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
org.gradle.sample.hello
plugin and a org.gradle.sample.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 27.6. Complete Plugin Publishing Sample
build.gradle
plugins { id 'java-gradle-plugin' id 'maven-publish' id 'ivy-publish' } group 'org.gradle.sample' version '1.0.0' gradlePlugin { plugins { hello { id = "org.gradle.sample.hello" implementationClass = "org.gradle.sample.hello.HelloPlugin" } goodbye { id = "org.gradle.sample.goodbye" implementationClass = "org.gradle.sample.goodbye.GoodbyePlugin" } } } publishing { repositories { maven { url "../consuming/maven-repo" } ivy { url "../consuming/ivy-repo" } } }
Running gradle publish
in the sample directory causes the following repo layouts to exist:
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.
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:
The JavaPlugin
symbol in the above sample refers to the 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 Section 18.8, “Default imports”). Furthermore, it is not necessary to append .class
to identify a class literal in Groovy as it is in Java.
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 Section 43.6, “External dependencies for the build script”.
Example 27.9. 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"
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.
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 Chapter 41, Writing Custom Plugins.