Gradle Release Notes

Version 1.2

Table Of Contents

New and noteworthy

Here are the new features introduced in Gradle 1.2.

Improved dependency report

The dependency report (obtained by running “gradle dependencies”) has been improved to provide better insight into the dependency resolution process. The report now specifies the requested version of a dependency and the selected version. The requested version may be different to the selected for the following reasons:

In the case of a conflict, the output provides all the information you need to infer which dependency depended on the version that was eventually selected. The improved output gives much better insight into how version conflicts that were encountered were resolved and why.

In the case of a dynamic dependency version, both the original dynamic version and selected real version are shown.

The new dependency report is also much faster to render. Our tests have shown that for large to very large dependency graphs the time taken to display the report has been reduced by up to 50%. Further improvements are planned for the dependency report in future versions of Gradle.

Example report

Given the following build script:

apply plugin: 'java'

repositories {
    maven { url "http://repo.gradle.org/gradle/repo" }
}

dependencies {
    compile 'commons-lang:commons-lang:2.+'
    compile 'org.gradle:gradle-base-services:1.1' // depends on org.slf4j:slf4j-api:1.6.6
    compile 'org.slf4j:slf4j-api:1.6.5'
}

The new report will look like:

> gradle dependencies
:dependencies

------------------------------------------------------------
Root project
------------------------------------------------------------

compile - Classpath for compiling the main sources.
+--- commons-lang:commons-lang:2.+ -> 2.6
+--- org.gradle:gradle-base-services:1.1
|    \--- org.slf4j:slf4j-api:1.6.6
\--- org.slf4j:slf4j-api:1.6.5 -> 1.6.6 (*)

(*) - dependencies omitted (listed previously)

(note: output for other configurations has been omitted for clarity)

The version that was selected for the dynamic dependency is shown (i.e. “commons-lang:commons-lang:2.+ -> 2.6”) and the fact that version “1.6.5” of “org.slf4j:slf4j-api” was requested but version “1.6.6” was selected is also shown.

Lower memory usage

We've continued to improve our dependency resolution engine, so that it now requires much less heap space. A moderately sized multi-project build can expect to see a 20-25% reduction in heap usage thanks to these improvements.

Reporting of multiple build failures

When running the build with --continue or the new --parallel option it is possible to have multiple failures in your build. Previously, these failures were only reported at the time they occurred. Now, additionally a complete list of build failures is shown on build completion.

The new output clearly indicates the cause and possible analysis of each failure, making it easier to track down the underlying issue. Detailing all failures makes the --continue command line option much more useful: it is now possible to use this option to discover as many failures as possible with a single build execution.

Configuration options for FindBugs plugin

Thanks to a contribution from Justin Ryan, the FindBugs plugin now supports more configuration options.

Important: In Gradle 1.2, there is an identified issue that requires any FindBugs specific configuration to be performed on the task; configuration via the DSL extension is ineffectual. Please click the “More” button below for instructions on how to workaround this issue.

FindBugs DSL extension issue

Instead of configuring FindBugs properties for all tasks globally via the DSL extension:

findbugs {
  excludeFilter = file("$rootProject.projectDir/config/findbugs/excludeFilter.xml")
}

You need to configure the task(s) directly, which can be done via:

tasks.withType(FindBugs) {
  excludeFilter = file("$rootProject.projectDir/config/findbugs/excludeFilter.xml")
}

This applies to all FindBugs specific task properties.

This issue will be resolved in Gradle 1.3, allowing you to globally configure all FindBugs tasks via the DSL extension.

Gradle, the Gradle Wrapper and the Gradle Tooling API now provide version information in the User-Agent header whenever HTTP resources are accessed. Especially for larger organizations, this can be very helpful to gather information about which versions of Gradle are used in which environment.

What information is provided?

The User-Agent header now includes information about

  • The Gradle application (Gradle, Gradle Wrapper or Gradle Tooling API) and version making the request.
  • The Operating system (name, version, architecture).
  • The Java version (vendor, version).

