Gradle Release Notes

Version 2.8

Gradle 2.8 delivers performance improvements and a collection of general fixes and enhancements.

Large builds with many source files should see major improvements in incremental build speed. This release also brings faster build script compilation, faster source compilation when using continuous build, and general performance improvements that apply to all builds.

Building upon the recent releases, this release brings more improvements to the Gradle TestKit. It is now easier to inject plugins under test into test builds.

Work continues on the new managed model. This release brings richer modelling capabilities along with interoperability improvements when dynamically depending on rule based tasks.

A Gradle release would not be complete without contributions from the wonderful Gradle community. This release provides support for file name encoding in Zip files, support for more PMD features and other fixes from community pull requests.

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Faster incremental builds

One of Gradle's key features is the ability to perform “incremental builds”. This allows Gradle to avoid doing redundant work, by detecting that it can safely reuse files created by a previous build. For example, the “class files” created by the Java compiler can be reused if there were no changes to source code or compiler settings since the previous build. This is a generic capability available to all kinds of work performed by Gradle.

This feature relies on tracking checksums of files in order to detect changes. In this Gradle release, improvements have been made to the management of file checksums, resulting in significantly improved build times when the build is mostly up to date (i.e. many previously created files were able to be reused).

Highly incremental builds of projects with greater than 140,000 files have been measured at 35-50% faster with Gradle 2.8. Very large projects (greater than 400,000 files) are also significantly faster again, if there is ample memory available to the build process (see “The Build Environment” in the Gradle User Guide for how to control memory allocation). Smaller projects also benefit from these changes.

No build script or configuration changes, beyond upgrading to Gradle 2.8, are required to leverage these performance improvements.

Faster build script compilation

Build script compilation times have been reduced by up to 30% in this version of Gradle.

This improvement is noticeable when building a project for the first time with a certain version of Gradle, or after making changes to build scripts. This is due to Gradle caching the compiled form of the build scripts.

The reduction in compilation time per script is dependent on the size and complexity of script. Additionally, the reduction for the entire build is dependent on the number of build scripts that need to be compiled.

Faster compilation for continuous builds

In many cases Gradle will spawn a daemon process to host a compiler tool. This is done for performance reasons, as well as to accommodate special heap size settings, classpath configurations, etc. A compiler daemon is started on first use, and stopped at the end of the build.

With Gradle 2.8, compiler daemons are kept running throughout the lifetime of a continuous build session and will only be stopped when the continuous build is cancelled. This improves the performance of continuous builds, since the cost of re-spawning these compilers is avoided for subsequent builds. This change has no impact on non-continuous builds: in this case each compiler daemon will be stopped at the end of the build.

The following compilers are forked and should demonstrate improved performance with continuous builds:

  • Java compiler - when options.fork = true (default is false)
  • Scala compiler - when used with the scala plugin and scalaCompileOptions.useAnt = false (default is true)
  • Groovy compiler - when options.fork = true (default is true)
  • Scala compiler - when used with the play plugin
  • Play Routes compiler, Twirl compiler and Javascript compiler

General performance improvements

This release also contains various other performance improvements that are generally applicable to most builds. These improvements are due to the use of more efficient data structures and smarter caching. Build time reductions vary depending on the size and nature of the build.

Convenient injection of classes under test via TestKit API

Previous releases of Gradle required the end user to provide classes under test (e.g. plugin and custom task implementations) to the TestKit by assigning them to the buildscript's classpath.

This release makes it more convenient to inject classes under test through the GradleRunner API with the method withPluginClasspath(Iterable<File>). This classpath is then available to use to locate plugins in a test build via the plugins DSL. The following code example demonstrates the use of the new TestKit API in a test class based on the test framework Spock:

class BuildLogicFunctionalTest extends Specification {
    @Rule final TemporaryFolder testProjectDir = new TemporaryFolder()
    File buildFile
    List<File> pluginClasspath

    def setup() {
        buildFile = testProjectDir.newFile('build.gradle')
        pluginClasspath = getClass().classLoader.findResource("plugin-classpath.txt")
          .readLines()
          .collect { new File(it) }
    }

    def "execute helloWorld task"() {
        given:
        buildFile << """
            plugins {
                id 'com.company.helloworld'
            }
        """

        when:
        def result = GradleRunner.create()
            .withProjectDir(testProjectDir.root)
            .withArguments('helloWorld')
            .withPluginClasspath(pluginClasspath)
            .build()

        then:
        result.standardOutput.contains('Hello world!')
        result.taskPaths(SUCCESS) == [':helloWorld']
    }
}

Future versions of Gradle will aim for automatically injecting the classpath without additional configuration from the end user.

Zip file name encoding

Gradle will use the default character encoding for file names when creating Zip archives. Depending on where the archive will be extracted, this may not be the best possible encoding to use due to the way various operating systems and archive tools interpret file names in the archive. Some tools assume the extracting platform character encoding is the same encoding used to create the archive. A mismatch between encodings will manifest itself as "corrupted" or "mangled" file names.

Zip tasks can now be configured with an explicit character encoding to use for file names and comment fields in the archive. (This option does not affect the content of the files in the archive.) The default behavior has not been changed, so no changes should be necessary for existing builds.

Configuration of the rule priority threshold for PMD incubating feature

By default, the PMD plugin will report all rule violations and fail the build if any violations are found. This means the only way to ignore low priority violations was to create a custom ruleset.

Gradle now supports configuring a "rule priority" threshold. The PMD report will contain only violations higher than or equal to the priority configured, and the build will only fail if one of these "priority" violations is discovered.

