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

[[more_about_tasks]]
= Understanding Tasks

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

++++
<p>
  <div style="position:relative;padding-top:56.25%;">
    <iframe src="https://www.youtube-nocookie.com/embed/FB5muea-2Z0?si=XcoZGjrw0KD5FSIJ&rel=0" frameborder="0" allowfullscreen
      style="position:absolute;top:0;left:0;width:100%;height:100%;"></iframe>
  </div>
</p>
++++

Before reading this chapter, it's recommended that you first read the <<gradle_directories_intermediate.adoc#gradle_directories,Learning The Basics>> and complete the <<part1_gradle_init_project.adoc#part1_gradle_init,Tutorial>>.

[[sec:more_listing_tasks]]
== Listing tasks

All available tasks in your project come from Gradle plugins and build scripts.

You can list all the available tasks in a project by running the following command in the terminal:

[source,bash]
----
$ ./gradlew tasks
----

Let's take a very basic Gradle project as an example.
The project has the following structure:

====
[.multi-language-sample]
=====
[source,kotlin]
----
gradle-project
├── app
│   ├── build.gradle.kts    // empty file - no build logic
│   └── ...                 // some java code
├── settings.gradle.kts     // includes app subproject
├── gradle
│   └── ...
├── gradlew
└── gradlew.bat
----
=====
[.multi-language-sample]
=====
[source,groovy]
----
gradle-project
├── app
│   ├── build.gradle    // empty file - no build logic
│   └── ...             // some java code
├── settings.gradle     // includes app subproject
├── gradle
│   └── ...
├── gradlew
└── gradlew.bat
----
=====
====

The settings file contains the following:

====
[.multi-language-sample]
=====
.settings.gradle.kts
[source,kotlin]
----
rootProject.name = "gradle-project"
include("app")
----
=====
[.multi-language-sample]
=====
.settings.gradle
[source,groovy]
----
rootProject.name = 'gradle-project'
include('app')
----
=====
====

Currently, the `app` subproject's build file is empty.

To see the tasks available in the `app` subproject, run `./gradlew :app:tasks`:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app:tasks

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

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
kotlinDslAccessorsReport - Prints the Kotlin code for accessing the currently available project extensions and conventions.
outgoingVariants - Displays the outgoing variants of project ':app'.
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':app'.
tasks - Displays the tasks runnable from project ':app'.
----

We observe that only a small number of help tasks are available at the moment.
This is because the core of Gradle only provides tasks that analyze your build.
Other tasks, such as the those that build your project or compile your code, are added by plugins.

Let's explore this by adding the <<base_plugin.adoc#base_plugin,Gradle core `base` plugin>> to the `app` build script:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
plugins {
    id("base")
}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source, groovy]
----
plugins {
    id('base')
}
----
=====
====

The `base` plugin adds central lifecycle tasks.
Now when we run `./gradlew app:tasks`, we can see the `assemble` and `build` tasks are available:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app:tasks

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

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

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of project ':app'.
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':app'.
tasks - Displays the tasks runnable from project ':app'.

Verification tasks
------------------
check - Runs all checks.
----

[[sec:task_outcomes]]
== Task outcomes

When Gradle executes a task, it labels the task with outcomes via the console.

image::author-tasks-1.png[]

These labels are based on whether a task has actions to execute and if Gradle executed them.
Actions include, but are not limited to, compiling code, zipping files, and publishing archives.

`(no label)` or `EXECUTED`:: *Task executed its actions.*
* Task has actions and Gradle executed them.
* Task has no actions and some dependencies, and Gradle executed one or more of the dependencies. See also <<organizing_tasks.adoc#sec:lifecycle_tasks,Lifecycle Tasks>>.

`UP-TO-DATE`:: *Task's outputs did not change.*
* Task has outputs and inputs but they have not changed. See <<incremental_build.adoc#incremental_build,Incremental Build>>.
* Task has actions, but the task tells Gradle it did not change its outputs.
* Task has no actions and some dependencies, but all the dependencies are `UP-TO-DATE`, `SKIPPED` or `FROM-CACHE`. See <<organizing_tasks.adoc#sec:lifecycle_tasks,Lifecycle Tasks>>.
* Task has no actions and no dependencies.

