Chapter 14. Tutorial - 'This and That'

14.1. Directory creation

There is a common situation where multiple tasks depend on the existence of a directory. Of course you can deal with this by adding a mkdir to the beginning of those tasks, but it's almost always a bad idea to repeat a sequence of code that you only need once (Look up the DRY principle). A better solution would use the dependsOn relationship between tasks to reuse the task to create the directory:

Example 14.1. Directory creation with mkdir

build.gradle

def classesDir = new File('build/classes')

task resources << {
    classesDir.mkdirs()
    // do something
}
task compile(dependsOn: 'resources') << {
    if (classesDir.isDirectory()) {
        println 'The class directory exists. I can operate'
    }
    // do something
}

Output of gradle -q compile

> gradle -q compile
The class directory exists. I can operate

14.2. Gradle properties and system properties

Gradle offers a variety of ways to add properties to your build. With the -D command line option you can pass a system property to the JVM which runs Gradle. The -D option of the gradle command has the same effect as the -D option of the java command.

You can also add properties to your project objects using properties files. You can place a gradle.properties file in the Gradle user home directory (defined by the “GRADLE_USER_HOME” environment variable, which if not set defaults to USER_HOME/.gradle) or in your project directory. For multi-project builds you can place gradle.properties files in any subproject directory. The properties set in a gradle.properties file can be accessed via the project object. The properties file in the user's home directory has precedence over property files in the project directories.

You can also add properties directly to your project object via the -P command line option.

Gradle can also set project properties when it sees specially-named system properties or environment variables. This feature is very useful when you don't have admin rights to a continuous integration server and you need to set property values that should not be easily visible, typically for security reasons. In that situation, you can't use the -P option, and you can't change the system-level configuration files. The correct strategy is to change the configuration of your continuous integration build job, adding an environment variable setting that matches an expected pattern. This won't be visible to normal users on the system. [6]

If the environment variable name looks like ORG_GRADLE_PROJECT_prop=somevalue, then Gradle will set a prop property on your project object, with the value of somevalue. Gradle also supports this for system properties, but with a different naming pattern, which looks like org.gradle.project.prop.

You can also set system properties in the gradle.properties file. If a property name in such a file has the prefix “systemProp.”, like “systemProp.propName”, then the property and its value will be set as a system property, without the prefix. In a multi project build, “systemProp.” properties set in any project except the root will be ignored. That is, only the root project's gradle.properties file will be checked for properties that begin with the “systemProp.” prefix.

Example 14.2. Setting properties with a gradle.properties file

gradle.properties

gradlePropertiesProp=gradlePropertiesValue
sysProp=shouldBeOverWrittenBySysProp
envProjectProp=shouldBeOverWrittenByEnvProp
systemProp.system=systemValue

build.gradle

task printProps << {
    println commandLineProjectProp
    println gradlePropertiesProp
    println systemProjectProp
    println envProjectProp
    println System.properties['system']
}

Output of gradle -q -PcommandLineProjectProp=commandLineProjectPropValue -Dorg.gradle.project.systemProjectProp=systemPropertyValue printProps

> gradle -q -PcommandLineProjectProp=commandLineProjectPropValue -Dorg.gradle.project.systemProjectProp=systemPropertyValue printProps
commandLineProjectPropValue
gradlePropertiesValue
systemPropertyValue
envPropertyValue
systemValue

14.2.1. Checking for project properties

You can access a project property in your build script simply by using its name as you would use a variable. If this property does not exist, an exception will be thrown and the build will fail. If your build script relies on optional properties the user might set, perhaps in a gradle.properties file, you need to check for existence before you access them. You can do this by using the method hasProperty('propertyName') which returns true or false.

14.3. Configuring the project using an external build script

You can configure the current project using an external build script. All of the Gradle build language is available in the external script. You can even apply other scripts from the external script.

Example 14.3. Configuring the project using an external build script

build.gradle

apply from: 'other.gradle'

other.gradle

println "configuring $project"
task hello << {
    println 'hello from other script'
}

Output of gradle -q hello

> gradle -q hello
configuring root project 'configureProjectUsingScript'
hello from other script

14.4. Configuring arbitrary objects

You can configure arbitrary objects in the following very readable way.

Example 14.4. Configuring arbitrary objects

build.gradle

task configure << {
    def pos = configure(new java.text.FieldPosition(10)) {
        beginIndex = 1
        endIndex = 5
    }
    println pos.beginIndex
    println pos.endIndex
}

Output of gradle -q configure

> gradle -q configure
1
5

14.5. Configuring arbitrary objects using an external script

You can also configure arbitrary objects using an external script.

Example 14.5. Configuring arbitrary objects using a script

build.gradle

task configure << {
    def pos = new java.text.FieldPosition(10)
    // Apply the script
    apply from: 'other.gradle', to: pos
    println pos.beginIndex
    println pos.endIndex
}

other.gradle

Output of gradle -q configure

> gradle -q configure
1
5

14.6. Caching

To improve responsiveness Gradle caches all compiled scripts by default. This includes all build scripts, initialization scripts, and other scripts. The first time you run a build for a project, Gradle creates a .gradle directory in which it puts the compiled script. The next time you run this build, Gradle uses the compiled script, if the script has not changed since it was compiled. Otherwise the script gets compiled and the new version is stored in the cache. If you run Gradle with the --recompile-scripts option, the cached script is discarded and the script is compiled and stored in the cache. This way you can force Gradle to rebuild the cache.



[6] Jenkins, Teamcity, or Bamboo are some CI servers which offer this functionality.