Gradle Release Notes

Version 2.5

Gradle 2.5 delivers some big features and plenty of internal improvements and optimizations.

The new “Continuous build” support brings capability to have Gradle automatically initiate a build in response to file system changes. This works with any build and has many applications. For example, it can be used to get continuous compile and test, giving more immediate feedback. As it works with any Gradle task, it is equally applicable to documentation generation tasks and more. Upcoming versions of Gradle will build on this capability to facilitate reloading applications and the like under development in response to changes, providing a fast feedback local development loop.

“Dependency substitution rules” make it possible to develop multiple related projects builds with more flexibility. It is now possible to dynamically substitute source dependencies with pre-built versions, and vice-versa, with greater ease. Dependency substitution rules are a powerful new addition to Gradle's arsenal for Dependency Management.

The Tooling API (i.e. the mechanism for embedding Gradle) now provides rich event information during the execution of the build to specified listeners. This mechanism can be used by IDEs and other tools wanting to provide visualisations or extra progress information during build execution.

There are also notable improvements to Gradle's support for native code, including support for GoogleTest and precompiled headers.

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Continuous build incubating feature

The new continuous build support allows Gradle to automatically start building in response to file system changes. When you run with the --continuous or -t command line options, Gradle will not exit at the end of a build. Instead, Gradle will wait for files that are processed by the build to change. When changes are detected, Gradle will re-run the previous build with the same task selection.

For instance, if you run gradle -t build in a typical Java project, main and test sources will be built and tests will be run. If changes are made to the project's main sources, Gradle will rebuild the main Java sources and re-run the project's tests. If changes are made to the project's test sources, Gradle will only rebuild the test Java sources and re-run the project's tests.

This is just the initial iteration of this feature, which will improve in coming releases. Future releases will increase the scope of “changes” to include more than just local input files. For example, the scope of considered “changes” may expand in the future to encompass dependencies in remote repositories along with other types of inputs that affect the build result.

For more information, please see the new User Guide chapter.

Dependency substitution rules incubating feature

Previous versions of Gradle allowed an external dependency to be replaced with another using a 'Dependency Resolve Rule'. With the introduction of 'Dependency substitution rules' this behaviour has been enhanced and extended to allow external dependencies and project dependencies to be replaced interchangeably.

When combined with a configurable Gradle settings file, these dependency substitution rules permit some powerful new ways of working with Gradle:

Substitute a project dependency with an external module dependency like this:

resolutionStrategy {
    dependencySubstitution {
        substitute project(":api") with module("org.utils:api:1.3")
    }
}

Alternatively, an external dependency can be replaced with a project dependency like this:

resolutionStrategy {
    dependencySubstitution {
        substitute module("org.utils:api") with project(":api")
    }
}

It is also possible to substitute a project dependency with another, or a module dependency with another. (The latter provides the same functionality as eachDependency, with a more convenient syntax).

Note: adding a dependency substitution rule to a Configuration used as a task input changes the timing of when that configuration is resolved. Instead of being resolved on first use, the Configuration is instead resolved when the task graph is being constructed. This can have unexpected consequences if the configuration is being further modified during task execution, or if the configuration relies on modules that are published during execution of another task.

For more information consult the User Guide and the DSL Reference.

This feature was contributed by Lóránt Pintér and the team at Prezi.

Progress events via the Tooling API incubating feature

It is now possible to receive progress events for various build operations. Listeners can be provided to the BuildLauncher via the addProgressListener(ProgressListener) method. Events are fired when the task graph is being populated, when each task is executed, when tests are executed, etc.

All operations are part of a single-root hierarchy that can be traversed through the operation descriptors via ProgressEvent.getDescriptor() and OperationDescriptor.getParent().

If you are only interested in the progress events for a sub-set of all available operations, you can use LongRunningOperation.addProgressListener(ProgressListener, Set<OperationType>). For example, you may elect to only receive events for the execution of tasks.

One potential use of this new capability would be to provide interesting visualisations of the build execution.

Simpler default dependencies incubating feature

Many Gradle plugins allow the user to specify a dependency for a particular tool, supplying a default version only if none is provided by the user. A common implementation of this involves using a beforeResolve() hook to check if the configuration has any dependencies, adding the default dependency if not. The new defaultDependencies() method has been introduced to make this simpler and more robust.

