Gradle Release Notes

Version 3.1

The Gradle team is pleased to announce Gradle 3.1.

Multi-project builds are a powerful feature with one significant constraint: the projects have to be in the same directory hierarchy. This doesn't help if you want to work on code across multiple repositories, for example if you're trying to fix a bug in a third-party open-source library that one of your projects depends on.

Gradle 3.1 now supports this scenario with the introduction of Composite Builds for all users. It's hard to understate just how important this feature is as it provides a whole new way of organizing your projects and builds. There is more work to be done in this area and the feature is currently incubating, but we encourage you to try it out and give us your feedback!

Incremental Build is a similar feature in terms of impact and this release improves the control you have over its up-to-date checks. You can read about the details further down.

As with many previous Gradle releases, you will also benefit from some performance improvements, this time in the form of faster dependency resolution. From testing, Android users specifically could see up to a 50% reduction in configuration and Android Studio sync time.

Build cancellation has improved when using the Daemon. Cancelling a build with Ctrl-C after the first build no longer terminates the Gradle Daemon.

Our Play Framework and Kotlin build script users will also be happy as 3.1 now has (limited) support for Play 2.5.x and the Kotlin build script support gets a more fully-featured syntax for declaring dependencies and faster code completion.

Finally, be sure to check out the potential breaking changes in case they affect you.

Table Of Contents

New and noteworthy

This release includes some significant new features and major improvements for our users. Read the following sections to learn more about them.

Composite Builds

Composite Builds take the pain out of binary integration. They allow you to integrate independent Gradle builds, effectively giving you something like a multi-project build while keeping the builds separate. This is done by substituting project dependencies for binary dependencies at will.

They allow you to:

As an example, imagine you have two separate projects with independent builds: a library called number-utils and an application called my-app. Let's say the library has this build:

apply plugin: 'java'
group "org.sample"
version "1.0"

while the application's build looks like this:

apply plugin: 'application'

dependencies {
    compile "org.sample:number-utils:1.0"
}

Gradle will normally just download the requested number-utils jar from a repository and use it, ignoring the fact that you have the library's project source available. But now, you can force Gradle to build the number-utils project and use its jar in place of the requested 1.0 version. Simply run the following Gradle command inside the my-app project directory:

gradle test --include-build ../number-utils

Of course, the number-utils project could be located anywhere on the filesystem. You would just need to use the appropriate file path with the --include-build option.

This is just one technique you can use with composite build. See the user guide for more options.

Faster dependency resolution

Dependency resolution is now faster for several common cases:

Dependency resolution affects many aspects of build performance and all builds are different. Some users will see a modest drop in the resolution time while other will experience a more significant improvement. We have observed good improvements for Android builds in particular, in some cases halving the build configuration time.

Incremental build improvements

The incremental build feature is a critical part of Gradle and for it to work properly, it needs to understand precisely when the inputs or outputs of a task have changed. Gradle 3.1 adds two more important options for specifying the rules that describe when an input is up-to-date or not, giving you more fine-grained control.

See the table of annotations in the user guide for more details of both these features.

Tracking changes in the order of input files

In many cases, a collection of files is just a collection of files and tasks don't care about the order of those files. But consider the classpath for Java compilation: the compiler searches those classpath entries in the order that they're declared when looking for a class. That means the classpath is order sensitive.

Gradle now supports this scenario via a new @OrderSensitive annotation. Adding this to a property marked with @InputFiles or @InputDirectory will cause Gradle to rerun the task if the order of the files changes, even if the files themselves have not. This annotation is already in use by Gradle internally and you can also use it in your own custom task classes.

Better understanding of input file paths

Has a file changed if it has moved, but the content is still the same? This is an important question to answer if Gradle is to correctly determine whether a task needs to run again or not.

Previously, Gradle used the absolute path when determining whether an input file had changed or not. So if a file was moved to a different location, Gradle would run the corresponding task again. But moving a file may or may not impact the task in such a way that it needs to run again. It depends on the task.

Gradle 3.1 introduces a new path sensitivity feature that allows Gradle to observe just the relevant part of an input file's path. For example, with an @InputFiles property annotated with @PathSensitive(PathSensitivity.NAME_ONLY), Gradle only cares about changes to the names of the input files, not their paths. So simply moving one of those files won't cause the task to run again.

Sync can preserve files

The Sync task can now preserve files that already exist in the destination directory. Here's a demonstration of the new syntax, showing you how to specify patterns for those files you want to keep or explicitly remove:

task sync(type: Sync) {
    from 'source'
    into 'dest'
    preserve {
        include 'extraDir/**'
        include 'dir1/**'
        exclude 'dir1/extra.txt'
    }
}

Before this change, Sync would always clear the whole target directory before copying files across.

The distribution type can be selected by the Wrapper task

The wrapper command has allowed you to specify a Gradle version for some time now, meaning that you only ever need to install one version of Gradle on your machine. But it always created a wrapper that downloaded the binary distribution, which excludes the Gradle source, docs, and samples.

You can now specify that you want the more complete -all distribution for the wrapper - particularly useful for IDEs - via the new --distribution-type options, like so:

gradle wrapper --distribution-type all

The default is still the binary distribution as it's smaller.

Initial support for Play 2.5.x

Initial support for Play 2.5.x has been added.

Improved IDEA code assistance performance for Kotlin based build scripts

Gradle 3.1 supports version 0.3.2 of Gradle Script Kotlin, a statically typed build language based on Kotlin.

This new version includes an improved dependencies DSL making it possible to configure all aspects of external module and project dependencies via a type-safe and IDE-friendly DSL, as shown here:

