Extending Gradle: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(96 intermediate revisions by the same user not shown)
Line 1: Line 1:
=External=
* https://docs.gradle.org/current/userguide/custom_tasks.html
=Internal=
=Internal=
* [[Gradle Concepts#Extending_Gradle|Extending Gradle]]
* [[Gradle Concepts#Extending_Gradle|Gradle Concepts]]
* [[Gradle Plugin Concepts]]
* [[Gradle Plugin Concepts]]
* [[Gradle_Task#Defining_Custom_Tasks|Gradle Tasks]]


=Overview=
=Overview=


The simplest way to extend Gradle is to write a [[#Custom_Task|custom task]], which can be declared in-line in [[build.gradle]] or can be written in its own source file(s).
The simplest way to extend Gradle is to write a [[#Custom_Task|custom task]], which can be declared [[#In-line_in_build.gradle|in-line in the project's build.gradle]] or in a [[#In-line_in_a_script_plugin|script plugin]], in the [[#In_the_Project.27s_buildSrc_Directory|projects's buildSrc directory]] or in can be [[#External_to_Project|external to project]] and provided back to the Gradle runtime as a JAR. More complex behavior that goes beyond the capabilities of a custom task can be implemented as a [[#Custom_Object_Plugin|custom object plugin]], which has the same choice in terms of where the code lives.
 
=Extensions Code Location=
Gradle does not suggest a specific way of writing extensions, such as tasks and plugins. Tasks can be declared in-line using the DSL keywords, or they can be programming using a JVM-based programming language such as Java or Groovy.
==In-line in build.gradle==
Both custom [[Gradle_Task#Simple_Task|simple]] or [[Gradle_Task#Enhanced_Task|enhanced]] tasks and binary plugins can be fully declared in-line in [[build.gradle]]. Placing the extension code here has the benefit that it is automatically compiled and included in the classpath of the build script. While declaring simple tasks in-line is acceptable, provided that the task or the plugin are not intended for reuse and sharing among other projects, declaring enhanced tasks or even full binary plugin in-line is, albeit possible, not recommended. The extension code declared in build.gradle is not visible outside the build script and it cannot be reused outside the build script.
 
Examples:
* [https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/01-in-line-build-gradle-simple-task Custom simple task declared in-line in build.gradle]
* [https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/04-in-line-build-gradle-enhanced-task Custom ehanced Java task declared in-line in build.gradle]
 
==In-line in a script plugin==
A [[Gradle_Plugin_Concepts#Script_Plugin|script plugin]] is a regular Gradle build script that can be imported into another build script. Both custom [[Gradle_Task#Simple_Task|simple]] or [[Gradle_Task#Enhanced_Task|enhanced]] tasks and [[Extending_Gradle_with_Binary_Plugins#Overview|"binary" plugin code]] can be declared in-line in a script plugin.
 
Examples:
* [https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/02-script-plugin-simple-task Custom simple task declared in-line in a script plugin].
* [https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/05-script-plugin-enhanced-task Custom enhanced task declared in-line in a script plugin].
 
==<span id='In_the_Project.27s_buildSrc_Directory'></span>In the Project's <tt>buildSrc</tt> Directory==
The source code for the [[Extending_Gradle_with_a_Custom_Enhanced_Task#Overview|custom enhanced task]] or the [[Extending_Gradle_with_Binary_Plugins#Overview|binary plugin]] can be placed in the 'buildSrc/src/main/java|groovy|kotlin' subdirectory of the project directory. Gradle will compile and test the extension code and it will automatically make it available on the classpath of the build script. This is a good choice while developing a custom task or a plugin, because it gives a quick feedback loop and allows for in-line debugging. The 'buildSrc' directory is itself a Gradle project and has a standard Maven layout. It could have a build.gradle, but it works without it for simple Java compilation cases that does not require external dependencies. 'buildSrc/build.gradle' starts to become useful when the custom code task being developed requires external dependencies. In that case, the dependencies must be declared in 'buildSrc/build.gradle', as shown below in [[#buildSrc_build.gradle_that_Declares_Dependencies|buildSrc build.gradle that Declares Dependencies]] section.
 
The extension code placed here is not visible outside the build and it cannot be reused outside the build it defines it.
<syntaxhighlight lang='text'>
.
├── build.gradle
├── buildSrc
│   ├── build.gradle
│   └── src
│      └── main
│          └── java
│              └── playground
│                  └── gradle
│                      └── CustomEnhancedTask.java
└── ...
</syntaxhighlight>


=Custom Task=
===<tt>buildSrc</tt> Project Example===
{{External|https://docs.gradle.org/current/userguide/custom_tasks.html}}
{{External|[https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/03-enhanced-task-in-buildSrc Custom enhanced task developed in buildSrc]}}
===<tt>buildSrc</tt> <tt>build.gradle</tt> that Declares Dependencies===
<syntaxhighlight lang='groovy'>
repositories {
  maven {
    url "https://plugins.gradle.org/m2/"
  }
}
dependencies {
  implementation "com.palantir.gradle.docker:gradle-docker:0.25.0"
}
</syntaxhighlight>
There are situations when the Gradle extensions developed in buildSrc depend on the libraries that back up plugins used by regular sub-projects during the build. In this case, the dependencies declared in buildSrc build.gradle should be declared on the library, not on plugin. An example is available in [[Configuring_com.palantir.docker_tag_at_Execution_Phase#Identify_the_Plugin_Library|Configuring com.palantir.docker tag at Execution Phase &#124; Identify the Plugin Library]].


The simplest way of extending Gradle is write a custom task. The custom task can be declared in-line in the default build script [[build.gradle]], as a [[#Simple_Task|simple task]]. The [[#Simple_Task|simple task]] can also be declared in-line in a separate build script, which is then included from the default build script. The code of the custom task can live in a separate source file, which in turn can be declared in a special area of the Gradle project, or can be share with other projects as part of a library. Such a task is referred to as a [[#Enhanced_Task|enhanced task]].
===Debugging a <tt>buildSrc</tt> Project===
{{Internal|Gradle_Operations#Debug_a_Gradle_Build|Gradle Operations &#124; Debug a Gradle Build}}


[[Gradle Task|Task]].
==<span id='External_to_Project'></span>External Standalone Project==
<font color=orange>DEPLETE [[Gradle_Task_TODEPLETE#Explicit_Task_Declaration_.28Custom_Tasks.29]]</font>
Extension code can live in an external standalone projects that publish JARs. Those JARs can be declared as dependencies by a Gradle project that can then use the custom task or the binary plugin externally developed.


==Simple Task==
Examples:
A simple task is defined with an in-line action closure in the build script or another script imported from the build script.
* [https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/06-enhanced-task-developed-in-standalone-project Custom enhanced task developed in standalone project]. The project publishes the JAR in the local Maven repository.
* [https://github.com/ovidiuf/playground/tree/master/gradle/extending-gradle/07-enhanced-task-imported-from-external-project Custom enhanced task imported from external project]. The project gets the JAR with the task from the local Maven repository.


==Enhanced Task==
=<span id='Custom_Task'></span>Custom Tasks=
An enhanced task implies writing code into a source code file (or files) and providing that bytecode to Gradle. The behavior is built into the task and the task exposes some properties that can be configured from the build script. This is appropriate if the task needs to be shared across different projects.
{{Internal|Gradle_Task#Simple_Task|Extending Gradle with Custom Simple Tasks}}
{{Internal|Extending Gradle with a Custom Enhanced Task#Overview|Extending Gradle with Custom Enhanced Tasks}}


=Custom Script Plugin=
=Custom Binary Plugin=
{{Internal|Extending Gradle with Binary Plugins|Extending Gradle with Binary Plugins}}


=Custom Object Plugin=
=Extension=
A [[Gradle_Plugin_Concepts#Plugin_Extension|plugin]] is the typical use case for an extension.

Latest revision as of 02:52, 11 November 2020

External

Internal

Overview

The simplest way to extend Gradle is to write a custom task, which can be declared in-line in the project's build.gradle or in a script plugin, in the projects's buildSrc directory or in can be external to project and provided back to the Gradle runtime as a JAR. More complex behavior that goes beyond the capabilities of a custom task can be implemented as a custom object plugin, which has the same choice in terms of where the code lives.

Extensions Code Location

Gradle does not suggest a specific way of writing extensions, such as tasks and plugins. Tasks can be declared in-line using the DSL keywords, or they can be programming using a JVM-based programming language such as Java or Groovy.

In-line in build.gradle

Both custom simple or enhanced tasks and binary plugins can be fully declared in-line in build.gradle. Placing the extension code here has the benefit that it is automatically compiled and included in the classpath of the build script. While declaring simple tasks in-line is acceptable, provided that the task or the plugin are not intended for reuse and sharing among other projects, declaring enhanced tasks or even full binary plugin in-line is, albeit possible, not recommended. The extension code declared in build.gradle is not visible outside the build script and it cannot be reused outside the build script.

Examples:

In-line in a script plugin

A script plugin is a regular Gradle build script that can be imported into another build script. Both custom simple or enhanced tasks and "binary" plugin code can be declared in-line in a script plugin.

Examples:

In the Project's buildSrc Directory

The source code for the custom enhanced task or the binary plugin can be placed in the 'buildSrc/src/main/java|groovy|kotlin' subdirectory of the project directory. Gradle will compile and test the extension code and it will automatically make it available on the classpath of the build script. This is a good choice while developing a custom task or a plugin, because it gives a quick feedback loop and allows for in-line debugging. The 'buildSrc' directory is itself a Gradle project and has a standard Maven layout. It could have a build.gradle, but it works without it for simple Java compilation cases that does not require external dependencies. 'buildSrc/build.gradle' starts to become useful when the custom code task being developed requires external dependencies. In that case, the dependencies must be declared in 'buildSrc/build.gradle', as shown below in buildSrc build.gradle that Declares Dependencies section.

The extension code placed here is not visible outside the build and it cannot be reused outside the build it defines it.

.
├── build.gradle
├── buildSrc
│   ├── build.gradle
│   └── src
│       └── main
│           └── java
│               └── playground
│                   └── gradle
│                       └── CustomEnhancedTask.java
└── ...

buildSrc Project Example

Custom enhanced task developed in buildSrc

buildSrc build.gradle that Declares Dependencies

repositories {
  maven {
    url "https://plugins.gradle.org/m2/"
  }
}
dependencies {
  implementation "com.palantir.gradle.docker:gradle-docker:0.25.0"
}

There are situations when the Gradle extensions developed in buildSrc depend on the libraries that back up plugins used by regular sub-projects during the build. In this case, the dependencies declared in buildSrc build.gradle should be declared on the library, not on plugin. An example is available in Configuring com.palantir.docker tag at Execution Phase | Identify the Plugin Library.

Debugging a buildSrc Project

Gradle Operations | Debug a Gradle Build

External Standalone Project

Extension code can live in an external standalone projects that publish JARs. Those JARs can be declared as dependencies by a Gradle project that can then use the custom task or the binary plugin externally developed.

Examples:

Custom Tasks

Extending Gradle with Custom Simple Tasks
Extending Gradle with Custom Enhanced Tasks

Custom Binary Plugin

Extending Gradle with Binary Plugins

Extension

A plugin is the typical use case for an extension.