Gradle Release Notes

Version 4.3

The Gradle team is pleased to announce Gradle 4.3.

First and foremost, this release of Gradle features experimental build cache support for C and C++ compilation. This further improves performance of native application builds as it does for the JVM ecosystem. Your feedback will be very helpful to make this feature stable.

C++ Build Cache Build Scan

JVM developers who use annotation processors and the build cache should consider using a new compileJava.options.annotationProcessorGeneratedSourcesDirectory property to make caching more effective.

The Gradle Kotlin DSL moves forward with a v0.12 release (included in Gradle 4.3). It brings Java 9 support, Kotlin 1.1.51, better support for Kotlin dependencies, improved documentation and samples, and more. Heads up Kotlin users: will want to ensure they declare the version of the Kotlin plugin; it no longer defaults to the embedded version.

Kotlin DSL v0.12 example

You can now use the build scan plugin without configuring it in your build. Using the --scan command line flag will automatically apply the latest compatible version of the plugin if it's not already applied.

Several improvements have been made to improve user experience, increase robustness in the face of network problems, and solidify existing APIs.

We hope you will build happiness with Gradle 4.3, and we look forward to your feedback via Twitter or on GitHub.

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Experimental task output caching for C/C++ compilation

This release adds experimental support for using the build cache with C/C++ compilation. To enable this feature the system property org.gradle.caching.native has to be set to true.

// gradle.properties
systemProp.org.gradle.caching.native=true

Some inputs to the compilation tasks are not tracked yet, which can cause false cache hits:

Specify output directory for source files generated by annotation processor

When using annotation processors, Java source may be generated into a directory specified by the -s compiler argument. When the directory is specified via the new compileJava.options.annotationProcessorGeneratedSourcesDirectory property, the generated sources are also stored in and loaded from the build cache.

Convenient use of build scan plugin

This version of Gradle makes it even easier to gain deep insights into your build. By using the command line option --scan, the latest build scan plugin is applied automatically. You will not have to explicitly declare the plugin in your build script or an init script.

Timeouts for HTTP/HTTPS requests

Previous versions of Gradle did not define a timeout for any HTTP/HTTPS requests. Under certain conditions e.g. network problems, unresponsive or overloaded servers this behavior could lead to hanging connections. Gradle now defines connection and socket timeouts for all HTTP/HTTPS requests.

The timeouts are also effective for connections to an HTTP build cache. If connections to the build cache time out then it will be disabled for the rest of the build.

:compileJava
Could not load entry 2b308a0ad9cbd0ad048d4ea84c186f71 for task ':compileJava' from remote build cache: Unable to load entry from 'https://example.com/cache/2b308a0ad9cbd0ad048d4ea84c186f71': Read timed out

BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed
The remote build cache was disabled during the build due to errors.

Blacklist repository in case of repository failures

Upon the event of a timeout (or any repository failures which are not caused by error HTTP status code), Gradle will skip subsequent dependency request to the same repository for the duration of the build.

* What went wrong:
Could not resolve all files for configuration ':deps'.
> Could not resolve group:a:1.0.
  Required by:
      project :
   > Could not resolve group:a:1.0.
      > Could not get resource 'http://localhost:54347/repo/group/a/1.0/a-1.0.pom'.
         > Could not GET 'http://localhost:54347/repo/group/a/1.0/a-1.0.pom'.
            > Read timed out
> Could not resolve group:b:1.0.
  Required by:
      project :
   > Skipped due to earlier error

More use cases supported using the plugins {} block

Non-core plugins already requested using the plugins {} block on a parent project can now be requested in child projects:

// root/settings.gradle
include("subproject")

// root/build.gradle
plugins {
    id("com.example.plugin") version "1.0"
}

// root/subproject/build.gradle
plugins {
    id("com.example.plugin")
}

Plugins from buildSrc can now be requested in child projects:

// root/buildSrc/src/main/groovy/my/MyPlugin.gradle
package my

import org.gradle.api.*

class MyPlugin implement Plugin<Project> {
    @Override
    void apply(Project project) {
        // ...
    }
}

// root/buildSrc/build.gradle
plugins {
    id("groovy")
    id("java-gradle-plugin")
}

gradlePlugin {
    plugins {
        myPlugins {
            id = "my-plugin"
            implementationClass = "my.MyPlugin"
        }
    }
}

