# Using Tasks

version 9.1.0-20250801000225+0000

The work that Gradle can do on a project is defined by one or more tasks.

A task represents some independent unit of work that a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.

When a user runs `./gradlew build` in the command line, Gradle will execute the `build` task along with any other tasks it depends on.

## List available tasks

Gradle provides several default tasks for a project, which are listed by running `./gradlew tasks`:

    > Task :tasks

    ------------------------------------------------------------
    Tasks runnable from root project 'myTutorial'
    ------------------------------------------------------------

    Build Setup tasks
    -----------------
    init - Initializes a new Gradle build.
    wrapper - Generates Gradle wrapper files.

    Help tasks
    ----------
    buildEnvironment - Displays all buildscript dependencies declared in root project 'myTutorial'.
    ...

Tasks either come from build scripts or plugins.

Once we apply a plugin to our project, such as the `application` plugin, additional tasks become available:

build.gradle.kts

    plugins {
        id("application")
    }

build.gradle

    plugins {
        id 'application'
    }

    $ ./gradlew tasks

    > Task :tasks

    ------------------------------------------------------------
    Tasks runnable from project ':app'
    ------------------------------------------------------------

    Application tasks
    -----------------
    run - Runs this project as a JVM application

    Build tasks
    -----------
    assemble - Assembles the outputs of this project.
    build - Assembles and tests this project.

    Documentation tasks
    -------------------
    javadoc - Generates Javadoc API documentation for the main source code.

    Other tasks
    -----------
    compileJava - Compiles main Java source.

    ...

Many of these tasks, such as `assemble`, `build`, and `run`, should be familiar to a developer.

## Task classification

There are two classes of tasks that can be executed:

1. Actionable tasks have some action(s) attached to do work in your build: `compileJava`.

2. Lifecycle tasks are tasks with no actions attached: `assemble`, `build`.

Typically, a lifecycle tasks depends on many actionable tasks, and is used to execute many tasks at once.

## Task registration and action

Let’s take a look at a simple "Hello World" task in a build script:

build.gradle.kts

    tasks.register("hello") {
        doLast {
            println("Hello world!")
        }
    }

build.gradle

    tasks.register('hello') {
        doLast {
            println 'Hello world!'
        }
    }

In the example, the build script registers a single task called `hello` using the TaskContainer API, and adds an action to it.

If the tasks in the project are listed, the `hello` task is available to Gradle:

    $ ./gradlew app:tasks --all

    > Task :app:tasks

    ------------------------------------------------------------
    Tasks runnable from project ':app'
    ------------------------------------------------------------

    Other tasks
    -----------
    compileJava - Compiles main Java source.
    compileTestJava - Compiles test Java source.
    hello
    processResources - Processes main resources.
    processTestResources - Processes test resources.
    startScripts - Creates OS-specific scripts to run the project as a JVM application.

You can execute the task in the build script with `./gradlew hello`:

    $ ./gradlew hello
    Hello world!

When Gradle executes the `hello` task, it executes the action provided. In this case, the action is simply a block containing some code: `println("Hello world!")`.

## Task group and description

The `hello` task from the previous section can be detailed with a description and assigned to a group with the following update:

build.gradle.kts

    tasks.register("hello") {
        group = "Custom"
        description = "A lovely greeting task."
        doLast {
            println("Hello world!")
        }
    }

build.gradle

    tasks.register('hello') {
        group = 'Custom'
        description = 'A lovely greeting task.'
        doLast {
            println 'Hello world!'
        }
    }

Once the task is assigned to a group, it will be listed by `./gradlew tasks`:

    $ ./gradlew tasks

    > Task :tasks

    Custom tasks
    ------------------
    hello - A lovely greeting task.

To view information about a task, use the `help --task <task-name>` command:

    $./gradlew help --task hello

    > Task :help
    Detailed task information for hello

    Path
    :app:hello

    Type
    Task (org.gradle.api.Task)

    Options
    --rerun     Causes the task to be re-run even if up-to-date.

    Description
    A lovely greeting task.

    Group
    Custom

As we can see, the `hello` task belongs to the `custom` group.

## Task dependencies

You can declare tasks that depend on other tasks:

build.gradle.kts

    tasks.register("hello") {
        doLast {
            println("Hello world!")
        }
    }
    tasks.register("intro") {
        dependsOn("hello")
        doLast {
            println("I'm Gradle")
        }
    }

build.gradle

    tasks.register('hello') {
        doLast {
            println 'Hello world!'
        }
    }
    tasks.register('intro') {
        dependsOn tasks.hello
        doLast {
            println "I'm Gradle"
        }
    }

    $ gradle -q intro
    Hello world!
    I'm Gradle

The dependency of `taskX` to `taskY` may be declared before `taskY` is defined:

build.gradle.kts

    tasks.register("taskX") {
        dependsOn("taskY")
        doLast {
            println("taskX")
        }
    }
    tasks.register("taskY") {
        doLast {
            println("taskY")
        }
    }

build.gradle

    tasks.register('taskX') {
        dependsOn 'taskY'
        doLast {
            println 'taskX'
        }
    }
    tasks.register('taskY') {
        doLast {
            println 'taskY'
        }
    }

    $ gradle -q taskX
    taskY
    taskX

