Chapter 6. Build Script Basics

6.1. Projects and tasks

Everything in Gradle sits on top of two basic concepts: projects 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.

Each project is made up of 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.

For now, we will look at defining some simple tasks in a build with one project. Later chapters will look at
working with multiple projects and more about working with projects and tasks.

6.2. Hello world

You run a Gradle build using the gradle command. The gradle command
looks for a file called build.gradle in the current directory.
[2]
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.

To try this out, create the following build script named build.gradle.

Example 6.1. Your first build script

build.gradle

task hello {
doLast {
println 'Hello world!'
}
}

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

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 Chapter 18, Logging for more details about the command-line options which affect Gradle's output.

Example 6.2. Execution of a build script

Output of gradle -q hello

> gradle -q hello
Hello world!

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
closure containing some Groovy 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.

6.3. A shortcut task definition

There is a shorthand way to define a task like our hello task above, which is more
concise.

Example 6.3. A task definition shortcut

build.gradle

task hello << {
println 'Hello world!'
}

Again, this defines a task called hello with a single closure to execute.
We will use this task definition style throughout the user guide.

6.4. Build scripts are code

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

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. The << operator is simply an
alias for doLast.

6.8. Shortcut notations

As you might have noticed in the previous examples, there is a convenient notation for accessing an
existing task. Each task is available as a property of the build script:

This enables very readable code, especially when using the tasks provided by the plugins,
like the compile task.

6.9. Extra task properties

You can add your own properties to a task. To add a property named myProperty,
set ext.myProperty to an initial value. From that point on, the property can be read
and set like a predefined task property.

6.10. 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. From the example below, you can learn how to execute Ant tasks and how to access Ant properties:

> gradle -q loadfile
*** agile.manifesto.txt ***
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
*** gradle.manifesto.txt ***
Make the impossible possible, make the possible easy and make the easy elegant.
(inspired by Moshe Feldenkrais)

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 Chapter 60, Organizing Build Logic.

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

6.13. Configure by DAG

As we later describe in full detail (see Chapter 56, The Build Lifecycle), Gradle has a
configuration phase and an execution phase. After the configuration phase, Gradle knows all tasks that should
be executed. Gradle offers you a hook to make use of this information. A use-case for this would be to check
if the release task is among the tasks to be executed. Depending on this, you can assign different values
to some variables.

In the following example, execution of the distribution and release tasks results in different value of the version variable.

The important thing is that whenReady affects the release task before the release task is executed.
This works even when the release task is not the primary task (i.e., the task passed to the gradle command).

6.14. Where to next?

In this chapter, we have had a first look at tasks. But this is not the end of the story for tasks. If you want to jump into more of the details,
have a look at Chapter 15, More about Tasks.