Gradle Release Notes

Version 1.7

Gradle 1.7 is the fastest Gradle ever. Significant performance optimizations have been made, particularly in the areas of dependency resolution and build script compilation. All users of Gradle will benefit from these improvements, while large builds stand to gain the most. Improving performance and scalability continues to be a pervasive theme in the evolution of Gradle and 1.7 delivers on this.

In addition to these behind the scenes improvements, Gradle 1.7 is also packed with many exciting new features. The new finalizer task mechanism makes it possible to run a task after another task, regardless of its outcome. This is extremely useful for integration testing where resources (such as application servers) must be shutdown after (possibly failing) tests. Another long awaited feature, the ability to control processing of duplicate files in copy and archive creation operations, has also been added in this release.

The improvements to the Build Setup plugin in Gradle 1.7 build upon the existing functionality (i.e. converting Maven projects to Gradle) to add support for generating projects from a template. Over time this mechanism will be expanded to include custom templates, easing the process of creating a new Gradle project of a certain type.

This release of Gradle also includes major steps forward for building native binaries from C++ source. Support for native binaries in general is an area under heavy development. Expect to see Gradle's capabilities in this area continue to improve in upcoming releases.

Excitingly, Gradle 1.7 contains more contributions from developers outside of the core development team than any other release. This is a steadily increasing trend release on release and is adding significant value to Gradle for all Gradle users. Thank you to all who contributed to Gradle 1.7.

For more information on what's new in Gradle 1.7, please read on.

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Faster Gradle builds

Gradle 1.7 is the fastest version of Gradle yet. Here are the highlights:

As always, the performance improvements that you actually see for your build depends on many factors.

Faster dependency resolution due to in-memory caching of artifact meta-data

With this change, the dependency resolution is much faster. Typically, the larger the project is the more configurations and dependencies are resolved during the build. By caching the artifact meta-data in memory Gradle avoids parsing the descriptor when the same dependency is requested multiple times in a build.

An incremental build for a large project should be tangibly faster with Gradle 1.7. A full build may be much faster, too. The level of performance improvement depends on the build. If a large portion of the build time is taken by slow integration tests, the performance improvements are smaller. Nevertheless, some of the large builds that were used for benchmarking show up to 30% speed increase.

Caching the artifact metadata in-memory is very important for local repositories, such as mavenLocal() and for resolution of snapshots / dynamic versions. Prior to Gradle 1.7, every time a local dependency was resolved, Gradle would load the dependency metadata directly from the local repository. With the in-memory caching of dependency metadata, this behavior now changes. During a single build, a given dependency will be loaded once only and will not be reloaded again from the repository.

This may be a breaking change for builds that depend the on the fact that certain dependencies are reloaded from the repository during each resolution. Bear in mind that the vast majority of builds will enjoy faster dependency resolution offered by the in-memory caching. If your project requires reloading of snapshots or local dependencies during the build please let us know so that Gradle can better understand your scenario and model it correctly.

To avoid increased heap consumption, the in-memory dependency metadata cache may clear the cached data when there is heap pressure.

Improved multiprocess locking

This change improves the mechanism that Gradle uses to coordinate multi-process access to the Gradle caches. This new mechanism means that the Gradle process now requires far fewer operations on the file system and can make better use of in-memory caching, even in the presence of multiple Gradle processes accessing the caches concurrently.

The caches used for dependency resolution and for incremental build up-to-date checks are affected by this change, meaning faster dependency resolution and incremental build checks.

Coupled with this change are some improvements to the synchronization of worker threads within a given Gradle process, which means parallel execution mode is now more efficient.

The new mechanism is biased to the case where a single Gradle process is running on a machine. There should not be any performance regressions when multiple Gradle processes are used, but please raise a problem report via the Gradle Forums if you observe a regression.

Faster build script compilation

This change improves build script compilation by adding some caching in critical points in the classloader hierarchy. This affects, for example, first time users of a build, build authors, and those upgrading a build to a new Gradle version.

Finalizer tasks incubating feature