`FROM-CACHE`:: *Task's outputs could be found from a previous execution.*
* Task has outputs restored from the build cache. See <<build_cache.adoc#build_cache,Build Cache>>.

`SKIPPED`:: *Task did not execute its actions.*
* Task has been explicitly excluded from the command-line. See <<command_line_interface.adoc#sec:excluding_tasks_from_the_command_line,Excluding tasks from execution>>.
* Task has an `onlyIf` predicate return false. See <<controlling_task_execution.adoc#sec:using_a_predicate,Using a predicate>>.

`NO-SOURCE`:: *Task did not need to execute its actions.*
* Task has inputs and outputs, but <<incremental_build.adoc#skip-when-empty,no sources>> (i.e., inputs were not found).

[[sec:task_groups]]
== Task group and description

Task groups and descriptions are used to organize and describe tasks.

Groups :: Task groups are used to categorize tasks. When you run `./gradlew tasks`, tasks are listed under their respective groups, making it easier to understand their purpose and relationship to other tasks. Groups are set using the `group` property.

Descriptions :: Descriptions provide a brief explanation of what a task does. When you run `./gradlew tasks`, the descriptions are shown next to each task, helping you understand its purpose and how to use it. Descriptions are set using the `description` property.

Let's consider a basic Java application as an example.
The build contains a subproject called `app`.

Let's list the available tasks in `app` at the moment:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app: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.
----

Here, the `:run` task is part of the `Application` group with the description `Runs this project as a JVM application`.
In code, it would look something like this:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
tasks.register("run") {
    group = "Application"
    description = "Runs this project as a JVM application."
}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source,groovy]
----
tasks.register("run") {
    group = "Application"
    description = "Runs this project as a JVM application."
}
----
=====
====

[[sec:hidden_tasks]]
== Private and hidden tasks

Gradle doesn't support marking a task as _private_.

However, tasks will only show up when running `:tasks` if `task.group` is set or no other task depends on it.

For instance, the following task will not appear when running `./gradlew :app:tasks` because it does not have a group; it is called a _hidden_ task:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
tasks.register("helloTask") {
    println("Hello")
}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source,groovy]
----
tasks.register("helloTask") {
    println 'Hello'
}
----
=====
====

Although `helloTask` is not listed, it can still be executed by Gradle:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app: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.
----

Let's add a group to the same task:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
tasks.register("helloTask") {
    group = "Other"
    description = "Hello task"
    println("Hello")
}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source,groovy]
----
tasks.register("helloTask") {
    group = "Other"
    description = "Hello task"
    println 'Hello'
}
----
=====
====

Now that the group is added, the task is visible:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app: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.

Other tasks
-----------
helloTask - Hello task
----

In contrast, `./gradlew tasks --all` will show all tasks; _hidden_ and _visible_ tasks are listed.

[[sec:grouping_tasks]]
== Grouping tasks

If you want to customize which tasks are shown to users when listed, you can group tasks and set the visibility of each group.

NOTE: Remember, even if you _hide_ tasks, they are still available, and Gradle can still run them.

Let's start with an example built by Gradle `init` for a Java application with multiple subprojects.
The project structure is as follows:

====
[.multi-language-sample]
=====
[source,kotlin]
----
gradle-project
├── app
│   ├── build.gradle.kts
│   └── src                 // some java code
│       └── ...
├── utilities
│   ├── build.gradle.kts
│   └── src                 // some java code
│       └── ...
├── list
│   ├── build.gradle.kts
│   └── src                 // some java code
│       └── ...
├── buildSrc
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src                 // common build logic
│       └── ...
├── settings.gradle.kts
├── gradle
├── gradlew
└── gradlew.bat
----
=====
[.multi-language-sample]
=====
[source,groovy]
----
gradle-project
├── app
│   ├── build.gradle
│   └── src             // some java code
│       └── ...
├── utilities
│   ├── build.gradle
│   └── src             // some java code
│       └── ...
├── list
│   ├── build.gradle
│   └── src             // some java code
│       └── ...
├── buildSrc
│   ├── build.gradle
│   ├── settings.gradle
│   └── src             // common build logic
│       └── ...
├── settings.gradle
├── gradle
├── gradlew
└── gradlew.bat
----
=====
====

