# Chapter 4. Build Script Basics

You run a build using the gradle command. When run, gradle looks for a file called `build.gradle` in the current directory. [5] We call this `build.gradle` file a build script, although strictly speaking it is a build configuration script, as we will see later. In Gradle the build script defines a project. The name of the directory containing the build script is used as the name of the project.

## 4.1. Hello world

In Gradle the most basic building block is the task. The tasks for your build are defined in the build script. To try this out, create the following build script named `build.gradle`.

Example 4.1. The first build script

`build.gradle`

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

In a command-line shell, enter into the containing directory and execute the build script by running `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. You don't need to use this option if you don't want. See Chapter 13, Logging for more details about the command-line options which affect Gradle's output.

Example 4.2. Execution of a build script

Output of `gradle -q hello`

    > gradle -q hello
    Hello world!

What's going on here? This build file 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, well, you are 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.

## 4.2. Build scripts are code

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

Example 4.3. Using Groovy in Gradle's tasks

`build.gradle`

    task upper << {
        String someString = 'mY_nAmE'
        println "Original: " + someString
        println "Upper case: " + someString.toUpperCase()
    }

Output of `gradle -q upper`

    > gradle -q upper
    Original: mY_nAmE
    Upper case: MY_NAME

or

Example 4.4. Using Groovy in Gradle's tasks

`build.gradle`

    task count << {
        4.times { print "$it " }
    }

Output of `gradle -q count`

    > gradle -q count
    0 1 2 3

## 4.3. Task dependencies

As you probably have guessed, you can declare dependencies between your tasks.

Example 4.5. Declaration of dependencies between tasks

`build.gradle`

    task hello << {
        println 'Hello world!'
    }
    task intro(dependsOn: hello) << {
        println "I'm Gradle"
    }

Output of `gradle -q intro`

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

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

Example 4.6. Lazy dependsOn - the other task does not exist (yet)

`build.gradle`

    task taskX(dependsOn: 'taskY') << {
        println 'taskX'
    }
    task taskY << {
        println 'taskY'
    }

Output of `gradle -q taskX`

    > gradle -q taskX
    taskY
    taskX

The dependency of `taskX` to `taskY` is declared before `taskY` is defined. This is very important for multi-project builds. Task dependencies are discussed in more detail in Section 12.4, “Adding dependencies to a task”.

Please notice, that you can't use a shortcut notation (see Section 4.6, “Shortcut notations”) when referring to task, which is not defined yet.

## 4.4. Dynamic tasks

The power of Groovy can be used for more than defining what a task does. For example, you can also use it to dynamically create tasks.

Example 4.7. Dynamic creation of a task

`build.gradle`

    4.times { counter ->
        task "task_$counter" << {
            println "I'm task number $counter"
        }
    }

Output of `gradle -q task_1`

    > gradle -q task_1
    I'm task number 1

## 4.5. Manipulating existing tasks

Once tasks are created they can be accessed via an API. This is different to Ant. For example you can create additional dependencies.

Example 4.8. Accessing a task via API - adding a dependency

`build.gradle`

    4.times { counter ->
        task "task_$counter" << {
            println "I'm task number $counter"
        }
    }
    task_0.dependsOn task_2, task_3

Output of `gradle -q task_0`

    > gradle -q task_0
    I'm task number 2
    I'm task number 3
    I'm task number 0

Or you can add behavior to an existing task.

Example 4.9. Accessing a task via API - adding behaviour

`build.gradle`

    task hello << {
        println 'Hello Earth'
    }
    hello.doFirst {
        println 'Hello Venus'
    }
    hello.doLast {
        println 'Hello Mars'
    }
    hello << {
        println 'Hello Jupiter'
    }

Output of `gradle -q hello`

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

## 4.6. 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:

Example 4.10. Accessing task as a property of the build script

`build.gradle`

    task hello << {
        println 'Hello world!'
    }
    hello.doLast {
        println "Greetings from the $hello.name task."
    }

Output of `gradle -q hello`

    > gradle -q hello
    Hello world!
    Greetings from the hello task.

This enables very readable code, especially when using the out of the box tasks provided by the plugins (e.g. `compile`).

## 4.7. Dynamic task properties

You can assign arbitrary new properties to any task.

Example 4.11. Assigning properties to a task

`build.gradle`

    task myTask
    myTask.myProperty = 'myCustomPropValue'

    task showProps << {
        println myTask.myProperty
    }

Output of `gradle -q showProps`

    > gradle -q showProps
    myCustomPropValue

## 4.8. Using Ant Tasks

Ant tasks are first-class citizens in Gradle. Gradle provides excellent integration for Ant tasks simply by 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. Let's look at an example:

Example 4.12. Using AntBuilder to execute ant.checksum target

`build.gradle`

    task checksum << {
        def files = file('../antChecksumFiles').listFiles().sort()
        files.each { File file ->
            ant.checksum(file: file, property: file.name)
            println "$file.name Checksum: ${ant.properties[file.name]}"
        }
    }

Output of `gradle -q checksum`

    > gradle -q checksum
    agile_manifesto.html Checksum: 2dd24e01676046d8dedc2009a1a8f563
    agile_principles.html Checksum: 659d204c8c7ccb5d633de0b0d26cd104
    dylan_thomas.txt Checksum: 91040ca1cefcbfdc8016b1b3e51f23d3

There is lots more you can do with Ant in your build scripts. You can find out more in Chapter 14, Using Ant from Gradle.

## 4.9. 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.

Example 4.13. Using methods to organize your build logic

`build.gradle`

    task checksum << {
        fileList('../antChecksumFiles').each { File file ->
            ant.checksum(file: file, property: file.name)
            println "$file.name Checksum: ${ant.properties[file.name]}"
        }
    }

    task length << {
        fileList('../antChecksumFiles').each { File file ->
            ant.length(file: file, property: file.name)
            println "$file.name Length: ${ant.properties[file.name]}"
        }
    }

    File[] fileList(String dir) {
        file(dir).listFiles().sort()
    }

Output of `gradle -q checksum`

    > gradle -q checksum
    agile_manifesto.html Checksum: 2dd24e01676046d8dedc2009a1a8f563
    agile_principles.html Checksum: 659d204c8c7ccb5d633de0b0d26cd104
    dylan_thomas.txt Checksum: 91040ca1cefcbfdc8016b1b3e51f23d3

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

## 4.10. Default tasks

Gradle allows you to define one or more default tasks for your build.

Example 4.14. Defining a default tasks

`build.gradle`

    defaultTasks 'clean', 'run'

    task clean << {
        println 'Default Cleaning!'
    }

    task run << {
        println 'Default Running!'
    }

    task other << {
        println "I'm not a default task!"
    }

Output of `gradle -q`

    > gradle -q
    Default Cleaning!
    Default Running!

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

## 4.11. Configure by DAG

As we describe in full detail later (See Chapter 27, 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 part of the tasks to be executed. Depending on this you can assign different values to some variables.

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

Example 4.15. Different outcomes of build depending on chosen tasks

`build.gradle`

    build.taskGraph.whenReady {taskGraph ->
        if (taskGraph.hasTask(':release')) {
            version = '1.0'
        } else {
            version = '1.0-SNAPSHOT'
        }
    }

    task distribution << {
        println "We build the zip with version=$version"
    }
    task release(dependsOn: 'distribution') << {
        println 'We release now'
    }

Output of `gradle -q distribution`

    > gradle -q distribution
    We build the zip with version=1.0-SNAPSHOT

Output of `gradle -q release`

    > gradle -q release
    We build the zip with version=1.0
    We release now

The important thing is, that the fact that the release task has been chosen, has an effect before the release task gets executed. Nor has the release task to be the primary task (i.e. the task passed to the gradle command).

## 4.12. Summary

This is not the end of the story for tasks. So far we have worked with simple tasks. Tasks will be revisited in Chapter 12, More about Tasks and when we look at the Java Plugin in Chapter 16, The Java Plugin.

[5] There are command line switches to change this behavior. See Appendix B, Gradle Command Line)