dependencies {

    default(group = "org.gradle", name = "foo", version = "1.0") {
        isForce = true
    }

    compile(group = "org.gradle", name = "bar") {
        exclude(module = "foo")
    }

    runtime("org.gradle:baz:1.0-SNAPSHOT") {
        isChanging = true
        isTransitive = false
    }

    testCompile(group = "junit", name = "junit")

    testRuntime(project(path = ":core")) {
        exclude(group = "org.gradle")
    }

    // Client module dependencies are also supported
    runtime(
        module("org.codehaus.groovy:groovy:2.4.7") {

            // Configures the module itself
            isTransitive = false

            dependency("commons-cli:commons-cli:1.0") {
                // Configures the external module dependency
                isTransitive = false
            }

            module(group = "org.apache.ant", name = "ant", version = "1.9.6") {
                // Configures the inner module dependencies
                dependencies(
                    "org.apache.ant:ant-launcher:1.9.6@jar",
                    "org.apache.ant:ant-junit:1.9.6")
            }
        }
    )
}

Gradle Script Kotlin 0.3.2 also ships with Kotlin 1.1-dev-2053, which greatly improves the performance of code completion within IDEA when used together with a recent Kotlin plugin version. Please check out the full Gradle Script Kotlin v0.3.1 release notes, the first release to include it, for details.

Parity with the Groovy based build language was greatly increased. Taking copySpec as an example. Before Gradle Script Kotlin v0.3.2 one could write:

copySpec {
    it.from("src/data")
    it.include("*.properties")
}

With v0.3.2 it should now read:

copySpec {
    from("src/data")
    include("*.properties")
}

Please note that this is a breaking change as many configuration patterns that previously required a qualifying it reference no longer do. This behavior is only enabled for non-generic Gradle API methods under the org.gradle.api package at this point. Subsequent releases will increasingly cover the full API.

Again for the full scoop please check out the full Gradle Script Kotlin release notes.

More resilient Daemon

In previous Gradle versions, if the Daemon client process improperly disconnected from the Daemon while a build was running, the Daemon process would exit and a subsequent build would have to start a new Daemon. In Gradle 3.1, the Daemon will now remain running and attempt to cancel the build instead. This allows subsequent builds to reuse the Daemon and reap the performance benefits of a warm Daemon. This behavior will be further improved in Gradle 3.2.

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

Ivy Publish plugin takes into account transitive attribute declared for dependencies when generating metadata

Previous versions of Gradle did not reflect the transitive attribute for a dependency in the generated metadata if the transitive attribute was set to false. To illustrate the change in behavior, let's assume the following dependency declaration.

dependencies {
    compile ("commons-dbcp:commons-dbcp:1.4") {
        transitive = false
    }
}

The generated ivy.xml will now properly reflect that the given dependency should not resolve any of its transitive dependencies.

<dependencies>
    <dependency org="commons-dbcp" name="commons-dbcp" rev="1.4" conf="runtime-&gt;default" transitive="false" />
</dependencies>

Projects consuming published artifacts generated by the Ivy Publish plugin might experience a different dependency graph than observed with earlier versions of Gradle.

Maven plugin takes into account exclude attributes group and module for dependencies when generating metadata

Previous versions of Gradle did not add exclusions for dependencies in the generated metadata that either use the attribute group or module. The following dependency declaration demonstrates those use cases.

dependencies {
    compile('org.apache.camel:camel-jackson:2.15.3') {
        exclude group: 'org.apache.camel'
    }
    compile('commons-beanutils:commons-beanutils:1.8.3') {
        exclude module: 'commons-logging'
    }
}

The generated pom.xml will now properly reflect the exclusions in the generated metadata. Projects consuming published artifacts generated by the Maven plugin might experience a different dependency graph than observed with earlier versions of Gradle.

JNA library has been removed from Gradle distribution

We do not need JNA anymore so we removed this library from the Gradle distribution. Plugin authors relying on the library being present now need to ship their own.

Tooling API models have missing dependency information when importing composite builds

When a composite build is imported via the Gradle Tooling API, then certain fields may not be populated:

Dependency resolution changes when a Maven module dependency is substituted with a Gradle project dependency

In previous Gradle versions, when a Maven module is substituted with a Gradle project during dependency resolution, the result includes dependencies and artifacts from all public configurations of the target project, such as any custom configurations defined by the project's build script, when the project does not define any of the compile, runtime or master configurations. The Java plugin does not define a master configuration, which means most projects using the Java plugin would be affected by this behaviour when the target of a dependency substitution rule.

In Gradle 3.1, this has been changed so that when the target project does not define a runtime or compile configuration, the default configuration is used instead. The master configuration is included if it is defined by the project and ignored if not.

Dependency resolution changes when a Maven module depends on an Ivy module

In previous Gradle versions, when a Maven module depends on an Ivy module and the target Ivy module does not define any of the runtime, compile or master configurations, the result includes all dependencies and artifacts from all public configurations of the Ivy module.

In Gradle 3.1, this has been changed so that when the target Ivy module does not define a runtime or compile configuration, the default configuration is used instead. The master configuration is included if it is defined by the Ivy module and ignored if not.

Dependency resolution result changes

As a result of performance improvements, the dependency graph returned by the ResolvedConfiguration.getFirstLevelModuleDependencies() API now includes fewer ResolvedDependency nodes, as some nodes are merged to reduce the size of the dependency graph.

The dependency graph reported by this API for previous versions of Gradle include a compile, runtime and master node for a Maven module that is included as a dependency of some other Maven module. In Gradle 3.1 the dependency graph reported by this API includes a single runtime node for these modules.

Gradle 3.1 includes the same modules and artifacts in the result, presented in the same order, as previous Gradle versions.

GradleConnection removed

The incubating GradleConnection API has been removed in favor of composite builds defined in settings.gradle. New methods for fetching all models from a composite will be added to ProjectConnection soon.

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.