Gradle 1.7 introduces a new task ordering rule that allows a task to finalize some other task. This feature was contributed by Marcin Erdmann.

Finalizer tasks execute after the task they finalize, and always run regardless of whether the finalized task succeeds or fails. Tasks declare the tasks that finalize them.

configure([integTest1, integTest2]) {
    dependsOn startAppServer
    finalizedBy stopAppServer
}

In this example, it is declared that the integTest1 and integTest2 tasks are finalized by the stopAppServer task. If either of these tasks are executed during a build, the declared finalizer task will be automatically executed after this. If both tasks are executed during a build, the finalizer task will be executed after both tasks have been executed. The finalizer task, stopAppServer, does not need to be declared as a task to be run when invoking Gradle.

Finalizer tasks can be used to clean up resources, produce reports, or perform any other mandatory function after a task executes regardless of whether it succeeds or fails.

Major improvements to C++ project support incubating feature

Gradle has had basic support for C++ projects for some time. This is now expanding with the goal of positioning Gradle as the best build system available for native code projects.

This includes:

Some of these features are included in Gradle 1.7 (see below), while others can be expected in the upcoming releases.

Improved native component model

A key part of improving C++ support is an improved component model which supports building multiple binary outputs for a single defined native component. Using this model Gradle can now produce both a static and shared version of any library component.

Static libraries from C++ sources

For any library declared in your C++ build, it is now possible to either compile and link the object files into a shared library, or compile and archive the object files into a static library (or both). For any library 'lib' added to your project, Gradle will create a 'libSharedLibrary' task to link the shared library, as well as a 'libStaticLibrary' task to create the static library.

Please refer to the User Guide chapter and the included C++ samples for more details.

Per binary configuration

Each binary to be produced from a C++ project is associated with a set of compiler and linker command-line arguments, as well as macro definitions. These settings can be applied to all binaries, an individual binary, or selectively to a group of binaries based on some criteria.

binaries.all {
    // Define a preprocessor macro for every binary
    define "NDEBUG"

    compilerArgs "-fconserve-space"
    linkerArgs "--export-dynamic"
}

binaries.withType(SharedLibraryBinary) {
    define "DLL_EXPORT"
}

Each binary is associated with a particular C++ tool chain, allowing settings to be targeted based on this value.

binaries.all {
    if (toolChain == toolChains.gcc) {
        compilerArgs "-O2", "-fno-access-control"
        linkerArgs "-S"
    }
    if (toolChain == toolChains.visualCpp) {
        compilerArgs "/Z7"
        linkerArgs "/INTEGRITYCHECK:NO"
    }
}

More examples of how binary-specific settings can be provided are in the user guide.

Cygwin support

The C++ plugins now support using g++ when running Gradle under Cygwin.

Improved incremental build

The incremental build support offered by the C++ plugins has been improved in this release, making incremental build very accurate:

  • Detects changes to compiler and linker settings, in addition to changes in source and header files.
  • No longer recompiles source files when linker settings change.
  • Detects changes to dependencies of a binary and recompiles or relinks as appropriate.
  • Detects changes to the toolchain used to build a binary and recompiles and relinks.
  • Removes stale object files when source files are removed or renamed.
  • Removes stale output files when compiler and linker settings change. For example, removes stale debug files when debug is disabled.

JCenter repository support incubating feature

It is now even easier to obtain JVM dependencies from Bintray's JCenter Repository, with the jcenter() repo notation. JCenter is a community repository, that is free to publish to via Bintray.

repositories {
    jcenter()
}

This will add http://jcenter.bintray.com to your repository list, as an Apache Maven repository.

Pattern based file copy configuration incubating feature

Gradle 1.7 adds the ability to specify fine grained configuration of how certain files should be copied by targeting configuration with “Ant Patterns”. This feature was contributed by Kyle Mahan.

Gradle has a unified API for file copying operations, by way of CopySpec, which includes creating archives (e.g. zips). This new feature makes this API more powerful.