The use of beforeResolve() to specify default dependencies will continue to work, but will emit a deprecation warning if the configuration has already participated in dependency resolution when it is first resolved (see below).

Specifying a default dependency with beforeResolve (deprecated):

def util = dependencies.create("org.gradle:my-util:1.0")
conf.incoming.beforeResolve {
    if (conf.dependencies.empty) {
        conf.dependencies.add(util)
    }
}

Specifying a default dependency with defaultDependencies (recommended):

def util = dependencies.create("org.gradle:my-util:1.0")
conf.defaultDependencies { dependencies ->
    dependencies.add(util)
}

See the DSL reference for more details.

Precompiled header support incubating feature

Precompiled headers are a performance optimization for native builds that allows commonly used headers to be parsed only once rather than for each file that includes the headers. Precompiled headers are now supported for C, C++, Objective-C and Objective-C++ projects.

To use a precompiled header, a header file needs to created containing all of the headers that should be precompiled. This header file is then declared in the build script as a precompiled header.

model {
    components {
        hello(NativeLibrarySpec) {
            sources {
                cpp {
                    preCompiledHeader "pch.h"
                }
            }
        }
    }
}

Each source set can have a single precompiled header defined. Any source file that includes this header file as the first header will be compiled using the precompiled header. Otherwise, the precompiled header will be ignored and the source file will be compiled in the normal manner.

Please see the User Guide for further information.

Google Test support incubating feature

The new Gradle google-test plugin provides support for compiling and executing GoogleTest tests in your native binary project. You simply need to include your Google Test test sources in a conventional location (i.e. src/«component name»Test/cpp).

Gradle will build a test executable and run your tests.

> gradle -q runFailingOperatorsTest