An example for a Gradle generated user-agent string: "Gradle/1.2 (Mac OS X;10.8;amd64) (Oracle Corporation;1.7.0_04-ea;23.0-b12)"

Documentation style improvements

Our documentation has received a facelift to match our new style. Check out the new look DSL Reference and User Guide.

The DSL Reference also now indicates which features are deprecated or incubating. See TestLoggingContainer for and example of how an incubating feature is displayed, and Directory for an example of a deprecated feature.

Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to our backwards compatibility policy.

Continue on failure (--continue)

Often a high-level task is dependent on multiple smaller tasks. By default, Gradle will stop executing any task and fail the build as soon as one of these sub-tasks fails. This means that the build will finish sooner, but it does not reveal failures in other, independent sub-tasks. There are many times when you would like to find out as many failures as possible in a single build execution. For example, when you kick off a build before heading out to lunch, or running a nightly CI job. The --continue command-line option allows you to do just that.

With the addition of nicer reporting of multiple build failures, we now consider --continue a production quality feature of Gradle. Please see the User Guide section for more details.

Fixed issues

The list of issues fixed between 1.1 and 1.2 can be found here.

Incubating features

We will typically introduce new features as incubating at first, giving you a chance to test them out. Typically the implementation quality of the new features is already good but the API might still change with the next release based on the feedback we receive. For some very challenging engineering problems like the Gradle Daemon or parallel builds, it is impossible to get the implementation quality right from the beginning. So we need you here also as beta testers. We will iterate on the new feature based on your feedback, eventually releasing it as stable and production-ready. Those of you who use new features before that point gain the competitive advantage of early access to new functionality in exchange for helping refine it over time. To learn more, read our forum posting on our release approach.

Comparing builds (upgrade assistance)

Gradle 1.2 delivers the first iteration of our support for comparing the outcomes (e.g. the produced binary archives) of two builds. There are several reasons why you may want to compare the outcomes of two builds. You may want to compare:

The build comparison support manages the execution of the “source” build and the “target” build, the association of outcomes between the two, the comparison of the outcomes and generation of a report that identifies any encountered differences. You can then use this report to go ahead with the Gradle upgrade, build system migration or build configuration change with confidence that the outcomes are identical, or that the differences are acceptable.

For Gradle 1.2, we have focused on supporting the case of comparing the current build with a newer Gradle version and zip archive outcomes (e.g. zip, jar, war, ear etc.). This feature will continue to evolve to encompass comparing more kinds of outcomes and smart integration with other build systems (such as Apache Maven) for convenient comparisons.

See the new User Guide chapter for more detail on this new capability.

How can I use it to try new Gradle versions?

You simply add a plugin and configure the comparison task.

apply plugin: 'compare-gradle-builds'

compareGradleBuilds {
  targetBuild.gradleVersion "1.3"
}

(note: Gradle 1.3 is unreleased at this time, so the above will not work. You can use 1.2 as the value in the meantime to play with this feature though)

Then simply…

> gradle compareGradleBuilds

If there are any differences found, a link to the HTML report identifying the differences will be given in the output.

Building projects in parallel

We are excited that Gradle 1.2 introduces support for building projects in parallel. By specifying the --parallel or --parallel-threads command-line options, Gradle will execute multiple projects in parallel build threads, after first configuring all projects sequentially. By building separate projects in parallel, Gradle will better utilize the build machine's hardware, resulting in faster build times. We are seeing significant performance benefits with this approach.

This feature is incubating and has known issues and limitations; it is not yet at production quality. Over the coming releases, it will be improved and stabilized. To find out more about our plans for parallel execution, have a read of the parallel-project-execution specification.

Project requirements

To guarantee successful parallel execution of projects, your multi-project build must be decoupled. At this time there are no checks implemented to ensure that projects are decoupled, and unexpected behaviour may result from executing a build with coupled projects using the new parallel executor.

