// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.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.

[[tutorial_using_tasks]]
= Build Script Basics

This chapter introduces you to the basics of writing Gradle build scripts.
It uses toy examples to explain basic functionality of Gradle, which is helpful to get an understanding of the basic concepts.
Especially if you move to Gradle from other build tools like Ant and want to understand differences and advantages.

However, to get started with a standard project setup, you don't even need to go into these concepts in detail.
Instead, you can have a quick hands-on introduction, through our <<getting_started.adoc#try_gradle,step-by-step samples>>.

[[sec:projects_and_tasks]]
== Projects, plugins and tasks

Every Gradle build is made up of one or more _projects_.
What a project represents depends on what it is that you are doing with Gradle.
For example, a project might represent a library JAR or a web application.
It might represent a distribution ZIP assembled from the JARs produced by other projects.
A project does not necessarily represent a thing to be built.
It might represent a thing to be done, such as deploying your application to staging or production environments.
Don't worry if this seems a little vague for now.
Gradle's build-by-convention support adds a more concrete definition for what a project is.

The work that Gradle can do on a project is defined by one or more _tasks_.
A task represents some atomic piece of work which a build performs.
This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.

Typically, tasks are provided by <<plugins.adoc#sec:plugins_block,applying a plugin>> so that you do not have to define them yourself.
Still, to give you an idea of what a taks is, we will look at defining some simple tasks in a build with one project in this chapter.

[[sec:hello_world]]
== Hello world