The `hello` task from the previous example is updated to include a dependency:

build.gradle.kts

    tasks.register("hello") {
        group = "Custom"
        description = "A lovely greeting task."
        doLast {
            println("Hello world!")
        }
        dependsOn(tasks.assemble)
    }

build.gradle

    tasks.register('hello') {
        group = "Custom"
        description = "A lovely greeting task."
        doLast {
            println("Hello world!")
        }
        dependsOn(tasks.assemble)
    }

The `hello` task now depends on the `assemble` task, which means that Gradle must execute the `assemble` task before it can execute the `hello` task:

    $ ./gradlew :app:hello

    > Task :app:compileJava UP-TO-DATE
    > Task :app:processResources NO-SOURCE
    > Task :app:classes UP-TO-DATE
    > Task :app:jar UP-TO-DATE
    > Task :app:startScripts UP-TO-DATE
    > Task :app:distTar UP-TO-DATE
    > Task :app:distZip UP-TO-DATE
    > Task :app:assemble UP-TO-DATE

    > Task :app:hello
    Hello world!

## Task configuration

Once registered, tasks can be accessed via the TaskProvider API for further configuration.

For instance, you can use this to add dependencies to a task at runtime dynamically:

build.gradle.kts

    repeat(4) { counter ->
        tasks.register("task$counter") {
            doLast {
                println("I'm task number $counter")
            }
        }
    }
    tasks.named("task0") { dependsOn("task2", "task3") }

build.gradle

    4.times { counter ->
        tasks.register("task$counter") {
            doLast {
                println "I'm task number $counter"
            }
        }
    }
    tasks.named('task0') { dependsOn('task2', 'task3') }

    $ gradle -q task0
    I'm task number 2
    I'm task number 3
    I'm task number 0

Or you can add behavior to an existing task:

build.gradle.kts

    tasks.register("hello") {
        doLast {
            println("Hello Earth")
        }
    }
    tasks.named("hello") {
        doFirst {
            println("Hello Venus")
        }
    }
    tasks.named("hello") {
        doLast {
            println("Hello Mars")
        }
    }
    tasks.named("hello") {
        doLast {
            println("Hello Jupiter")
        }
    }

build.gradle

    tasks.register('hello') {
        doLast {
            println 'Hello Earth'
        }
    }
    tasks.named('hello') {
        doFirst {
            println 'Hello Venus'
        }
    }
    tasks.named('hello') {
        doLast {
            println 'Hello Mars'
        }
    }
    tasks.named('hello') {
        doLast {
            println 'Hello Jupiter'
        }
    }

    $ gradle -q hello
    Hello Venus
    Hello Earth
    Hello Mars
    Hello Jupiter

| The calls `doFirst` and `doLast` can be executed multiple times. They add an action to the beginning or the end of the task’s actions list. When the task executes, the actions in the action list are executed in order.

Here is an example of the `named` method being used to configure a task added by a plugin:

build.gradle.kts

    tasks.dokkaHtml.configure {
        outputDirectory.set(buildDir)
    }

build.gradle

    tasks.named("dokkaHtml") {
        outputDirectory.set(buildDir)
    }

## Task types

Gradle tasks are a subclass of `Task`.

In the build script, the `HelloTask` class is created by extending `DefaultTask`:

build.gradle.kts

    // Extend the DefaultTask class to create a HelloTask class
    abstract class HelloTask : DefaultTask() {
        @TaskAction
        fun hello() {
            println("hello from HelloTask")
        }
    }

    // Register the hello Task with type HelloTask
    tasks.register<HelloTask>("hello") {
        group = "Custom tasks"
        description = "A lovely greeting task."
    }

build.gradle

    // Extend the DefaultTask class to create a HelloTask class
    class HelloTask extends DefaultTask {
        @TaskAction
        void hello() {
            println("hello from HelloTask")
        }
    }

    // Register the hello Task with type HelloTask
    tasks.register("hello", HelloTask) {
        group = "Custom tasks"
        description = "A lovely greeting task."
    }

The `hello` task is registered with the type `HelloTask`.

Executing our new `hello` task:

    $ ./gradlew hello

    > Task :app:hello
    hello from HelloTask

Now the `hello` task is of type `HelloTask` instead of type `Task`.

The Gradle `help` task reveals the change:

    $ ./gradlew help --task hello

    > Task :help
    Detailed task information for hello

    Path
    :app:hello

    Type
    HelloTask (Build_gradle$HelloTask)

    Options
    --rerun     Causes the task to be re-run even if up-to-date.

    Description
    A lovely greeting task.

    Group
    Custom tasks

## Built-in task types

Gradle provides many built-in task types with common and popular functionality, such as copying or deleting files.

This example task copies `*.war` files from the `source` directory to the `target` directory using the `Copy` built-in task:

build.gradle.kts

    tasks.register<Copy>("copyTask") {
        from("source")
        into("target")
        include("*.war")
    }

build.gradle

    tasks.register('copyTask', Copy) {
        from("source")
        into("target")
        include("*.war")
    }

There are many task types developers can take advantage of, including `GroovyDoc`, `Zip`, `Jar`, `JacocoReport`, `Sign`, or `Delete`, which are available in the DSL.

Next Step: Learn how to write Tasks >>