You configure the rule priority threshold via the PmdExtension. You can also configure the property on a per-task level through the Pmd task.

pmd {
    rulePriority = 3
}

Better PMD analysis with type resolution incubating feature

Some PMD rules require access to the dependencies of your project to perform type resolution. If the dependencies are available on PMD's auxclasspath, additional problems can be detected.

Gradle now automatically adds the compile dependencies of each analyzed source set to PMD's auxclasspath. No additional configuration should be necessary to enable this in existing builds.

Managed model improvements

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

Fixed issues

Retrieving the fixed issue information for 2.8 …

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.

The sonar and sonar-runner plugins have been superseded by an external plugin from SonarQube

SonarQube is an open platform to manage code quality, and in previous versions of Gradle the sonar and sonar-runner plugin has provided integration with this analysis tool. An improved plugin is now available directly from the developers of SonarQube. This new plugin supersedes the sonar and sonar-runner plugins that are part of the Gradle distribution; the sonar and sonar-runner plugin are now deprecated and will be removed in Gradle 3.0.

See the official documentation from SonarQube for more details.

Deprecated classes and constants

The following classes have been deprecated and will be removed in Gradle 3.0:

  • org.gradle.api.artifacts.ConflictResolution.
  • org.gradle.api.artifacts.Module.
  • org.gradle.api.tasks.javadoc.AntGroovydoc.
  • org.gradle.api.tasks.scala.AntScalaDoc.
  • org.gradle.BuildExceptionReporter.
  • org.gradle.BuildLogger.
  • org.gradle.BuildResultLogger.
  • org.gradle.TaskExecutionLogger.
  • org.gradle.plugins.ide.eclipse.model.EclipseDomainModel.
  • org.gradle.api.logging.Logging.ANT_IVY_2_SLF4J_LEVEL_MAPPER. This constant is intended to be used only by the Gradle internals, and will be removed from the Gradle API.
  • org.gradle.util.AvailablePortFinder. Although this class is an internal class and not a part of the public API, some users may be utilizing it and should plan to implement an alternative.

Setting Eclipse project name in beforeMerged or whenMerged hook

Setting the Eclipse project name in eclipse.project.file.beforeMerged or eclipse.project.file.whenMerged hook provided by the Eclipse plugin has been deprecated. Support for this will be removed in Gradle 3.0

Adding a one-item List to a FileCollection

In previous versions of Gradle, adding a one-item list of FileCollection objects to a FileCollection would succeed.

For example:

FileCollection foo = files()
foo += [files()]

However, this behavior was never explicitly supported and only worked incidentally because Groovy selected the appropriate method on FileCollection to add a single FileCollection object. In Groovy 2.4, this behavior has changed and no longer selects the correct method (see "Using the + operator with Iterable objects" under Upgraded to Groovy 2.4.4). As this construct may be in use, we have added a workaround to maintain backwards compatibility, but this unsupported functionality is considered deprecated.

Instead, adding the FileCollection without a list should be used:

FileCollection foo = files()
foo += files()

Potential breaking changes

Upgraded to Groovy 2.4.4

The Gradle API now uses Groovy 2.4.4. Previously, it was using Groovy 2.3.10. This change should be transparent to the majority of users; however, it can cause minor problems with existing build scripts and plugins.

Please refer to the Groovy language changelogs for further details.

New PMD violations due to type resolution changes

PMD can perform additional analysis for some rules (see above), therefore new violations may be found in existing projects. Previously, these rules were unable to detect problems because classes outside of your project were not available during analysis.

Updated to CodeNarc 0.24.1

The default version of CodeNarc has been updated from 0.23 to 0.24.1. Should you want to stay on older version, it is possible to downgrade it using the codenarc configuration:

dependencies {
   codenarc 'org.codenarc:CodeNarc:0.17'
}

Updated to bndlib 2.4.0

The built-in OSGi plugin uses the bndlib library internally. The library has been updated from 2.1.0 to 2.4.0.

Improved IDE project name de-duplication

To ensure unique project names in the IDE, Gradle applies de-duplication logic when generating IDE metadata for Eclipse and Idea projects. This de-duplication logic has been improved such that all projects with non-unique names are now de-duplicated by adding a prefix based on the parent project(s). For example:

Given a Gradle multiproject build with the following project structure:

root
|-foo
|  \- app
|
\-bar
   \- app

The following IDE project name mapping will result:

root
|-foo
|  \- foo-app
|
\-bar
   \- bar-app

Duplicate words in a row within the de-duplication prefix are removed from the generated ide project name.

Given a project with the following structure:

myapp
|-myapp-foo
|  \- app
|
\-myapp-bar
   \- app

The following IDE project name mapping will result:

myapp
|-myapp-foo
|  \- myapp-foo-myapp-app
|
\-myapp-bar
   \- myapp-bar-myapp-app

Changes to the incubating integration between the managed model and the Java plugins

The Java plugins make some details about the project source sets visible in the managed model, to allow integration between rules based plugins and the stable Java plugins. This integration has changed in this Gradle release, to move more of the integration into the managed model:

  • The sources container is no longer added as a project extension. It is now visible only to rules, as part of the managed model.
  • ClassDirectoryBinarySpec instances can no longer be added to the binaries container. Instances are still added to this container by the Java plugins for each source set, however, additional instances cannot be added. This capability will be added again in a later release, to allow rules based plugins to define arbitrary class directory binaries.
  • The Java plugins do not add instances to the binaries container until they are required by rules. Previously, the plugins would add these instances eagerly when the source set was defined.

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.

Retrieving the known issue information for 2.8 …