Run `app:tasks` to see available tasks in the `app` subproject:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app: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.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the classes of the 'main' feature.
testClasses - Assembles test classes.

Distribution tasks
------------------
assembleDist - Assembles the main distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the 'main' feature.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
kotlinDslAccessorsReport - Prints the Kotlin code for accessing the currently available project extensions and conventions.
outgoingVariants - Displays the outgoing variants of project ':app'.
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':app'.
tasks - Displays the tasks runnable from project ':app'.

Verification tasks
------------------
check - Runs all checks.
test - Runs the test suite.
----

If we look at the list of tasks available, even for a standard Java project, it's extensive.
Many of these tasks are rarely required directly by developers using the build.

We can configure the `:tasks` task and limit the tasks shown to a certain group.

Let's create our own group so that all tasks are hidden by default by updating the `app` build script:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
val myBuildGroup = "my app build"               // Create a group name

tasks.register<TaskReportTask>("tasksAll") {    // Register the tasksAll task
group = myBuildGroup
description = "Show additional tasks."
setShowDetail(true)
}

tasks.named<TaskReportTask>("tasks") {          // Move all existing tasks to the group
displayGroup = myBuildGroup
}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source,groovy]
----
def myBuildGroup = "my app build"               // Create a group name

tasks.register("tasksAll", TaskReportTask) {    // Register the tasksAll task
    group = myBuildGroup
    description = "Show additional tasks."
    setShowDetail(true)
}

tasks.named("tasks", TaskReportTask) {          // Move all existing tasks to the group
    displayGroup = myBuildGroup
}
----
=====
====

Now, when we list tasks available in `app`, the list is shorter:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app:tasks

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

My app build tasks
------------------
tasksAll - Show additional tasks.
----

[[sec:task_categories]]
== Task categories

Gradle distinguishes between two categories of tasks:

1. *Lifecycle tasks*
2. *Actionable tasks*

**Lifecycle tasks** define targets you can call, such as `:build` your project.
Lifecycle tasks do not provide Gradle with actions.
They must be _wired_ to actionable tasks.
The <<base_plugin.adoc#base_plugin,`base` Gradle plugin>> only adds lifecycle tasks.

**Actionable tasks** define actions for Gradle to take, such as `:compileJava`, which compiles the Java code of your project.
Actions include creating JARs, zipping files, publishing archives, and much more.
Plugins like the <<java_library_plugin.adoc#java_library_plugin,`java-library` plugin>> adds actionable tasks.

Let's update the build script of the previous example, which is currently an empty file so that our `app` subproject is a Java library:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
plugins {
    id("java-library")
}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source,groovy]
----
plugins {
    id('java-library')
}
----
=====
====

Once again, we list the available tasks to see what new tasks are available:

[source,bash]
----
$ ./gradlew :app:tasks
----
[source,text]
----
> Task :app:tasks

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

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the classes of the 'main' feature.
testClasses - Assembles test classes.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the 'main' feature.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':app'.
dependencies - Displays all dependencies declared in project ':app'.
dependencyInsight - Displays the insight into a specific dependency in project ':app'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of project ':app'.
projects - Displays the sub-projects of project ':app'.
properties - Displays the properties of project ':app'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':app'.
tasks - Displays the tasks runnable from project ':app'.

Verification tasks
------------------
check - Runs all checks.
test - Runs the test suite.
----

We see that many new tasks are available such as `jar` and `testClasses`.

Additionally, the `java-library` plugin has wired actionable tasks to lifecycle tasks.
If we call the `:build` task, we can see several tasks have been executed, including the `:app:compileJava` task.

[source,bash]
----
$ ./gradlew :app:build
----
[source,text]
----
> Task :app:compileJava
> Task :app:processResources NO-SOURCE
> Task :app:classes
> Task :app:jar
> Task :app:assemble
> Task :app:compileTestJava
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses
> Task :app:test
> Task :app:check
> Task :app:build
----