task copyFiles(type: Copy) {
    from "src/files"
    into "$buildDir/copied-files"

    // Replace the version number variable in only the text files
    filesMatching("**/*.txt") {
        expand version: "1.0"
    }
}

The filesMatching() method can be called with a closure and configures an instance of FileCopyDetails. There is also an inverse variation, filesNotMatching(), that allows configuration to be specified for all files that do not match the given pattern.

Duplicate file handling for copy and archive operations incubating feature

When copying files or creating archives, it is possible to do so in such a way that effectively creates duplicates at the destination. It is now possible to specify a strategy to use when this occurs to avoid duplicates. This feature was contributed by Kyle Mahan.

task zip(type: Zip) {
    from 'dir1'
    from 'dir2'
    duplicatesStrategy 'exclude'
}

There are two possible strategies: include and exclude.

The include strategy is equivalent to Gradle's existing behavior. For copy operations, the last file copied to the duplicated destination is used. However, a warning is now issued when this occurs. For archive creation (e.g. zip, jar), duplicate entries will be created in the archive.

The exclude strategy effectively ignores duplicates. The first thing copied to a location is used and all subsequent attempts to copy something to the same location are ignored. This means that for copy operations, the first file copied into place is always used. For archive operations, the same is true and duplicate entries will not be created.

It is also possible to specify the duplicates strategy on a very fine grained level using the flexibility of the Gradle API for specifying copy operations (incl. archive operations).

task zip(type: Zip) {
    duplicatesStrategy 'exclude' // default strategy
    from ('dir1') {
        filesMatching("**/*.xml") {
            duplicatesStrategy 'include'
        }
    } 
    from ('dir2') {
        duplicatesStrategy 'include'
    }
}

Generate Gradle wrapper files without touching your build script incubating feature

It is now possible to Gradle Wrapper enable a project without having to create a Wrapper task in your build. That is, you do not need to edit a build script to enable the Wrapper.

To Wrapper enable any project with Gradle 1.7, simply run:

gradle wrapper

The Wrapper files are installed and configured to use the Gradle version that was used when running the task.

To customize the wrapper task you can modify the task in your build script:

wrapper {
    gradleVersion '1.6'
}

If there is already an explicitly defined task of type Wrapper in your build script, this task will be used when running gradle wrapper; otherwise the new implicit default task will be used.

Generate a Java library Gradle project skeleton incubating feature

The build-setup plugin now supports declaring a project type when setting up a build, laying the foundations for creating different types of project starting points conveniently. Gradle 1.7 comes with the java-library type, which generates:

To create a new Java library project, you can execute the following in a directory (no build.gradle needed):

gradle setupBuild --type java-library

See the chapter on the Build Setup plugin for more info, including future directions.

Customise publication identity with new publishing plugins incubating feature

It is now possible to explicitly set the identity of a publication with the new publishing plugins. Previously the identity was assumed to be the same of the project.

For a MavenPublication you can specify the groupId, artifactId and version used for publishing. You can also set the packaging value on the MavenPom.

publications {
    mavenPub(MavenPublication) {
        from components.java

        groupId "my.group.id"
        artifactId "my-publication"
        version "3.1"
        pom.packaging "pom"
    }
}

For an IvyPublication you can set the organisation, module and revision. You can also set the status value on the IvyModuleDescriptor.

publications {
    ivyPub(IvyPublication) {
        from components.java

        organisation "my.org"
        module "my-module"
        revision "3"
        descriptor.status "milestone"
    }
}

This ability is particularly useful when publishing with a different module or artifactId, since these values default to the project.name which cannot be modified from within the Gradle build script itself.

Publish multiple modules from a single Gradle project incubating feature

The publishing plugins now allow you to publish multiple publications from a single Gradle project.

project.group "org.cool.library"

publications {
    implJar(MavenPublication) {
        artifactId "cool-library"
        version "3.1"

        artifact jar
    }
    apiJar(MavenPublication) {
        artifactId "cool-library-api"
        version "3"

        artifact apiJar
    }
}

