// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[writing_tasks]]
= Creating and Registering Tasks

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

image::gradle-basic-14.png[]

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.

== Task Types

A *task type* defines what kind of work a *task* can do.
It’s like a blueprint or class.

Gradle includes many *built-in task types*, such as `Copy`, `Jar`, and `Test`, and you can also define your own.
By default, a *task* is of *type* link:{javadocPath}/org/gradle/api/DefaultTask.html[`DefaultTask`] .

[[sec:task_registration]]
Let’s start with a simple custom task that prints a message:

====
include::sample[dir="snippets/tutorial/hello/kotlin", files="build.gradle.kts[]"]
include::sample[dir="snippets/tutorial/hello/groovy", files="build.gradle[]"]
====

You just registered a *task* called `hello` of *type* `DefaultTask` and gave it an action using `doLast{}`.

A task is *created* in the build script using the link:{javadocPath}/org/gradle/api/tasks/TaskContainer.html[`TaskContainer.register()`] method, which allows it to be then used in the build logic.

When you run the `hello` task in the command-line using `./gradlew hello`, it prints your message:

[source,text]
----
$ ./gradlew hello
include::{snippetsPath}/tutorial/hello/tests/hello.out[]
----

When you *register* (i.e. create) a *task* in your build script, you can:

- Use the default *task type* (`DefaultTask`) and define the behavior inline.
- Use a *built-in task type*, like `Copy`, to take advantage of pre-defined behavior.
- Create and use a *custom task type* if you need reusable behavior across tasks.

This example registers a *task* called `copyTask` which copies `\*.war` files from the `source` directory to the `target` directory using the `Copy` **built-in task type**:

====
include::sample[dir="snippets/tasks/taskTutorial/kotlin", files="build.gradle.kts[tags=copy]"]
include::sample[dir="snippets/tasks/taskTutorial/groovy", files="build.gradle[tags=copy]"]
====

== Built-in Task Types

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

This registers a Gradle *task* named `removeOutput` of *type* `Delete`.
When the *task* runs, it will delete the file `build/outputs/1.txt` relative to the project directory.

====
include::sample[dir="snippets/tasks/incrementalTask/kotlin",files="build.gradle.kts[tags=removed-output]"]
include::sample[dir="snippets/tasks/incrementalTask/groovy",files="build.gradle[tags=removed-output]"]
====

There are many *task types* developers can take advantage of, including `GroovyDoc`, `Zip`, `Jar`, `JacocoReport`, `Sign`, or `Delete`, which are detailed in the link:link:{groovyDslPath}/org.gradle.api.plugins.antlr.AntlrTask.html[DSL].

[[sec:sample_task]]
== Custom Task Types

Gradle *tasks* are a subclass of link:{javadocPath}/org/gradle/api/Task.html[`Task`].

In the example below, the `HelloTask` class, a *custom task type*, is created by extending link:{javadocPath}/org/gradle/api/DefaultTask.html[`DefaultTask`] (our default task type):

====
include::sample[dir="snippets/tasks/tutorialTask/kotlin", files="build.gradle.kts[tags=hello]"]
include::sample[dir="snippets/tasks/tutorialTask/groovy", files="build.gradle[tags=hello]"]
====

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

Executing our new `hello` *task* results in the following:

[source,text]
----
$ ./gradlew hello

> Task :app:hello
hello from HelloTask
----

The Gradle `help` *task* can reveal the specifications of the `hello` task:

[source,text]
----
$ ./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
----

[[task_inputs_and_outputs]]
== Task Input and Outputs

For a *custom task* to do useful work, it typically needs some *inputs* which it uses to produce *outputs*.

A *task* can declare those *inputs* (files, values) and *outputs* (files it creates).
Ideally, these inputs and outputs leverage Gradle managed types.
This helps Gradle skip work when nothing has changed:

====
include::sample[dir="snippets/tasks/tutorialTask/kotlin", files="build.gradle.kts[tags=default]"]
include::sample[dir="snippets/tasks/tutorialTask/groovy", files="build.gradle[tags=default]"]
====

Now Gradle knows what the *task* needs and what it produces.
If nothing changes, the *task* is skipped.

== Task Action

*Task actions* are the blocks of code that define what the *custom task* does when it runs.

Every *task* can have one or more actions, and they’re executed during the execution phase of the Gradle build lifecycle.

A *task action* is typically added using `doLast {}` or `doFirst {}`:

====
include::sample[dir="snippets/tutorial/hello/kotlin", files="build.gradle.kts[]"]
include::sample[dir="snippets/tutorial/hello/groovy", files="build.gradle[]"]
====

In this example, the *action* is `println("Hello world!")`.
It will run when the *task* is executed.

Similarly, in the example below, a *custom task type* is created called `GreetingTask`.
The `@TaskAction` annotation marks a method that Gradle should call when the *task* of this *type* is executed:

====
include::sample[dir="snippets/tasks/customTask/kotlin", files="build.gradle.kts[tags=add-action]"]
include::sample[dir="snippets/tasks/customTask/groovy", files="build.gradle[tags=add-action]"]
====

[[sec:task_dependencies]]
== Task Dependencies

You can declare *tasks* that depend on other *tasks*:

====
include::sample[dir="snippets/tutorial/intro/kotlin", files="build.gradle.kts[]"]
include::sample[dir="snippets/tutorial/intro/groovy", files="build.gradle[]"]

----
$ gradle -q intro
include::{snippetsPath}/tutorial/intro/tests/intro.out[]
----
====

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

====
include::sample[dir="snippets/tutorial/lazyDependsOn/kotlin", files="build.gradle.kts[]"]
include::sample[dir="snippets/tutorial/lazyDependsOn/groovy", files="build.gradle[]"]

----
$ gradle -q taskX
include::{snippetsPath}/tutorial/lazyDependsOn/tests/lazyDependsOn.out[]
----
====

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

====
include::sample[dir="snippets/tutorial/dynamicDepends/kotlin", files="build.gradle.kts[tags=hello]"]
include::sample[dir="snippets/tutorial/dynamicDepends/groovy", files="build.gradle[tags=hello]"]
====

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*:

[source,text]
----
$ ./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!
----

[[sec:manipulating_existing_tasks]]
== Task Configuration

Once registered, *tasks* can be accessed via the link:{javadocPath}/org/gradle/api/tasks/TaskProvider.html[`TaskProvider`] API for further configuration.

For instance, you can add behavior to an existing *task*:

[[sec:hello_world]]
====
include::sample[dir="snippets/tutorial/helloEnhanced/kotlin", files="build.gradle.kts[]"]
include::sample[dir="snippets/tutorial/helloEnhanced/groovy", files="build.gradle[]"]

----
$ gradle -q hello
include::{snippetsPath}/tutorial/helloEnhanced/tests/helloEnhanced.out[]
----
====

TIP: 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.

A task is optionally *configured* in a build script using the link:{javadocPath}/org/gradle/api/tasks/TaskCollection.html[`TaskCollection.named()`] method.

== 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.

[.text-right]
**Next Step:** <<plugins_intermediate.adoc#using_plugins,Learn about Plugins>> >>
