Gradle Release Notes

Version 1.6-rc-1

Gradle 1.6 sees some fantastic new features contributed by the Gradle community: Task ordering rules offer you more control over the execution of tasks, there's now a JaCoCo plugin for test coverage, and the Junit integration supports test categories.

To help get you started with Gradle, this release introduces the build setup plugin. This plugin takes care of the work of setting up a new build. This includes support for converting an Apache Maven POM to a Gradle build. You simply point Gradle at your current Maven build and you end up with a functioning Gradle build. Note that this plugin is in early stages of development and we plan to improve it in future releases.

Continuing on the performance work of the last few releases, Gradle 1.6 includes support for incremental tasks. These are tasks that selectively process only those inputs that have changed, and avoid processing those inputs that have not changed.

The Gradle team also invites you to the first ever “Gradle Summit” (Sponsored by Gradleware), held June 13th - 14th in Santa Clara, California. The summit will be two fully packed days of technical sessions given by Gradle core developers ranging from introductory to deep dive as well as informational sessions by several large organizations on how they get the most out of Gradle. In between sessions there'll be plenty of opportunity for talking to other Gradle users and the Gradle development team. This is an event not to miss. Registration is now open.

Read on for more details on why you should upgrade to Gradle 1.6. As always, please share your feedback and experiences with Gradle 1.6 via the Gradle Forums.

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Force a task to run after another task, without adding a dependency incubating feature

In the past, the only way to ensure that Gradle ran one task after another was to add a dependency between those tasks. So if Task A must always run before Task B, you would say that B.dependsOn(A). This has the added effect of forcing Task A to always run if Task B is executed.

In some cases, dependsOn is not the correct semantics. A simple example is “clean” must always run before “build”, but you don't always want to run “clean” whenever you run “build”. For this use case Gradle now has “task ordering” rules, the first of which is Task.mustRunAfter. This rule does not change which tasks will be executed, but it does influence the order in which they will be executed.

task clean { ... }
task build { ... }

build.mustRunAfter clean

In this example you can still execute gradle clean and gradle build independently, but running gradle build clean will cause 'clean' to be executed before 'build'.

Another example is a test-aggregation task that consumes the outputs of all of the test tasks. You want this aggregation task to run after all test tasks, but you do not necessarily want to force all test tasks to run.

task runUnitTests(type: Test) { ... }
task runIntegTests(type: Test) { ... }
task createTestReports { ... }

createTestReports.mustRunAfter tasks.withType(Test)

task allTest(dependsOn: [runUnitTests, runIntegTests, createTestReports]) // This will run unit+integ tests and create the aggregated report
task unitTest(dependsOn: [runUnitTests, createTestReports]) // This will run unit tests only and create the report
task integTest(dependsOn: [runIntegTests, createTestReports]) // This will run integ tests only and create the report

Note that it would not be suitable to use createTestReport.dependsOn(runUnitTests) in this case, since that would make it difficult to execute the integration tests and generate the report, without running the unit tests. The mustRunAfter task ordering rule makes it easy to wire this logic into your build.

See the User guide section on “Ordering Tasks” for more information.

On behalf of the Gradle community, the Gradle development team would like to thank Marcin Erdmann for taking on this long anticipated feature. The design and implementation of task ordering rules involved a deep understanding and refactoring of the Gradle Task execution engine, and Marcin took this on with gusto.

JaCoCo Code Coverage Plugin incubating feature

Gradle now ships with a JaCoCo plugin to generate code coverage reports. JaCoCo is a free code coverage library for Java.

To gather code coverage information for your java project, just apply the JaCoCo plugin:

apply plugin: 'jacoco'

and run gradle test jacocoTestReport which generates code coverage reports for the test task introduced by the java plugin. The JacocoReport adds a mustRunAfter dependency on the coverage data producing task (test in our example). After the build has finished you find the coverage report in build/reports/jacoco/test.

You can configure every task of type JacocoReport to enable other output formats than the default HTML report. For example, if you just want the XML coverage report that can be reused by your favourite CI server, you can simply configure this:

jacocoTestReport {
    reports {
        html.enabled = false
        csv.enabled = false
        xml.enabled = true
    } 
}

In some scenarios it might be desirable to compute code coverage not by running tests, but by running the application itself. Since the JaCoCo plugin can be used in combination with any JavaExec task of your build, it's quite simple to combine the JaCoCo plugin with the run task introduced by the application plugin:

jacoco {
    applyTo run
}

task applicationCodeCoverageReport(type: JacocoReport) {
    executionData run
    sourceSets sourceSets.main
}

This plugin was contributed by Andrew Oberstar, an energetic member of the Gradle community, and is a long requested out-of-the-box feature that is a very welcome addition.

Build Setup Plugin incubating feature

Gradle 1.6 introduces a build-setup plugin that makes initializing new Gradle builds more convenient. It also supports the migration of an Apache Maven build to a Gradle build by generating a build.gradle file from a pom.xml.

The build-setup plugin is not a plugin that you would apply to your project. Instead, you use it by executing the setupBuild task in a directory that does not contain any Gradle build files. This will do the following:

For more information please see the User Guide chapter on this plugin.

This plugin is an incubating feature and will improve and expand in scope in future releases. If you're interested in its progress and future, you can check out the design spec.

Support for JUnit @Category incubating feature

Thanks to a contribution by Uladzimir Mihura, Gradle now supports JUnit categories. Categories are a mechanism to label and group JUnit tests by using annotations.

Given the following JUnit test code:

public interface FastTests { /* category marker interface */ }
public interface SlowTests { /* category marker interface */ }

public class MyTestClass {
    @Category(SlowTests.class)
    @Test public void testA() {
        …
    }

    @Category(FastTests.class)
    @Test public void testB() {
        …
    }
}

You can now easily configure your test task to run only specific categories:

test { // run fast unit test only
    useJUnit {
        includeCategories 'org.gradle.categories.FastTests'
        excludeCategories 'org.gradle.categories.SlowTests'
    }
}

The includeCategories and excludeCategories are methods of the JUnitOptions object and take the full class names of one or more category annotations to include or exclude.

Incremental Tasks incubating feature

One of Gradle's most prized features is its ability to build a project incrementally. If tasks declare their inputs and outputs, Gradle can optimize the build by skipping the execution of each task whose inputs and outputs are unchanged since the previous execution (because the work would be completely redundant). This is known as “Incremental Build”. Gradle 1.6 introduces a related, incubating, feature that takes build optimization to the next level: “Incremental Tasks”.

An “incremental task” is able to selectively process inputs that have changed, avoiding processing inputs that have not changed and do not need reprocessing. Gradle provides information about changes to inputs to the task implementation for this purpose.

To implement an incremental task, you add a @TaskAction method that takes a single parameter of type IncrementalTaskInputs. You can then supply an action to execute for every input file that is out of date, and another action to execute for every input file that has been removed.

@TaskAction
void execute(IncrementalTaskInputs inputs) {
    inputs.outOfDate { change ->
        println "File ${change.file.name} is out of date"
    }

    inputs.removed { change ->
        println "File ${change.file.name} has been removed"
    }
}

Note: Incremental task support is a complicated and challenging feature to support. Since the introduction of the implementation described above (early in the Gradle 1.6 release cycle), discussions within the Gradle community have produced superior ideas for exposing the information about changes to task implementors. As such, the API for this feature will almost certainly change in upcoming releases. However, please do experiment with the current implementation and share your experiences with the Gradle community. The feature incubation process (which is part of the Gradle feature lifecyle) exists for this purpose of ensuring high quality final implementation through incorporation of early user feedback.

Be sure to check out the User Guide chapter and DSL reference for more details on implementing incremental tasks.

Installation via Gradle Wrapper is now multi process safe

In previous versions of Gradle it was possible for a Gradle distribution installed implicitly via the Gradle Wrapper to be corrupted, or to fail to install, if more than one process was trying to do this at the same time. This was more likely to occur on a continuous build server than a developer workstation. This no longer occurs as the installation performed by the wrapper is now multi process safe.

Important: leveraging the new multi process safe wrapper requires updating the gradle-wrapper.jar that is checked in to your project. This requires an extra step to the usual wrapper upgrade process.

First, update your wrapper as per usual by updating the gradleVersion property of the wrapper task in the build…

task wrapper(type: Wrapper) {
    gradleVersion = "1.6"
}

