Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Gradle writes a build script


May 25, 2021 Gradle


Table of contents


Write a build script

This chapter looks at some of the details of writing build scripts.

Gradle builds the language

Gradle provides a domain-specific language, or DSL, to describe the build. This build language is based on Groovy and is supplemented to make it easy to describe the build.

Project API

In the Java Getting Started tutorial, we used the apply() method. W here does this method come from? W e said earlier that building scripts in Gradle defines a project. I n each project built, Gradle creates an instance of the Project type and associates the Project object in the build script. When the build script executes, it configures this Project object:

  • In a build script, any method you call, if not defined in the build script, is delegated to the Project object.
  • In a build script, any property that you access, if not defined in the build script, is also delegated to the Project object.

Let's try this, try visiting the name property of the Project object.

Access the properties of the Project object

build.gradle

println name
println project.name  

The output of the gradle -q check

> gradle -q check
projectApi
projectApi  

The two println statements print out the same properties. P roperties that are not defined in the build script are automatically delegated to the Project object the first time they are used. O ther statements use the project property that can be accessed in any build script, returning the associated Project object. You need to use the project property only if you define a property or a member of the method Project object with the same name.

The standard project property

Project objects provide some standard properties that are available in the build script. The following table lists several commonly used properties.

Table 13.1. The Project property

Name Type The default
project Project Project instance
name String The name of the project directory.
path String The absolute path of the project.
description String The description of the project.
projectDir File The directory that contains the build script.
buildDir File projectDir /build
group Object 未指定
version Object 未指定
ant AntBuilder AntBuilder instance

Script API

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

Declare the variable

There are two types of variables that can be declared in the build script: local variables and additional properties.

Local variable local

Local variables are declared with the def keyword. T hey can only be accessed within the scope within which they are defined. Local variables are a feature of the bottom layer of the Groovy language.

Example 13.2. Use local variables

build.gradle

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

Additional properties

In Gradle's domain model, all enhanced objects can accommodate additional user-defined properties. T his includes, but is not limited to, projects, tasks, and source sets. A dditional properties can be added, read, and set by the ext property of the object to which they belong. Alternatively, you can use ext blocks to add multiple properties at the same time.

13.3 Examples. Use additional properties

build.gradle

apply plugin: "java"
ext {
    springVersion = "3.1.0.RELEASE"
    emailNotification = "[email protected]"
}
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 }
}   

The output of the gradle -q printProperties

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

In this example, an ext block of code adds two additional properties to the project object. I n addition, by setting ext.purpose to null, an allowed value, a property named purpose is added to each source set. Once properties are added, they can be read and set like predetermined properties.

By adding a property that requires special syntax, Gradle can fail fast when you try to set a (predefined or additional) property, but the property is misspelled or does not exist. A dditional properties can be accessed anywhere they can access the objects to which they belong, which gives them a wider scope than local variables. Additional properties on the parent project can also be accessed in child projects.

For more information about the additional properties and their APIs, see ExtraPropertiesExtension.

Some of Groovy's basics

Groovy provides a number of features for creating DSLs, and the Gradle build language leverages them. Understanding how the build language works will help you write build scripts, especially when you start writing custom plug-ins and tasks.

Groovy JDK

Groovy adds a number of useful methods to JVM classes. For example, the new each method for iterable traverses the elements of iterable:

Groovy JDK's method

build.gradle

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

Property accessor

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

Property accessor

build.gradle

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

The parenthesis is optional for method calls

Parenthesis is optional when a method is called.

Method calls without parentheses

build.gradle

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

List and Map

Groovy provides some quick writing to define List and Map instances.

List and map

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)  

The closure as the last argument of the method

Gradle DSL uses closures in many places. Y ou can see more information about the closed package here. When the last argument of the method is a closure, you can put the closure after the method call:

A closure that is used as a method parameter

build.gradle

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

Closed delegate (delegate)

Each closure has a delegate object that Groovy uses to find references to variables and methods, rather than as local variables or parameters for the closure. Gradle uses it in configuration closures, setting the delegate object as the configured object.

Closure delegate

build.gradle

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