# Chapter 13. Writing Build Scripts

This chapter looks at some of the details of writing a build script.

## 13.1. The Gradle build language

Gradle provides a domain specific language, or DSL, for describing builds. This build language is based on Groovy, with some additions to make it easier to describe a build.

## 13.2. The Project API

In the tutorial in Chapter 7, Java Quickstart we used, for example, the `apply()` method. Where does this method come from? We said earlier that the build script defines a project in Gradle. For each project in the build, Gradle creates an instance of type `Project` and associates this `Project` object with the build script. As the build script executes, it configures this `Project` object:

### Getting help writing build scripts

Don't forget that your build script is simply Groovy code that drives the Gradle API. And the `Project` interface is your starting point for accessing everything in the Gradle API. So, if you're wondering what 'tags' are available in your build script, you can start with the documentation for the `Project` interface.

- Any method you call in your build script, which is not defined in the build script, is delegated to the `Project` object.

- Any property you access in your build script, which is not defined in the build script, is delegated to the `Project` object.

Let's try this out and try to access the `name` property of the `Project` object.

Example 13.1. Accessing property of the Project object

`build.gradle`

    println name
    println project.name

Output of `gradle -q check`

    > gradle -q check
    projectApi
    projectApi

Both `println` statements print out the same property. The first uses auto-delegation to the `Project` object, for properties not defined in the build script. The other statement uses the `project` property available to any build script, which returns the associated `Project` object. Only if you define a property or a method which has the same name as a member of the `Project` object, you need to use the `project` property.

### 13.2.1. Standard project properties

The `Project` object provides some standard properties, which are available in your build script. The following table lists a few of the commonly used ones.

Table 13.1. Project Properties

Name | Type | Default Value
`project` | `Project` | The `Project` instance
`name` | `String` | The name of the project directory.
`path` | `String` | The absolute path of the project.
`description` | `String` | A description for the project.
`projectDir` | `File` | The directory containing the build script.
`buildDir` | `File` | ``projectDir`/build`
`group` | `Object` | `unspecified`
`version` | `Object` | `unspecified`
`ant` | `AntBuilder` | An `AntBuilder` instance

## 13.3. The Script API

When Gradle executes a script, it compiles the script into a class which implements `Script`. This means that all of the properties and methods declared by the `Script` interface are available in your script.

## 13.4. Declaring variables

There are two kinds of variables that can be declared in a build script: local variables and extra properties.

### 13.4.1. Local variables

Local variables are declared with the `def` keyword. They are only visible in the scope where they have been declared. Local variables are a feature of the underlying Groovy language.

Example 13.2. Using local variables

`build.gradle`

    def dest = "dest"

    task copy(type: Copy) {
        from "source"
        into dest
    }

### 13.4.2. Extra properties

All enhanced objects in Gradle's domain model can hold extra user-defined properties. This includes, but is not limited to, projects, tasks, and source sets. Extra properties can be added, read and set via the owning object's `ext` property. Alternatively, an `ext` block can be used to add multiple properties at once.

Example 13.3. Using extra properties

`build.gradle`

    apply plugin: "java"

    ext {
        springVersion = "3.1.0.RELEASE"
        emailNotification = "build@master.org"
    }

    sourceSets.all { ext.purpose = null }

    sourceSets {
        main {
            purpose = "production"
        }
        test {
            purpose = "test"
        }
        plugin {
            purpose = "production"
        }
    }

    task printProperties << {
        println springVersion
        println emailNotification
        sourceSets.matching { it.purpose == "production" }.each { println it.name }
    }

Output of `gradle -q printProperties`

    > gradle -q printProperties
    3.1.0.RELEASE
    build@master.org
    main
    plugin

In this example, an `ext` block adds two extra properties to the `project` object. Additionally, a property named `purpose` is added to each source set by setting `ext.purpose` to `null` (`null` is a permissible value). Once the properties have been added, they can be read and set like predefined properties.

By requiring special syntax for adding a property, Gradle can fail fast when an attempt is made to set a (predefined or extra) property but the property is misspelled or does not exist. [5] Extra properties can be accessed from anywhere their owning object can be accessed, giving them a wider scope than local variables. Extra properties on a parent project are visible from subprojects.

For further details on extra properties and their API, see `ExtraPropertiesExtension`.

## 13.5. Some Groovy basics

Groovy provides plenty of features for creating DSLs, and the Gradle build language takes advantage of these. Understanding how the build language works will help you when you write your build script, and in particular, when you start to write customs plugins and tasks.

### 13.5.1. Groovy JDK

Groovy adds lots of useful methods to JVM classes. For example, `Iterable` gets an `each` method, which iterates over the elements of the `Iterable`:

Example 13.4. Groovy JDK methods

`build.gradle`

    // Iterable gets an each() method
    configurations.runtime.each { File f -> println f }

Have a look at http://groovy.codehaus.org/groovy-jdk/ for more details.

### 13.5.2. Property accessors

Groovy automatically converts a property reference into a call to the appropriate getter or setter method.

Example 13.5. Property accessors

`build.gradle`

    // Using a getter method
    println project.buildDir
    println getProject().getBuildDir()

    // Using a setter method
    project.buildDir = 'target'
    getProject().setBuildDir('target')

### 13.5.3. Optional parentheses on method calls

Parentheses are optional for method calls.

Example 13.6. Method call without parentheses

`build.gradle`

    test.systemProperty 'some.prop', 'value'
    test.systemProperty('some.prop', 'value')

### 13.5.4. List and map literals

Groovy provides some shortcuts for defining `List` and `Map` instances.

Example 13.7. List and map literals

`build.gradle`

    // List literal
    test.includes = ['org/gradle/api/**', 'org/gradle/internal/**']

    List<String> list = new ArrayList<String>()
    list.add('org/gradle/api/**')
    list.add('org/gradle/internal/**')
    test.includes = list

    // Map literal
    apply plugin: 'java'

    Map<String, String> map = new HashMap<String, String>()
    map.put('plugin', 'java')
    apply(map)

### 13.5.5. Closures as the last parameter in a method

The Gradle DSL uses closures in many places. You can find out more about closures here. When the last parameter of a method is a closure, you can place the closure after the method call:

Example 13.8. Closure as method parameter

`build.gradle`

    repositories {
        println "in a closure"
    }
    repositories() { println "in a closure" }
    repositories({ println "in a closure" })

### 13.5.6. Closure delegate

Each closure has a `delegate` object, which Groovy uses to look up variable and method references which are not local variables or parameters of the closure. Gradle uses this for configuration closures, where the `delegate` object is set to the object to be configured.

Example 13.9. Closure delegates

`build.gradle`

    dependencies {
        assert delegate == project.dependencies
        compile('junit:junit:4.8.2')
        delegate.compile('junit:junit:4.8.2')
    }

[5] As of Gradle 1.0-milestone-9, using `ext` to add extra properties is strongly encouraged but not yet enforced. Therefore, Gradle will not fail when an unknown property is set. However, it will print a warning.