[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from OperatorTests
[ RUN      ] OperatorTests.test_plus
src/operatorsTest/cpp/test_plus.cpp:8: Failure
Value of: plus(0, -2) == -2
 Actual: false
Expected: true
[  FAILED  ] OperatorTests.test_plus (0 ms)
[ RUN      ] OperatorTests.test_minus
[       OK ] OperatorTests.test_minus (0 ms)
[----------] 2 tests from OperatorTests (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] OperatorTests.test_plus

1 FAILED TEST

See the User Guide to learn more. Expect deeper integration with Google Test (and other native testing tools) in the future.

This feature was contributed by Daniel Lacasse.

Obtaining a task's group via the Tooling API

It is now possible to obtain the “group” of a task via org.gradle.tooling.model.Task.getGroup().

New managed model improvements

A number of improvements have been made to the experimental managed model feature. This feature is currently used by the native plugins and will evolve into a general purpose feature for describing Gradle builds:

The model report for Rule based model configuration has been enhanced to display string representations of some values. This allows the effective values of the build model to be visualised, not just the structure as was the case previously.

More of the new software model is now visible to the model report and to configuration rules.

@Managed models can now have managed model properties of type java.io.File.

@Managed types can now implement the Named interface. The name property will be automatically populated based on the objects location in the model graph.

It is now possible for @Managed types to declare properties of type ModelMap<T>.

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

Changing a configuration after it has participated in dependency resolution

Unexpected behaviour can result from changing a configuration after it has participated in dependency resolution. Examples include:

Previous versions of Gradle prevented the resolved configuration itself from being modified, but did nothing to prevent modifications to related configurations after they have participated in dependency resolution. This version of Gradle extends the checks, emitting a deprecation warning when a modification is made to a configuration that has been referenced in dependency resolution.

One exception is that changes to the ResolutionStrategy of a configuration can be made at any time until that configuration is itself resolved. Changes to the strategy do not impact the resolution of child configurations, or configurations referenced as project dependencies. Thus, these changes are safe to make.

Distribution Plugin changes

Due to a bug in the distribution plugin (see GRADLE-3278), earlier Gradle versions didn't follow the general naming convention for the assemble task of the main distribution. This has been fixed and assemble task name for the main distribution has changed from assembleMainDist to assembleDist.

Deprecation of CollectionBuilder and ManagedSet.

The types org.gradle.model.collection.CollectionBuilder and org.gradle.model.collection.ManagedSet have been deprecated and replaced by org.gradle.model.ModelMap and org.gradle.model.ModelSet respectively.

As these types were incubating, they will be removed before Gradle 3.0. Please change your usage to the new ModelMap and ModelSet types.

Deprecations in Eclipse model

As part of the changes in the IDE classpath generation, the following properties have been deprecated:

Potential breaking changes

Changes to the new software model

As work continues on the new software model for Gradle, many changes to the new incubating plugins and types are required. These changes should have no impact on builds that do not leverage these new features.

Removal of componentSpec project extension

As part of work on exposing more of the component model as managed types, the componentSpec project extension previously added by all language plugins via ComponentModelBasePlugin has been removed. The components container can now only be accessed using configuration rules.

Changes to ComponentSpecContainer

  • ComponentSpecContainer no longer implements ExtensiblePolymorphicDomainObjectContainer<ComponentSpec>.
  • ComponentSpecContainer now implements ModelMap<ComponentSpec>.
  • All configuration done using subject of type ComponentSpecContainer is now deferred. In earlier versions of Gradle this configuration was eager.

Changes to ComponentSpec

  • getSource() now returns a ModelMap<LanguageSourceSet> instead of DomainObjectSet<LanguageSourceSet>.
  • sources() now takes a Action<? super ModelMap<LanguageSourceSet>> instead of Action<? super PolymorphicDomainObjectContainer<LanguageSourceSet>>.
  • getBinaries() now returns a ModelMap<BinarySpec> instead of DomainObjectSet<BinarySpec>.
  • binaries() now takes a Action<? super ModelMap<BinarySpec>> instead of Action<? super DomainObjectSet<BinarySpec>>.
  • Source sets and binaries cannot be removed from these collections.

Changes in TestSuiteContainer

  • TestSuiteContainer no longer implements ExtensiblePolymorphicDomainObjectContainer<TestSuiteSpec>.
  • TestSuiteContainer now implements ModelMap<TestSuiteSpec>.
  • All configuration done using subject of type TestSuiteContainer is now deferred. In earlier versions of Gradle this configuration was eager.

Maven publishing

The maven-publish and maven plugins no longer use the Maven 2 based Maven ant tasks libraries to publish artifacts. Both plugins now use the newer Maven 3 and Aether libraries. Whilst the API's exposed by both plugins remain unchanged, the underlying publishing libraries have been upgraded.

This upgrade was contributed by Mikolaj Izdebski.

Java annotation processing of Groovy code is now disabled by default

Gradle 2.4 introduced the ability to use Java annotation processors on Groovy sources. If annotation processors were present on the classpath, they were implicitly applied to Groovy source. This caused problems in situations where a separate “processing” strategy was required for joint compiled Groovy source (GRADLE-3300).

Java annotation processing of Groovy source is now disabled by default. It can be enabled by setting the javaAnnotationProcessing property of GroovyCompileOptions

compileGroovy {
    groovyOptions.javaAnnotationProcessing = true
}

Registering test progress listeners through the Tooling API

The incubating API BuildLauncher.addTestProgressListener() and the associated listener type have been removed. This API has been superseded by the new progress listener API.

Changes in IDE classpath generation

Project files generated by the Gradle Idea and Eclipse plugins are responsible for deriving the classpath from the declared list of dependencies in the build file. Some incorrect behavior, resulting in incorrect classpaths in the IDE, has been rectified in this Gradle version.

Let's assume project A and B are part of a multi-project build. Project B declares a project dependency on project A. The generated classpath of project B is a union of the classpath of project A (the generated JAR file plus its dependencies) and its own declared top-level dependencies and transitive dependencies. In practice, this means that when project A and B depend on a specific library with different versions, the "exported" dependency version wins as it happens to be listed first in the classpath of project B. This behaviour might lead to compilation and runtime issues in the IDE as no conflict-resolution takes place across projects.

To avoid the situation just described, the IDE classpath generation now more closely reflects the classpath as it is used by Gradle:

Dependency Substitution

Gradle 2.4 included some of the new dependency substitution interfaces and classes, but they were unannounced. Build scripts written to use these interfaces in 2.4 will likely not work in 2.5. Please take a look at the dependency substitution sample and User Guide chapter to understand the changes that were made while getting dependency substitution ready for the Gradle 2.5 release.

External contributions

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

Known issues

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