Known issues with parrallel building

One known issue is that the Gradle compiler daemon is currently not thread-safe. So if multiple projects attempt to compile java code simultaneously with fork=true, exceptions will result. Workaround: don't use options.fork=true to compile when running with --parallel.

Dependency resolution result API

We are exposing the new API that our improved dependency reports are using. It provides a powerful toolkit for developing your own custom dependency reports. It also allows to develop smart build logic that can make decisions based on the content of the dependency graph.

The best way to start with the new API is to take a look at the Javadocs for ResolvedConfiguration.getResolutionResult().

JSR-330 dependency injection for plugins and tasks

We've taken some steps towards allowing JSR-330 style dependency injection for plugins and tasks. At this stage, the changes are mostly internal. To find out why we want to use dependency injection, and our plans for this, have a read of the dependency-injection-for-plugins specification.

At this stage, only internal Gradle services are available for injection. Over time we will add public services that can be injected into plugin and task implementations.

Deprecations

If you make use of the deprecated features below you will get a warning from now on. But you can rest assured that those features will be supported at least until the release of Gradle 2.0, our next major release. To learn more read our forum posting on our release and backwards compatibility approach.

The useMavenMetadata property for Maven repositories

The useMavenMetadata property has been deprecated for resolvers returned by repositories.mavenRepo(). This property controls whether Gradle should search for a maven-metadata.xml file when attempting to determine the versions that are available for a particular module. The default value is true, which means Gradle will look for a maven-metadata.xml file and then fall back to a directory listing if not present. When set to false, Gradle will use a directory listing only. It is part of our former internal usage of Ivy for dependency resolution.

Thanks to the various improvements we've made to make dependency management more efficient, there is no longer a performance penalty for searching for the maven-metadata.xml file. This means this property is no longer useful and will be removed in Gradle 2.0.

Task class renames

To avoid ambiguity, the Java and C++ Compile task classes have been renamed. The Java org.gradle.api.tasks.compile.Compile task class has been renamed to org.gradle.api.tasks.compile.JavaCompile, and the incubating C++ org.gradle.plugins.binaries.tasks.Compile task class has been renamed to org.gradle.plugins.cpp.CppCompile.

For backwards compatibility, the old classes are still available, but are now deprecated. The old Java Compile class will be removed in Gradle 2.0. The old incubating C++ Compile class will be removed in Gradle 1.3.

Changes to plugin and task constructor handling

As a first step towards handling JSR-330 style dependency injection for plugin and task instances, we have made some changes to how constructors for these types are handled by Gradle. These changes are fully backwards compatible, but some combinations of constructors are now deprecated.

If your plugin or task implementation class has exactly one default constructor, nothing has changed. This should be the case for the majority of implementations.

If your implementation class has multiple constructors, you will need to add an @javax.inject.Inject annotation to the default constructor. The implementation will continue to work without this, but you will receive a deprecation warning. In Gradle 2.0, a plugin or task implementation with multiple constructors will be required to annotate exactly one constructor with an @Inject annotation.

Potential breaking changes

Plugin and task constructors

See constructor handling above. The changes should be backwards compatible. Please let us know if you come across a situation where a plugin or task implementation that worked with previous versions of Gradle does not work with Gradle 1.2.

Upgrade to ASM 4.0

Gradle uses the ASM bytecode manipulation library internally. The version of ASM used has been upgraded from 3.3.1 to 4.0 in the Gradle 1.2 release.

When building and testing custom plugins and build logic (or anything with the Gradle libraries and dependencies on the classpath), you may encounter issues if there is also an earlier version of ASM than 4.0 on the classpath. This error will manifest as an exception with a message such as:

Caused by: java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected

There have been some reports of this issue occurring in the Groovy Eclipse development environment.

If you experience this issue, please let us know via the Gradle Forums.