dependencies {
    compileOnly(gradleApi())
}

// root/build.gradle
plugins {
    id("my-plugin")
}

See the user guide section on the plugins {} block for more information.

Task input/output annotations and runtime API

Gradle 4.3 introduces some changes that bring task inputs and outputs registered via task annotations (e.g. @InputFile and @OutputDirectory etc.) and the runtime API (think task.inputs.file(...) and task.outputs.dir(...) etc.) closer to each other.

Output directory creation

For task outputs declared via annotations like @OutputDirectory and @OutputFile, Gradle always ensured that the necessary directory exists before executing the task. Starting with version 4.3 Gradle will also create directories for outputs that were registered via the runtime API (e.g. by calling methods like task.outputs.file() and dir()).

task customTask {
    inputs.file "input.txt"
    outputs.file "output-dir/output.txt"
    doLast {
        mkdir "output-dir" // <-- This is now unnecessary
        file("output-dir/output.txt") << file("input.txt")
    }
}

Input/output validation

Task inputs and outputs declared via task property annotations have always been validated by Gradle. If a task declared a non-optional (@Optional) input that was null, Gradle would fail the build with the message:

* What went wrong:
Some problems were found with the configuration of task ':test'.
> No value has been specified for property 'inputDirectory'.

Gradle would also fail the build if an input file or directory did not exist, and also if it expected an output directory, but found a file (or vice versa).

Starting with Gradle 4.3, these validations also happen for properties registered via the runtime API. For backwards compatibility, Gradle will not fail the build if the new validation fails, but produce a warning similar to this:

A problem was found with the configuration of task ':test'. Registering invalid inputs and outputs via TaskInputs and TaskOutputs methods has been deprecated and is scheduled to be removed in Gradle 5.0.
 - No value has been specified for property 'inputDirectory'.

Declaring classpath properties

The @Classpath annotation was introduced in Gradle 3.2 to mark task input properties that should represent a runtime classpath. Gradle 3.4 added @CompileClasspath. However, it was not possible to declare a similar property via the runtime API. With Gradle 4.3 this is now possible. The following examples declare equivalent inputs for customTask.

Using the annotations API:

class CustomTask {
    @Classpath FileCollection classpath

    // ...
}

task customTask(type: CustomTask) {
    classpath = files("lib1.jar", "lib2.jar")
}

Using the runtime API:

task customTask {
    inputs.files("lib1.jar", "lib2.jar")
        .withNormalizer(ClasspathNormalizer)
        .withPropertyName("classpath")
}

Clean up local task state when loading from cache

Using the new @LocalState annotation and task.localState.register(...) API, you can register the local state of a task. Local state files will be cleaned up whenever the task is loaded from cache.

New command line options

New verbose console type

Since Gradle 4.0, task header and outcome won't be displayed by default. Now you can use --console=verbose on the command line or set org.gradle.console to tell Gradle that you want all executed tasks and their outcomes (e.g. UP-TO-DATE) logged at the default LIFECYCLE log level.

Persist console type through Gradle properties

You can now specify a preferred console type in build output by setting org.gradle.console in gradle.properties. Acceptable values are plain, rich, and verbose.

Boolean command line flag inverses

All Command line options that allow to enable a feature (e.g. --no-parallel turns off --parallel) now also have an equivalent for disabling the feature. Some of the existing command line options did not follow the same pattern. With this version of Gradle, every boolean-based command line option also expose a "disabled" option. For more information please review the list of command line options in the user guide.

Improvements for plugin authors

This release of Gradle continues to add features that build on the Provider and Property (previously called PropertyState) concepts added in Gradle 4.0. These types help plugin authors implement tasks and other model elements whose property values are derived from the values of other configurable properties.

Task input directories

In Gradle 4.1, we added APIs that allow a specific task output directory or output file to be wired in as an input for another task, in a way that allows the task dependencies to be inferred and that deals with later changes to the configured locations of those outputs. It is intended to be a more robust, performant and descriptive alternative to using File property types and calls to Task.dependsOn.

