Dark theme | Light theme

February 25, 2024

Gradle Goodness: Using System Properties Lazily

It is good practice in Gradle to use lazy configuration. This makes builds faster as only configuration values are evaluated when needed. We should try to not let Gradle spend time on evaluating configuration values that will not be used. For example tasks that are not executed could still be configured by Gradle. If we make sure the configuration of these tasks is lazy we can save time.

Gradle gives us a lazy way to get the value of a Java system property. In our build script we can use the providers property of type ProviderFactory and the method systemProperty(String). This method returns a Provider<String> instance that can be used to get the value of a system property in a lazy way. The method systemProperty can also be used with a Provider<String> argument.

In the following example we register a task that prints the value of the Java system property to the console. We use lazy configuration to make sure the value of the system property is only fetched when the task is executed.

tasks {
    register<PrintSystemProperty>("printSystemProperty") {
        // We can use providers.systemProperty(String)
        // to get the value of an Java system property
        // in a lazy way.
        // The argument can also be a Provider<String> type.
        // So at this point the value is not fetched yet,
        // only when the task is executed the actual value
        // of the system property "" is fetched.
        systemProperty = providers.systemProperty("")

// Simple task to print the value of a Java system property.
abstract class PrintSystemProperty : DefaultTask() {
    abstract val systemProperty: Property<String> // Use lazy property.

    fun printSystemPropertyValue() {
        // Only here we actually will get the value
        // for the system property.
$ ./gradlew printSystemProperty

> Task :printSystemProperty

2 actionable tasks: 2 executed

Written with Gradle 8.6.