Gradle Release Notes

Version 4.0-milestone-1

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Public type for representing lazily evaluated properties

Because Gradle's build lifecycle clearly distinguishes between configuration phase and execution phase the evaluation of property values has to be deferred under certain conditions to properly capture end user input. A typical use case is the mapping of extension properties to custom task properties as part of a plugin implementation. In the past, many plugin developers were forced to solve evaluation order problems by using the concept of convention mapping, an internal API in Gradle subject to change.

This release of Gradle introduces a mutable type to the public API representing a property with state. The relevant interface is called PropertyState. An instance of this type can be created through the method Project.property(Class).

The following example demonstrates how to use the property state API to map an extension property to a custom task property without running into evaluation ordering issues:

apply plugin: GreetingPlugin

greeting {
    message = 'Hi from Gradle'
    outputFiles = files('a.txt', 'b.txt')
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Add the 'greeting' extension object
        def extension = project.extensions.create('greeting', GreetingPluginExtension, project)
        // Add a task that uses the configuration
        project.tasks.create('hello', Greeting) {
            message = extension.messageProvider
            outputFiles = extension.outputFiles
        }
    }
}

class GreetingPluginExtension {
    final PropertyState<String> message
    final ConfigurableFileCollection outputFiles

    GreetingPluginExtension(Project project) {
        message = project.property(String)
        setMessage('Hello from GreetingPlugin')
        outputFiles = project.files()
    }

    String getMessage() {
        message.get()
    }

    Provider<String> getMessageProvider() {
        message
    }

    void setMessage(String message) {
        this.message.set(message)
    }

    FileCollection getOutputFiles() {
        outputFiles
    }

    void setOutputFiles(FileCollection outputFiles) {
        this.outputFiles.setFrom(outputFiles)
    }
}

class Greeting extends DefaultTask {
    final PropertyState<String> message = project.property(String)
    final ConfigurableFileCollection outputFiles = project.files()

    @Input
    String getMessage() {
        message.get()
    }

    void setMessage(String message) {
        this.message.set(message)
    }

    void setMessage(Provider<String> message) {
        this.message.set(message)
    }

    FileCollection getOutputFiles() {
        outputFiles
    }

    void setOutputFiles(FileCollection outputFiles) {
        this.outputFiles.setFrom(outputFiles)
    }

    @TaskAction
    void printMessage() {
        getOutputFiles().each {
            it.text = getMessage()
        }
    }
}

Build Cache Improvements

Remote build cache honors --offline

When running with --offline, Gradle will disable the remote build cache.

Detecting overlapping task outputs

When two tasks write into the same directory, Gradle will now disable task output caching for the second task to execute. This prevents issues where task outputs for a different task are captured for the wrong build cache key. On subsequent builds, if overlapping outputs are detected, Gradle will also prevent you from loading task outputs from the cache if it would remove existing outputs from another task.

You can diagnose overlapping task output issues by running Gradle at the --info log level. If you are using Gradle Build Scans, the same detailed reason for disabling task output caching will be included in the build timeline.

Stricter validation of task properties

When a plugin is built with the Java Gradle Plugin Development Plugin, custom task types declared in the plugin will go through validation. In Gradle 4.0, additional problems are now detected.

A warning is shown when: * a task has a property without an input or output annotation (this might indicate a forgotten input or output), * a task has @Input on a File property (instead of using @InputFile of @InputDirectory), * a task declares conflicting types for a property (say, both @InputFile and @InputDirectory), * a cacheable task declares a property without specifying @PathSensitive. In such a case, we default to ABSOLUTE path sensitivity, which will prevent the task's outputs from being shared across different users via a shared cache.

For more info on using task property annotations, see the user guide chapter.

Parallel download of dependencies

Gradle will now download dependencies from remote repositories in parallel. It will also make sure that if you build multiple projects in parallel (with --parallel) and that 2 projects try to download the same dependency at the same time, that dependency wouldn't be downloaded twice.

Default Zinc compiler upgraded from 0.3.7 to 0.3.13

This will take advantage of performance optimizations in the latest Zinc releases.

Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User guide section on the “Feature Lifecycle” for more information.

The following are the features that have been promoted in this Gradle release.

Fixed issues

Deprecations

Features that have become superseded or irrelevant due to the natural evolution of Gradle become deprecated, and scheduled to be removed in the next major Gradle version (Gradle 4.0). See the User guide section on the “Feature Lifecycle” for more information.

The following are the newly deprecated items in this Gradle release. If you have concerns about a deprecation, please raise it via the Gradle Forums.

Potential breaking changes

maven-publish and ivy-publish mirror multi-project behavior

When using the java plugin, all compile and runtime dependencies will now be mapped to the compile scope, i.e. "leaked" into the consumer's compile classpath. This is in line with how these legacy configurations work in multi-project builds. We strongly encourage you to use the api(java-library plugin only), implementation and runtimeOnly configurations instead. These are mapped as expected, with api being exposed to the consumer's compile classpath and implementation and runtimeOnly only available on the consumer's runtime classpath.

Changes to previously deprecated APIs

The deprecated jetty plugin has been removed. We recommend using the Gretty plugin for developing Java web applications. The deprecated pluginRepositories block for declaring custom plugin repositories has been removed in favor of pluginManagement.repositories.

Adding copy specs is not allowed during task execution of a AbstractCopyTask task

You can no longer add copy specs to a copy (like Copy and Sync) or archive task (like Zip and Tar) when the task is executing. Tasks that used this behavior could produce incorrect results and not honor task dependencies.

Starting with Gradle 4.0, builds that rely on this behavior will fail. Previously, Gradle only failed if the task was cacheable and emitted a warning otherwise.

```groovy // This task adds a copy spec during the execution phase. task copy(type: Copy) { from ("some-dir") into ("build/output")

doFirst {
    // Adding copy specs during runtime is not allowed anymore
    // The build will fail with 4.0
    from ("some-other-dir") {
        exclude "non-existent-file"
    }
}

} ```

External contributions

We would like to thank the following community members for making contributions to this release of Gradle.

We love getting contributions from the Gradle community. For information on contributing, please see gradle.org/contribute.

Known issues

Known issues are problems that were discovered post release that are directly related to changes made in this release.