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.
Here are the new features introduced in this Gradle release.
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.
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.
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.
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 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.
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.
It is now possible to obtain the “group” of a task via org.gradle.tooling.model.Task.getGroup()
.
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>
.
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.
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.
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
.
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.
As part of the changes in the IDE classpath generation, the following properties have been deprecated:
EclipseClasspath#noExportConfigurations
ProjectDependency#declaredConfigurationName
AbstractLibrary#declaredConfigurationName
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.
componentSpec
project extensionAs 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.
ComponentSpecContainer
ComponentSpecContainer
no longer implements ExtensiblePolymorphicDomainObjectContainer<ComponentSpec>
.ComponentSpecContainer
now implements ModelMap<ComponentSpec>
.ComponentSpecContainer
is now deferred. In earlier versions of Gradle this configuration was eager.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>>
.TestSuiteContainer
TestSuiteContainer
no longer implements ExtensiblePolymorphicDomainObjectContainer<TestSuiteSpec>
.TestSuiteContainer
now implements ModelMap<TestSuiteSpec>
.TestSuiteContainer
is now deferred. In earlier versions of Gradle this configuration was eager.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.
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
}
The incubating API BuildLauncher.addTestProgressListener()
and the associated listener type have been removed. This API has been superseded by the new progress listener API.
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:
exported = false
.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.
We would like to thank the following community members for making contributions to this release of Gradle.
Project.copy(Action)
and Project.copySpec(Action)
.Known issues are problems that were discovered post release that are directly related to changes made in this release.