Chapter 32. Writing Custom Tasks

Gradle supports 2 types of task. One such type is the simple task, where you define the task with an action closure. We have seen these in Chapter 4, Build Script Basics. For this type of task, the action closure determines the behaviour of the task. This type of task is good for implementing one-off tasks in your build script.

The other type of task is the enhanced task, where the behaviour is built into the task, and the task provides some properties which you can use to configure the behaviour. We have seen these in Chapter 13, More about Tasks. Most Gradle plugins use enhanced tasks. With enhanced tasks, you don't need to implement the task behaviour as you do with simple tasks. You simply declare and configure the task using its properties. In this way, enhanced tasks let you reuse a piece of behaviour in many different places, potentially across different builds.

Gradle allows you to implement your own custom enhanced tasks. Implementing such a custom task in Gradle is easy. You can implement a custom task in pretty much any language you like, provided it ends up compiled to classes files. In our examples, we are going to use Groovy as the implementation language, but you could use, for example, Java or Scala.

There are several places where you can put the source for the task. Two convenient options are to add the task implementation to your build script, or to put the source in the rootProjectDir/buildSrc/src/main/groovy directory. Gradle will take care of compiling the task and making it available on the classpath of the build script. See Chapter 34, Organizing Build Logic for more details, and some other options. In our examples, we will put the task implementation in the build script, to keep things simple.

To implement a custom task, you extend DefaultTask .

Example 32.1. Defining a custom task

build.gradle

class HelloTask extends DefaultTask {
}

This task doesn't do anything useful, so let's add some behaviour. To do so, we add a method to the task and mark it with the TaskAction annotation. Gradle will call the method when the task executes. You don't have to use a method to define the behaviour for the task. You could, for instance, call doFirst() or doLast() with a closure in the task constructor to add behaviour.

Example 32.2. A hello world task

build.gradle

task hello(type: HelloTask)

class HelloTask extends DefaultTask {
    @TaskAction
    def printGreeting() {
        println 'hello from HelloTask'
    }
}

Output of gradle -q hello

> gradle -q hello
hello from HelloTask

Let's add a property to the task, so we can customize it.

Example 32.3. A customizable hello world task

build.gradle

task hello(type: HelloTask)

task greeting(type: HelloTask) {
    greeting = 'greetings from HelloTask'
}

class HelloTask extends DefaultTask {
    def String greeting = 'hello from HelloTask'

    @TaskAction
    def printGreeting() {
        println greeting
    }
}

Output of gradle -q hello greeting

> gradle -q hello greeting
hello from HelloTask
greetings from HelloTask