While possible, it is not trivial to do the same with the old publishing support. The new ivy-publish and maven-publish plugins now make it easy.

TestNG parameters included in test reports incubating feature

TestNG supports parameterizing test methods, allowing a particular test method to be executed multiple times with different inputs. Previously in Gradle's test reports, parameterized methods were listed multiple times (for each parameterized iteration) with no way to differentiate the executions. The test reports now include the toString() values of each parameter for each iteration, making it easy to identify the data set for a given iteration.

Given a TestNG test case:

import org.testng.annotations.*;

public class ParameterizedTest {
    @Test(dataProvider = "1")
    public void aParameterizedTestCase(String var1, String var2) {
        …
    }

    @DataProvider(name = "1")
    public Object[][] provider1() {
        return new Object[][] {
           {"1", "2"},
           {"3", "4"}
        };
    }
}

The test report will show that the following test cases were executed:

This includes Gradle's own HTML test report and the “JUnit XML” file. The “JUnit XML” file is typically used to convey test execution information to the CI server running the automated build, which means the parameter info is also visible via the CI server.

Test task implements standard Reporting interface

The Reporting interface provides a standardised way to control the reporting aspects of tasks that produce reports. The Test task type now implements this interface.

apply plugin: "java"

test {
    reports {
        html.enabled = false
        junitXml.destination = file("$buildDir/junit-xml")
    }
}

The Test task provides a ReportContainer of type TestReports, giving control over both the HTML report and the JUnit XML result files (these files are typically used to communicate test results to CI servers and other tools).

This brings the Test task into line with other tasks that produce reports in terms of API. It also allows you to completely disable the JUnit XML file generation if you don't need it.

Build dashboard improvements incubating feature

The above change (Test task implements standard Reporting interface) means that the test reports now appear in the build dashboard.

Also, the buildDashboard task is automatically executed when any reporting task is executed (by way of the new “Finalizer Task” mechanism mentioned earlier).

Record test output per test case in JUnit XML result files incubating feature

This change facilitates better reporting of test execution on CI servers, notably Jenkins.

The JUnit XML file format is a de-facto standard for communicating test execution results between systems. CI servers typically use this file as the source of test execution information. It was originally conceived by the “JUnit Ant Tasks” that quickly appeared after the introduction of JUnit and became widely used, without a specification ever forming.

This file also captures the system output (System.out and System.err) that occurs during test execution. Traditionally, the output has been recorded at the class level. That is, output is not associated with the individual test cases (i.e. methods) within the class but with the class as a whole. You can now enable “output per test case” mode in Gradle to get better reporting.

test {
    reports {
        junitXml.outputPerTestCase = true
    }
}

With this mode enabled, the XML report will associate output to the particular test case that created it. The Jenkins CI server provides a UI for inspecting the result of a particular test case of class. With outputPerTestCase = true, output from that test case will be shown on that screen. Previously it was only visible on the page for the test class.

This is also necessary for effective use of the Jenkins JUnit Attachments Plugin that allows associating test attachments (e.g. Selenium screen shots) with test execution in the Jenkins UI.

Specify default JVM arguments for the Application plugin incubating feature

Thanks to a contribution by Olaf Klischat, the Application Plugin now provides the ability to specify default JVM arguments to include in the generated launcher scripts.

apply plugin: "application"

applicationDefaultJvmArgs = ["-Dfile.encoding=UTF=8"]

Improved OSGi support through Bnd library update

The OSGi plugin uses the Bnd tool to generate bundle manifests. The version used has changed from 1.50.0 to 2.1.0 with this release.

The most significant improvement obtained through this upgrade is the improved accuracy of generated manifests for Java code that uses the “invokedynamic” byte code instruction.

Automatic string to enum value coercion in DSL incubating feature

It is now possible to set enum value properties in the Gradle DSL using the name of the value as a string. Gradle will automatically convert it the string to the corresponding enum value. For example, this can be used for setting the (new in 1.7) duplicate handling strategy for file copy operations.