[.multi-language-text.lang-groovy]
You run a Gradle build using the `gradle` command. The `gradle` command looks for a file called `build.gradle` in the current directory.footnote:[There are command line switches to change this behavior. See <<command_line_interface.adoc#command_line_interface,Command-Line Interface>>)] We call this `build.gradle` file a _build script_, although strictly speaking it is a build configuration script, as we will see later. The build script defines a project and its tasks.

[.multi-language-text.lang-groovy]
To try this out, create the following build script named `build.gradle`.

[.multi-language-text.lang-kotlin]
You run a Gradle build using the `gradle` command. The `gradle` command looks for a file called `build.gradle.kts` in the current directory.footnote:[There are command line switches to change this behavior. See <<command_line_interface.adoc#command_line_interface,Command-Line Interface>>)] We call this `build.gradle.kts` file a _build script_, although strictly speaking it is a build configuration script, as we will see later. The build script defines a project and its tasks.

[.multi-language-text.lang-kotlin]
To try this out, create the following build script named `build.gradle.kts`.

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

In a command-line shell, move to the containing directory and execute the build script with `gradle -q hello`:

[TIP]
.What does `-q` do?
====

Most of the examples in this user guide are run with the `-q` command-line option. This suppresses Gradle's log messages, so that only the output of the tasks is shown. This keeps the example output in this user guide a little clearer. You don't need to use this option if you don't want to. See <<logging.adoc#logging,Logging>> for more details about the command-line options which affect Gradle's output.

====

.Execution of a build script
====
.Output of **`gradle -q hello`**
----
> gradle -q hello
include::{snippetsPath}/tutorial/hello/tests/hello.out[]
----
====

What's going on here? This build script defines a single task, called `hello`, and adds an action to it. When you run `gradle hello`, Gradle executes the `hello` task, which in turn executes the action you've provided. The action is simply a block containing some code to execute.

If you think this looks similar to Ant's targets, you would be right. Gradle tasks are the equivalent to Ant targets, but as you will see, they are much more powerful. We have used a different terminology than Ant as we think the word _task_ is more expressive than the word _target_. Unfortunately this introduces a terminology clash with Ant, as Ant calls its commands, such as `javac` or `copy`, tasks. So when we talk about tasks, we _always_ mean Gradle tasks, which are the equivalent to Ant's targets. If we talk about Ant tasks (Ant commands), we explicitly say _Ant task_.

[[sec:build_scripts_are_code]]
== Build scripts are code

Gradle's build scripts give you the full power of Groovy and Kotlin. As an appetizer, have a look at this:

.Using Groovy or Kotlin in Gradle's tasks
====
include::sample[dir="snippets/tutorial/upper/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/upper/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q upper`**
----
> gradle -q upper
include::{snippetsPath}/tutorial/upper/tests/upper.out[]
----
====

or

.Using Groovy or Kotlin in Gradle's tasks
====
include::sample[dir="snippets/tutorial/count/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/count/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q count`**
----
> gradle -q count
include::{snippetsPath}/tutorial/count/tests/count.out[]
----
====


[[sec:task_dependencies]]
== Task dependencies

As you probably have guessed, you can declare tasks that depend on other tasks.

.Declaration of task that depends on other task
====
include::sample[dir="snippets/tutorial/intro/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/intro/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q intro`**
----
> gradle -q intro
include::{snippetsPath}/tutorial/intro/tests/intro.out[]
----
====

To add a dependency, the corresponding task does not need to exist.

.Lazy dependsOn - the other task does not exist (yet)
====
include::sample[dir="snippets/tutorial/lazyDependsOn/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/lazyDependsOn/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q taskX`**
----
> gradle -q taskX
include::{snippetsPath}/tutorial/lazyDependsOn/tests/lazyDependsOn.out[]
----
====

The dependency of `taskX` to `taskY` may be declared before `taskY` is defined.
Task dependencies are discussed in more detail in <<more_about_tasks.adoc#sec:adding_dependencies_to_tasks,Adding dependencies to a task>>.

[[sec:dynamic_tasks]]
== Flexible task registration

The power of Groovy or Kotlin can be used for more than defining what a task does
For example, you can use it to register multiple tasks of the same type in a loop.

.Felxible registration of a task
====
include::sample[dir="snippets/tutorial/dynamic/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/dynamic/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q task1`**
----
> gradle -q task1
include::{snippetsPath}/tutorial/dynamic/tests/dynamic.out[]
----
====


[[sec:manipulating_existing_tasks]]
== Manipulating existing tasks

Once tasks are registered, they can be accessed via an _API_.
For instance, you could use this to dynamically add dependencies to a task, at runtime.
Ant doesn't allow anything like this.

.Accessing a task via API - adding a dependency
====
include::sample[dir="snippets/tutorial/dynamicDepends/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/dynamicDepends/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q task0`**
----
> gradle -q task0
include::{snippetsPath}/tutorial/dynamicDepends/tests/dynamicDepends.out[]
----
====

Or you can add behavior to an existing task.

.Accessing a task via API - adding behaviour
====
include::sample[dir="snippets/tutorial/helloEnhanced/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/helloEnhanced/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q hello`**
----
> gradle -q hello
include::{snippetsPath}/tutorial/helloEnhanced/tests/helloEnhanced.out[]
----
====

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.

[[sec:using_ant_tasks_tutorial]]
== Using Ant Tasks

Ant tasks are first-class citizens in Gradle. Gradle provides excellent integration for Ant tasks by simply relying on Groovy. Groovy is shipped with the fantastic `AntBuilder`. Using Ant tasks from Gradle is as convenient and more powerful than using Ant tasks from a `build.xml` file. And it is usable from Kotlin too. From the example below, you can learn how to execute Ant tasks and how to access Ant properties:

.Using AntBuilder to execute ant.loadfile target
====
include::sample[dir="snippets/tutorial/antLoadfile/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/antLoadfile/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q loadfile`**
----
> gradle -q loadfile
include::{snippetsPath}/tutorial/antLoadfile/tests/antLoadfile.out[]
----
====

There is lots more you can do with Ant in your build scripts. You can find out more in <<ant.adoc#ant,Ant>>.

[[sec:using_methods]]
== Using methods

Gradle scales in how you can organize your build logic. The first level of organizing your build logic for the example above, is extracting a method.

.Using methods to organize your build logic
====
include::sample[dir="snippets/tutorial/antLoadfileWithMethod/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/antLoadfileWithMethod/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q loadfile`**
----
> gradle -q loadfile
include::{snippetsPath}/tutorial/antLoadfileWithMethod/tests/antLoadfileWithMethod.out[]
----
====

Later you will see that such methods can be shared among subprojects in multi-project builds. If your build logic becomes more complex, Gradle offers you other very convenient ways to organize it. We have devoted a whole chapter to this. See <<organizing_gradle_projects.adoc#organizing_gradle_projects,Organizing Gradle Projects>>.

[[sec:default_tasks]]
== Default tasks

Gradle allows you to define one or more default tasks that are executed if no other tasks are specified.

.Defining a default task
====
include::sample[dir="snippets/tutorial/defaultTasks/groovy", files="build.gradle[]"]
include::sample[dir="snippets/tutorial/defaultTasks/kotlin", files="build.gradle.kts[]"]

.Output of **`gradle -q`**
----
> gradle -q
include::{snippetsPath}/tutorial/defaultTasks/tests/defaultTasks.out[]
----
====

This is equivalent to running `gradle clean run`. In a multi-project build every subproject can have its own specific default tasks. If a subproject does not specify default tasks, the default tasks of the parent project are used (if defined).

[[sec:build_script_external_dependencies]]
== External dependencies for the build script

NOTE: Instead of manipulating the script classpath directly, it is recommended to <<plugins.adoc#,apply plugins>> that come with their own classpath.
For custom build logic, the recommendation is to <<sharing_build_logic_between_subprojects.adoc#,use a custom plugin>>.

If your build script needs to use external libraries, you can add them to the script's classpath in the build script itself. You do this using the `buildscript()` method, passing in a block which declares the build script classpath.

.Declaring external dependencies for the build script
====
include::sample[dir="snippets/tutorial/externalDependency/groovy", files="build.gradle[tags=declare-classpath]"]
include::sample[dir="snippets/tutorial/externalDependency/kotlin", files="build.gradle.kts[tags=declare-classpath]"]
====

The block passed to the `buildscript()` method configures a link:{javadocPath}/org/gradle/api/initialization/dsl/ScriptHandler.html[ScriptHandler] instance.
You declare the build script classpath by adding dependencies to the `classpath` configuration.
This is the same way you declare, for example, the Java compilation classpath.
You can use any of the <<declaring_dependencies.adoc#sec:dependency-types,dependency types>> except project dependencies.

Having declared the build script classpath, you can use the classes in your build script as you would any other classes on the classpath. The following example adds to the previous example, and uses classes from the build script classpath.

.A build script with external dependencies
====
include::sample[dir="snippets/tutorial/externalDependency/groovy", files="build.gradle[tags=all]"]
include::sample[dir="snippets/tutorial/externalDependency/kotlin", files="build.gradle.kts[tags=all]"]

.Output of **`gradle -q encode`**
----
> gradle -q encode
include::{snippetsPath}/tutorial/externalDependency/tests/externalBuildDependency.out[]
----
====

For multi-project builds, the dependencies declared with a project's `buildscript()` method are available to the build scripts of all its sub-projects.

Build script dependencies may be Gradle plugins. Please consult <<plugins.adoc#plugins,Using Gradle Plugins>> for more information on Gradle plugins.

Every project automatically has a `buildEnvironment` task of type link:{groovyDslPath}/org.gradle.api.tasks.diagnostics.BuildEnvironmentReportTask.html[BuildEnvironmentReportTask] that can be invoked to report on the resolution of the build script dependencies.

== Further Reading

This chapter only scratched the surface with what's possible. Here are some other topics that may be interesting:

- <<authoring_maintainable_build_scripts#authoring_maintainable_build_scripts,Authoring maintainable build scripts>>
- <<organizing_gradle_projects#organizing_gradle_projects,Organizing your Gradle projects>>
- <<custom_tasks#custom_tasks,Writing Custom tasks>>
