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 6, 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 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. 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.4.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.2. 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.4.2. Property accessors

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

Example 13.3. 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.4.3. Optional parentheses on method calls

Parentheses are optional for method calls.

Example 13.4. Method call without parentheses

build.gradle

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

13.4.4. List and map literals

Groovy provides some shortcuts for defining List and Map instances.

Example 13.5. 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.4.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.6. Closure as method parameter

build.gradle

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

13.4.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.7. Closure delegates

build.gradle

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