The actionable `:compileJava` task is wired to the lifecycle `:build` task.

[[sec:incremental_tasks]]
== Incremental tasks

A key feature of Gradle tasks is their incremental nature.

Gradle can reuse results from prior builds.
Therefore, if we've built our project before and made only minor changes, rerunning `:build` will not require Gradle to perform extensive work.

For example, if we modify only the test code in our project, leaving the production code unchanged, executing the build will solely recompile the test code.
Gradle marks the tasks for the production code as `UP-TO-DATE`, indicating that it remains unchanged since the last successful build:

[source,bash]
----
$ ./gradlew :app:build
----
[source,text]
----
gradle@MacBook-Pro temp1 % ./gradlew :app:build
> 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:assemble UP-TO-DATE
> Task :app:compileTestJava
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses
> Task :app:test
> Task :app:check UP-TO-DATE
> Task :app:build UP-TO-DATE
----

[[sec:caching_tasks]]
== Caching tasks

Gradle can reuse results from past builds using the build cache.

To enable this feature, activate the build cache by using the `--build-cache` <<command_line_interface#command_line_interface,command line>> parameter or by setting `org.gradle.caching=true` in your <<build_environment#sec:gradle_configuration_properties,`gradle.properties`>> file.

This optimization has the potential to accelerate your builds significantly:

[source,bash]
----
$ ./gradlew :app:clean :app:build --build-cache
----
[source,text]
----
> Task :app:compileJava FROM-CACHE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar
> Task :app:assemble
> Task :app:compileTestJava FROM-CACHE
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses UP-TO-DATE
> Task :app:test FROM-CACHE
> Task :app:check UP-TO-DATE
> Task :app:build
----

When Gradle can fetch outputs of a task from the cache, it labels the task with `FROM-CACHE`.

The build cache is handy if you switch between branches regularly.
Gradle supports both local and remote build caches.

[[sec:developing_tasks]]
== Developing tasks

When developing Gradle tasks, you have two choices:

1. Use an existing Gradle task type such as `Zip`, `Copy`, or `Delete`
2. Create your own Gradle task type such as `MyResolveTask` or `CustomTaskUsingToolchains`.

Task types are simply subclasses of the Gradle link:{javadocPath}/org/gradle/api/Task.html[`Task`] class.

With Gradle tasks, there are three states to consider:

1. *Registering* a task - using a task (implemented by you or provided by Gradle) in your build logic.
2. *Configuring* a task - defining inputs and outputs for a registered task.
3. *Implementing* a task - creating a custom task class (i.e., custom class type).

*Registration* is commonly done with the link:{javadocPath}/org/gradle/api/tasks/TaskContainer.html#register-java.lang.String-java.lang.Class-[`register()`] method. +
*Configuring* a task is commonly done with the link:{javadocPath}/org/gradle/api/tasks/TaskCollection.html#named-java.lang.String-java.lang.Class-[`named()`] method. +
*Implementing* a task is commonly done by extending Gradle's link:{javadocPath}/org/gradle/api/DefaultTask.html[`DefaultTask`] class:

====
[.multi-language-sample]
=====
[source,kotlin]
----
tasks.register<Copy>("myCopy")                              // <1>

tasks.named<Copy>("myCopy") {                               // <2>
    from("resources")
    into("target")
    include("**/*.txt", "**/*.xml", "**/*.properties")
}

abstract class MyCopyTask : DefaultTask() {                 // <3>
    @TaskAction
    fun copyFiles() {
        val sourceDir = File("sourceDir")
        val destinationDir = File("destinationDir")
        sourceDir.listFiles()?.forEach { file ->
            if (file.isFile && file.extension == "txt") {
                file.copyTo(File(destinationDir, file.name))
            }
        }
    }
}
----
<1> Register the `myCopy` task of type `Copy` to let Gradle know we intend to use it in our build logic.
<2> Configure the registered `myCopy` task with the inputs and outputs it needs according to its link:{javadocPath}/org/gradle/api/tasks/Copy.html[API].
<3> Implement a custom task type called `MyCopyTask` which extends `DefaultTask` and defines the `copyFiles` task action.
=====
[.multi-language-sample]
=====
[source,groovy]
----
tasks.register("myCopy", Copy)                              // <1>