task copyFiles(type: Copy) {
    from 'source'
    into 'destination'
    duplicatesStrategy 'exclude'
}

The duplicatesStrategy property is being set here via the CopySpec.setDuplicatesStrategy(DuplicatesStrategy) method, which takes an enum value of type DuplicatesStrategy In the Gradle DSL, the value can be set using the (case-insensitive) name of the desired enum value.

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.

Test report properties

The Test task has been updated to implement the standard Reporting interface. The existing API for configuring reporting and results has now been deprecated. This includes the following methods:

All of the deprecated functionality is still available via the new Reporting mechanism.

Potential breaking changes

In memory dependency metadata caching

As a significant performance optimization, Gradle now caches dependency descriptors in memory across the entire build. This means that if that dependency metadata changes during the build, the changes may not be seen by Gradle. There are no identified usage patterns where this would occur, but it is theoretically possible.

Please see the section on “Faster Gradle Builds” for more information.

Incubating JaCoCo plugin changes incubating feature

Some properties of classes introduced by the JaCoCo code coverage plugin have been renamed with better names.

Incubating BuildSetup plugin changes incubating feature

The ConvertMaven2Gradle, GenerateBuildScript and GenerateSettingsScript classes have been removed. The respective logic is now part of the buildSetup task which has now the type SetupBuild.

The plugin creates different set of tasks, with different types and names depending on the build-setup type.

The setupWrapper task is now called wrapper.

Incubating Ivy publish plugin changes incubating feature

Changed task name in incubating ivy-publish plugin

For consistency with the maven-publish plugin, the task for generating the ivy.xml file for an Ivy publication has changed. This task is now named generateDescriptorFileFor${publication.name}Publication.

Default status value of IvyPublication is integration and no longer defaults to project.status

In order to continue decoupling the Gradle project model from the Ivy publication model, the 'project.status' value is no longer used when publishing with the ivy-publish plugin.

If no status value is set on the IvyModuleDescriptor of an IvyPublication, then the default ivy status ('integration') will be used. Previously, 'release' was used, being the default value for 'project.status'.

Major changes to C++ support incubating feature

The incubating C++ support in Gradle is undergoing a major update. Many existing plugins, tasks, API classes and the DSL have been being given an overhaul. It's likely that all but the simplest existing C++ builds will need to be updated to accommodate these changes.

If you want your existing C++ build to continue working with Gradle, you have 2 options:

  1. Remain on Gradle 1.6 for the next few releases until the C++ support stabilises, and then perform a single migration.
  2. Keep your build updated for the latest changes, being aware that further changes will be required for subsequent releases.

ConfigureableReport renamed to ConfigurableReport incubating feature

The incubating class org.gradle.api.reporting.ConfigureableReport was renamed to org.gradle.api.reporting.ConfigurableReport as the original name was misspelled.

Test report is not generated there are no test classes

The test task is now skipped when there are no test classes (GRADLE-2702).

Previously, the test task was still executed even if there were no test classes. This meant that dependency resolution would occur and an empty HTML report was generated. This new behavior results in faster builds when there are no test classes. No negative impacts on existing builds are expected.

Bnd library used by OSGi plugin updated

The OSGi plugin uses the Bnd tool to generate bundle manifests. The version used has changed from 1.50.0 to 2.1.0 with the 1.7 release.

While this should be completely backwards compatible, it is a significant upgrade.

Changes to the handling of dependency configuration mappings in Ivy descriptor files

Gradle now treats the configuration mapping of a dependency declaration in an Ivy descriptor file (ivy.xml) the same way as Ivy. Previously, there were a number of bugs that affected how Gradle handled configuration mappings in Ivy descriptor files.

These changes mean you may see different resolution results in Gradle 1.7 compared to previous Gradle versions, if you are using Ivy repositories.

Contributors

On behalf of the Gradle community, the Gradle development team would like to thank the following people who contributed to this version of Gradle:

Contributions are an important part of the continuous improvement of Gradle.

If you would like to contribute to Gradle, please see gradle.org/contribute for how to start.

Known issues

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