It added factory methods on DefaultTask - i.e. newInputFile(), newOutputFile(), and newOutputDirectory() - to allow a task implementation class to create DirectoryProperty instances that represent an output directory, and RegularFileProperty instances that represent an input or output file. When used as an output directory or file property, these instances carry dependency information about the producing task. When used as an input file property, the producing task is tracked as a dependency of the consuming task. Similar support for input files is done using ConfigurableFileCollection and friends, as has been possible for quite a while.

In Gradle 4.3, we added a new factory method on DefaultTask - i.e. newInputDirectory() - to allow a task implementation class to create DirectoryProperty instances that represent an input directory. These instances can be used with the @InputDirectory annotation, which automatically adds a task dependency on the producing task.

Using Provider and Property types

The @Input annotation now supports the Provider<T> and Property<T> types. This allows a task to use these types for input properties that are lazily calculated.

The Groovy DSL now supports setting the value of a property with type Property<Directory> and Property<RegularFile> using a File.

Several methods have been added to Provider to query the current value of the Provider or transform the future value of the Provider.

A new ListProperty<T> type has been added to add conveniences for dealing with properties of type List<T>.

Default JaCoCo updated to version 0.7.9

The JaCoCo plugin has been upgraded to use JaCoCo version 0.7.9 by default.

Support for Windows 10 SDK

Gradle now supports Windows 10 SDK when building native projects. If a Windows 10 SDK is installed, Gradle will automatically discover and use it when a Visual Studio toolchain is selected. Alternatively, a Windows 10 SDK installation directory can be specified when configuring a Visual Studio toolchain.

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

Version ranges are now handled properly

Gradle will now honor version ranges correctly when multiple ranges are intersecting. For example, if a dependency on some-module is found with a range of versions [3,6] and that the same dependency is found transitively with a range of [4,8], Gradle now selects version 6, which is the highest version within both ranges. Previous releases of Gradle used to select version 8.

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 5.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.

Deprecation of old Tooling API version

The following supports are deprecated now and will be removed in Gradle 5.0. You should avoid using them:

Please see Gradle version and Java version compatibility for more details.

Chaining calls on TaskInputs

Chaining calls to TaskInputs.property() and TaskInputs.properties() is now deprecated, similar to how calls to TaskInputs.file() and TaskOutputs.dir() should not be chained since Gradle 3.0.

Don't do this:

task myTask { // Chaining all calls on `TaskInputs` is now deprecated inputs.property("title", title).property("version", "1.0") }

Do this instead:

task myTask { inputs.property("title", title) inputs.property("version", "1.0") }

Calling TaskInputs methods with incorrect parameters

TaskInputs.file() used to accept anything that files() would, and the same was true for dir(). Starting with Gradle 4.3 this behavior is deprecated, and only values that resolve to a single file or directory are accepted.

Do not do this:

task myTask { inputs.dir fileTree(...) }

Do this instead:

task myTask { inputs.files fileTree(...) }

Deprecation of TaskInternal.execute()

In this release we deprecate calling TaskInternal.execute(). Calling task.execute() should never be necessary. There are better ways for re-using task logic, for example by using task dependencies, task rules, extracting a re-usable piece of logic from your task which can be called on its own (e.g. project.copy vs. the Copy task) or using the worker API.

Deprecation of --recompile-scripts

The --recompile-scripts flag would be ignored in some cases. To avoid confusion, we deprecate this flag.

Task destroyables API changes

Instead of the file() and files() methods on TaskDestroyables, now there is a single TaskDestroyables.register() method.

Changes to Provider types

Other deprecations

Potential breaking changes

Changes to incubating Provider types

Incremental build respects order of declared output files

For output properties annotated with @OutputFiles or @OutputDirectories that evaluate to an Iterable, the order of the declared files is now important. In other words, if the property changes from [file1, file2] to [file2, file1] the task will not be up-to-date. Prefer annotating individual properties with @OutputFile and @OutputDirectory if you can, or return a Map annotated with @OutputFiles or @OutputDirectories.

Avoid checking other repositories when dependency resolution in one repository fails

Previous versions of Gradle would fall through to the next repository if resolution in one repository failed. This behaviour might cause potentially nondeterministic resolution result. Now Gradle will explicitly rethrow exceptions which occur in dependency resolution instead of quietly continue to the next repository.

Change in TaskDestroyables API

The TaskDestroyables.getFiles() method is no longer part of the public API.

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.