tasks.named("myCopy", Copy) {                               // <2>
    from "resources"
    into "target"
    include "**/*.txt", "**/*.xml", "**/*.properties"
}

abstract class MyCopyTask extends DefaultTask {             // <3>
    @TaskAction
    void copyFiles() {
        fileTree('sourceDir').matching {
            include '**/*.txt'
        }.forEach { file ->
            file.copyTo(file.path.replace('sourceDir', 'destinationDir'))
        }
    }
}
----
<1> Register the `myCopy` task of type `Copy` to let Gradle know we intend to use it in our build logic.
<2> Configure the registered `myCopy` task with the inputs and outputs it needs according to its link:{javadocPath}/org/gradle/api/tasks/Copy.html[API].
<3> Implement a custom task type called `MyCopyTask` which extends `DefaultTask` and defines the `copyFiles` task action.
=====
====

[[sec:defining_tasks]]
=== 1. Registering tasks

You define actions for Gradle to take by registering tasks in build scripts or plugins.

Tasks are defined using strings for task names:

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

In the example above, the task is added to the link:{javadocPath}/org/gradle/api/tasks/TaskCollection.html[`TasksCollection`] using the link:{javadocPath}/org/gradle/api/tasks/TaskContainer.html#register-java.lang.String-java.lang.Class-[`register()`] method in link:{javadocPath}/org/gradle/api/tasks/TaskContainer.html[`TaskContainer`].

[[sec:configuring_tasks]]
=== 2. Configuring tasks

Gradle tasks must be configured to complete their action(s) successfully.
If a task needs to ZIP a file, it must be configured with the file name and location.
You can refer to the link:{javadocPath}/org/gradle/api/tasks/bundling/Zip.html[API] for the Gradle `Zip` task to learn how to configure it appropriately.

Let’s look at the `Copy` task provided by Gradle as an example.
We first register a task called `myCopy` of type `Copy` in the build script:

====
include::sample[dir="snippets/tasks/configureUsingBlock/kotlin",files="build.gradle.kts[tags=declare-task]"]
include::sample[dir="snippets/tasks/configureUsingBlock/groovy",files="build.gradle[tags=declare-task]"]
====

This registers a copy task with no default behavior.
Since the task is of type `Copy`, a Gradle supported task type, it can be configured using its link:{javadocPath}/org/gradle/api/tasks/Copy.html[API].

The following examples show several ways to achieve the same configuration:

==== 1. Using the `named()` method:

Use `named()` to configure an existing task registered elsewhere:

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

==== 2. Using a configuration block:

Use a block to configure the task immediately upon registering it:

====
include::sample[dir="snippets/tasks/defineAndConfigure/kotlin",files="build.gradle.kts[tags=no-description]"]
include::sample[dir="snippets/tasks/defineAndConfigure/groovy",files="build.gradle[tags=no-description]"]
====

==== 3. Name method as call:

A popular option that is only supported in Groovy is the shorthand notation:

[source,groovy]
----
copy {
    from("resources")
    into("target")
    include("**/*.txt", "**/*.xml", "**/*.properties")
}
----

NOTE: This option breaks task configuration avoidance and is not recommended!

Regardless of the method chosen, the task is configured with the name of the files to be copied and the location of the files.

[[sec:implementing_tasks]]
=== 3. Implementing tasks

Gradle provides many task types including `Delete`, `Javadoc`, `Copy`, `Exec`, `Tar`, and `Pmd`.
You can implement a custom task type if Gradle does not provide a task type that meets your build logic needs.

To create a custom task class, you extend link:{javadocPath}/org/gradle/api/DefaultTask.html[`DefaultTask`] and make the extending class abstract:

====
[.multi-language-sample]
=====
.app/build.gradle.kts
[source,kotlin]
----
abstract class MyCopyTask : DefaultTask() {

}
----
=====
[.multi-language-sample]
=====
.app/build.gradle
[source,groovy]
----
abstract class MyCopyTask extends DefaultTask {

}
----
=====
====