Then run ./gradlew wrapper to update the wrapper definition. This will configure the wrapper to use and download Gradle 1.6 for future builds, but it has not updated the gradle-wrapper.jar that is checked in to your project. To do this, simply run ./gradlew wrapper again. This is necessary as the wrapper jar is sourced from the Gradle environment that is running the build.

If you are seeding a new project using an installation of Gradle 1.6 or higher, you do not need to run the wrapper task twice. It is only necessary when upgrading the wrapper from an older version.

Apply plugins from init and settings scripts incubating feature

The Gradle type, which is configured by init scripts, and the Settings type, which is configured by settings scripts, now accept plugins. Previously, you could apply scripts to these types, but not binary plugins.

This change means that you can now package up init or settings logic in a binary plugin and apply this plugin from the appropriate script, in exactly the same way you do for projects. And this means that you can reuse and share these plugins in exactly the same way.

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

groovy configuration is deprecated

Since Gradle 1.4, the preferred way to specify the Groovy library is to add it to the compile (or testCompile) configuration, rather than the groovy configuration. Therefore, the groovy configuration is now deprecated. Simply replace groovy with compile in the dependencies block:

dependencies {
    compile "org.codehaus.groovy:groovy-all:2.0.6"
}

In some cases (for example if the Groovy Jar has been renamed), it may also be necessary to explicitly configure the groovyClasspath of GroovyCompile and Groovydoc tasks.

For additional background information about this change, see the Groovy chapter of the Gradle user guide.

Renamed several add() methods

To improve consistency in the Gradle API, we've replaced the container add() methods with a create() method. Since well before Gradle 1.0, every container type has had a number of create() methods which both create a new object and add it to the container. Some older container types also define an add() method which does the same thing, but also conflicts with the add() method inherited from java.util.Collection which simply adds an object rather than creating it. To simplify this, these add() methods have now been deprecated and will be removed in Gradle 2.0.

The methods in question are:

StartParameter.getMergedSystemProperties() method is deprecated

This method was used internally and was not intended to form part of the public API. It has now been deprecated and will be removed in Gradle 2.0.

Potential breaking changes

Renamed add() method on incubating PublicationContainer

The incubating org.gradle.api.publish.PublicationContainer introduced by the new publish plugins leverages the new support for polymorphic domain object containers in Gradle. This change involved switching from the custom add() methods to the standard create(), as described above. The semantics of the replacement methods is identical to those replaced.

This change does not effect publications added to the PublicationContainer using a configuration block, but will impact publications added directly using the add() method.

ProjectDependency and ExtensionContainer now have an internal protocol

This means that the users should not create their own implementations of org.gradle.api.artifacts.ProjectDependency or org.gradle.api.plugins.ExtensionContainer. This change should not affect any builds because there are no known use cases supporting custom instances of these API classes.

Changes to exceptions thrown on project evaluation

The exception thrown by Gradle when on build script error or other configuration problem has changed. All such exceptions are now chained in a ProjectConfigurationException. This change will only impact code that explicitly catches and processes an exception thrown by Gradle when configuring a project.

Incubating StartParameter.isParallelThreadCountConfigured() method removed

This incubating method was used internally and was not intended to form part of the public API. It has now been removed.

Upper bound removed from Tooling API ModelBuilder

In Gradle 1.6, we've started work to allow plugins to provide custom tooling API models. A consequence of this work is that the tooling API models are no longer required to extend the org.gradle.tooling.model.Model marker interface. The upper bound extends Model has been removed from the type parameter of ModelBuilder. This change should be both source and binary compatible.

Tooling API ProjectConnection.model() no longer throws UnknownModelException

To support for custom tooling API models, it is no longer possible to determine whether a model is supported without configuring the target build. This exception is now thrown when the result is requested, rather than when the builder is created.

Wrapper environment variable GRADLE_WRAPPER_ALWAYS_UNPACK and GRADLE_WRAPPER_ALWAYS_DOWNLOAD no longer supported

The Gradle wrapper no longer supports the GRADLE_WRAPPER_ALWAYS_UNPACK and GRADLE_WRAPPER_ALWAYS_DOWNLOAD environment variables. Instead, the wrapper is now much better at recovering from failures to download or unpack the distribution.

More packages included in default imports

The set of default imports is now generated directly from the Gradle API. This means that the default imports now includes a number of additional packages that were not previously imported by default. These packages may contain classes that conflict with other imports present in your build scripts.

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.