Gradle Release Notes

Version 2.4

The big story for Gradle 2.4 is the improved performance. While it's not unusual for a new Gradle release to be the fastest Gradle yet, Gradle 2.4 is significantly faster. Many early testers of Gradle 2.4 have reported that overall build times have improved by 20% up to 40%.

There are two main components to the improved performance; general configuration time optimizations, and the class reuse with the Gradle Daemon. As such, using the Gradle Daemon now provides an even greater performance advantage.

If you are using Gradle to build native code (e.g. C/C++), the news gets even better with the introduction of parallel compilation.

Memory consumption has also been reduced when compiling Java source code with Java 7 and 8, which can significantly improve compile times for large Java projects.

Other highlights include support for Amazon S3 dependency repositories and support for using annotation processors with Groovy code and more.

Table Of Contents

New and noteworthy

Here are the new features introduced in this Gradle release.

Significant configuration time performance improvements

Gradle 2.4 features a collection of performance improvements particularly targeted at “configuration time” (i.e. the part of the build lifecycle where Gradle is comprehending the definition of the build by executing build scripts and plugins). Several users of early Gradle 2.4 builds have reported build time improvements of around 20% just by upgrading to Gradle 2.4.

Most performance improvements were realized by optimizing internal algorithms along with data and caching structures. Builds that have more configuration (i.e. more projects, more build scripts, more plugins, larger build scripts) stand to gain more from the improvements. The Gradle build itself, which is of non trivial complexity, realized improved configuration times of 34%. Stress tests run as part of Gradle's own build pipeline have demonstrated an 80% improvement in configuration time with Gradle 2.4.

No change is required to builds to leverage the performance improvements.

Improved performance of Gradle Daemon via class reuse

The Gradle Daemon is now much smarter about reusing classes across builds. This makes all Gradle builds faster when using the Daemon, and builds that use non-core plugins in particular. This feature is completely transparent and applies to all builds.

The Daemon is a persistent process. For a long time it has reused the Gradle core infrastructure and plugins across builds. This allows these classes to be loaded once during a “session”, instead of for each build (as is the case when not using the Daemon). The level of class reuse has been greatly improved in Gradle 2.4 to also cover build scripts and third-party plugins. This improves performance in several ways. Class loading is expensive and by reusing classes this just happens less. Classes also reside in memory and with the Daemon being a persistent process reuse also reduces memory usage. This also reduces the severity of class loader leaks (because fewer class loaders actually leak) which again reduces memory usage.

Perhaps more subtly, reusing classes across builds also improves performance by giving the JVM more opportunity to optimize the code. The optimizer typically improves build performance dramatically over the first half dozen builds in a JVM.

The Tooling API, which allows Gradle to be embedded in IDEs automatically uses the Gradle Daemon. The Gradle integration in IDEs such as Android Studio, Eclipse, IntelliJ IDEA and NetBeans also benefits from these performance improvements.

If you aren't using the Gradle Daemon, we urge you to try it out with Gradle 2.4.

Parallel native compilation

Starting with 2.4, Gradle uses multiple concurrent compilation processes when compiling C/C++/Objective-C/Objective-C++/Assembler languages. This is automatically enabled for all builds and works for all supported compilers (GCC, Clang, Visual C++). Up until this release, Gradle compiled all native source files sequentially.

This change has dramatic performance implications for native builds. Benchmarks for a project with a 500 source files on a machine with 8 processing cores available exhibited reduced build times of 53.4s to 12.9s.

The degree of concurrency is determined by the new “max workers” build setting.

New “max workers” build setting incubating feature

The new --max-workers=«N» command line switch, and synonymous org.gradle.workers.max=«N» build property (e.g. specified in gradle.properties) determines the degree of build concurrency.

As of Gradle 2.4, this setting influences native code compilation and parallel project execution. The “max workers” setting specifies the size of these independent worker pools. However, a single worker pool is used for all native compilation operations. This means that if two (or more) native compilation tasks are executing at the same time, they will share the worker pool and the total number of concurrent compilation options will not exceed the “max workers” setting.

Future versions of Gradle will leverage the shared worker pool for more concurrent work, allowing more precise control over the total build concurrency.

The default value is the number of processors available to the build JVM (as reported by Runtime.availableProcessors()). Alternatively, it can be set via the --max-workers=«N» command line switch or org.gradle.workers.max=«N» build property where «N» is a positive, non-zero, number.

Please note: the --parallel-threads command line switch has been deprecated in favor of this new setting.

Reduced memory consumption when compiling Java source code with Java 7 and 8

By working around JDK bug JDK-7177211, Java compilation requires less memory in Gradle 2.4. This JDK bug causes what was intended to be a performance improvement to not improve compilation performance and use more memory. The workaround is to implicitly apply the internal compiler flag -XDuseUnsharedTable=true to all compilation operations.

Very large Java projects (building with Java 7 or 8) may notice dramatically improved build times due to the decreased memory throughput which in turn requires less aggressive garbage collection in the build process.

Support for Amazon Web Services S3 backed repositories incubating feature

It is now possible to consume dependencies from, and publish to, Amazon Web Services S3 stores when using MavenArtifactRepository or IvyArtifactRepository.

repositories {
    maven {
        url "s3://someS3Bucket/maven2"
        credentials(AwsCredentials) {
            accessKey "someKey"
            secretKey "someSecret"
        }
    }

    ivy {
        url "s3://someS3Bucket/ivy"
        credentials(AwsCredentials) {
            accessKey "someKey"
            secretKey "someSecret"
        }
    }
}

Downloading dependencies from S3 is supported for Maven and Ivy type repositories as above.

Publishing to S3 is supported with both the ivy-publish and maven-publish plugins, as well as when using an IvyArtifactRepository with an Upload task (see section 8.6. Publishing artifacts of the User Guide).

Please see section 50.6. Repositories of the User Guide for more information on configuring S3 repository access.

This feature was contributed by Adrian Kelly.

Support for publishing to Maven repositories over SFTP using maven-publish plugin

In previous releases, it was not possible to publish to a Maven repository (via the maven-publish plugin) via SFTP in the same manner that it was for an Ivy repository or when downloading dependencies. This restriction has been lifted, with the publishing now supporting all of the transport protocols that Gradle currently supports (file, http(s), sftp and s3).

This change will also make it possible to seamlessly use any transports that Gradle will support in the future at that time.

Please see section 50.6. Repositories of the User Guide for more information on configuring SFTP repository access.

Depending on a particular Maven snapshot version

It is now possible to depend on particular Maven snapshot, rather than just the “latest” published version.

dependencies {
  compile "org.company:my-lib:1.0.0-20150102.010203-20"
}

The Maven snapshot version number is a timestamp and snapshot number. The snippet above is depending on the snapshot of version 1.0.0 published on the 2nd of January 2015, at 01:02:03 AM which was the 20th snapshot published.

This feature was contributed by Noam Y. Tenne.

Support for “annotation processing” of Groovy code

It is now possible to use Java's “annotation processing” with Groovy code. This, for example, allows using the Dagger dependency injection library, that relies on annotation processing, with Groovy code.

Annotation processing is a Java centric feature. Support for Groovy is achieved by having annotation processors process the Java “stubs” that are generated from Groovy code. The stubs convey the structure of the class, which is typically used to allow Java code to compile against the Groovy code in “one pass”. Annotations on structural elements (i.e. classes/methods/fields) will be present in the generated stubs. Annotation processors will detect such annotations on stubs as they would with “normal” Java code.

The support for annotation processing of Groovy code is limited to annotation processors that generate new classes, and not to processors that modify annotated classes. The official and supported annotation processing mechanisms do not support modifying classes, so almost all annotation processors will work. However, some popular annotation processing tools, notably Project Lombok, that use unofficial API to modify classes will not work.

This feature was contributed by Will Erickson.

Generate wrapper with specific version from command-line

Previously to generate a Gradle wrapper with a specific version, or a custom distribution URL, you had to change the build.gradle file to contain a wrapper task with a configured gradleVersion property.

Now the target Gradle version or the distribution URL can be configured from the command-line, without having to add or modify the task in build.gradle:

gradle wrapper --gradle-version 2.3

And with a distribution URL:

gradle wrapper --gradle-distribution-url https://myEnterpriseRepository:7070/gradle/distributions/gradle-2.3-bin.zip

This feature was contributed by Lóránt Pintér.

Customization of application plugin start script generation incubating feature

The application plugin can be used to create “executable” distributions Java-based application, including operating system specific start scripts. While certain values in the generated scripts (e.g. main class name, classpath) were customizable, the script content was generally hardcoded and cumbersome to change. With Gradle 2.4, it is now much easier to fully customise the start scripts.

The generation of the scripts is performed by a CreateStartScripts task. Please consult its DSL reference for customization examples.

Tooling API improvements incubating feature

The tooling API allows Gradle to be embedded in other applications, such as an IDE. This release includes a number of improvements to the tooling API:

An application can now receive test progress events as a build is executed. Using these events, an application can display or report on test execution as tests run during the build.

An application receives test events using the LongRunningOperation.addTestProgressListener() method.

The following additions have been added to the respective Tooling API models:

Rule based model configuration improvements

A number of improvements have been made to the rule based model configuration used by the native language plugins in this release. There is also a new User Guide chapter that explains just what “rule based model configuration” is.

Key additions and improvements in Gradle 2.4:

It is now also possible to create model elements via the DSL.

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

Setting number of build execution threads with --parallel-threads

The, incubating, --parallel-threads command line switch has been superseded by the new --max-workers command line switch and synonymous org.gradle.workers.max build property. Likewise, the StartParameter.getParallelThreadCount() has also been deprecated.

This setting configured parallel project execution.

The --parallel-threads is still respected, until removed. If not specified, the value specified for --max-workers will be used.

If you were using an invocation such as:

./gradlew build --parallel-threads=4

The replacement is now:

./gradlew build --max-workers=4 --parallel

Alternatively, the following can be used, which will use the default value for --max-workers:

./gradlew build --parallel

Lifecycle plugin changes

The tasks build, clean, assemble and check are part of the standard build lifecycle and are added by most plugins, typically implicitly through the base or language-base plugins. Due to the way these tasks are implemented, it is possible to redefine them simply by creating your own task of the same name. This behavior has been deprecated and will not be supported in Gradle 3.0. That is, attempting to define a task with the same name as one of these lifecycle tasks when they are present will become an error just like any other attempt to create a task with the same name as an existing task.

Potential breaking changes

Incompatibility with Team City 9.0.3 and earlier

An internal change to Gradle test execution has broken the Gradle integration provided by JetBrains' TeamCity integration server. JetBrains have acknowledged the issue and have fixed the problem for the pending 9.0.4 release of TeamCity.

Please see https://youtrack.jetbrains.com/issue/TW-40615 for more information on the problem.

If you are affected by this issue, you can install a pre-release version of the Gradle plugin for TeamCity which is available via the above link.

Class reuse across builds when using the Daemon

Due to the performance improvements enabled by reusing classes across builds with the Daemon, builds that equate static state to build state may behave differently with Gradle 2.4.

Previously, classes were not reused across builds. This meant that each build created a new class object and therefore fresh static class state. It was therefore theoretically possible to use static state of classes loaded during the build as a kind of “build state”, which was reset for each build. This was never a supported feature or recommended technique.

Now, due to classes being reused this is no longer possible. Class objects are reused across builds, including their static state.

The recommended way of achieving “build state” is to use a root project extension, or extra property.

Model DSL changes

There have been some changes to the behaviour of the model { ... } block:

Generally, the DSL should be the same, except:

Updated default Scala Zinc compiler version

The default version of the Scala Zinc compiler has changed from 0.3.0 to 0.3.5.3.

MavenDeployer no longer uses global Maven settings.xml

When publishing to a Maven repository using an Upload task (e.g. uploadArchives) and the mavenDeployer repository type, the global Maven settings.xml file is no longer consulted.

Previously, the “mirror”, “authentication” and “proxy” settings defined in the global settings.xml file were effecting publishing, making builds less portable which is no longer the case.

This resolves [GRADLE-2681].

The user settings file (i.e. ~/.m2/settings.xml) is still consulted for the location of the local repository when performing a local install (e.g. gradle install or gradle publishToMavenLocal).

PublishToMavenLocal.repository property has been removed

Previously, the PublishToMavenLocal task (as used by the maven-publishing plugin) could be configured with an ArtifactRepository instance, which would specify the location to install to. The default repository was the repository that returned by RepositoryHandler.mavenLocal().

It is no longer possible to provide an arbitrary repository to this task. If you need to publish to an arbitrary repository, please use the PublishToMavenRepository task type instead.

Changed default assembler executable for GCC/Clang tool chains

The default tool used when turning assembler into object files is now gcc or clang instead of as.
Some arguments that were specific to as were converted to their GCC/Clang equivalents.
If you were passing arguments to the assembler, you may now need to use -Wa when passing them.

Please see GCC's documentation for passing arguments to the assembler.

Changes to CommandLineToolConfiguration.withArguments() usage

The CommandLineToolConfiguration allows fine grained configuration of a tool execution for the native domain, for example when configuring a GccPlatformToolChain. There are changes to the semantics of the withArguments() method.

The withArguments() method used to be called just before Gradle built the command-line arguments for the underlying tool for each source file. The arguments passed to this would include the path to the source file and output file. This hook was intended to capture "overall" arguments to the command-line tool instead of "per-file" arguments. Now, the withArguments() method is called once per task execution and does not contain any specific file arguments.
Any changes to arguments using this method will affect all source files.

Implicit Groovy source compilation while compiling build script is now disabled

The Groovy compiler by default looks for dependencies in source form before looking for them in class form. That is, if Groovy code being compiled references foo.bar.MyClass then the compiler will look for foo/bar/MyClass.groovy on the classpath. If it finds such a file, it will try to compile it. If it doesn't it will then look for a corresponding class file.

As of Gradle 2.4, this feature has been disabled for build script compilation. It does not affect the compilation of “application” Groovy code (e.g. src/main/groovy). It has been disabled to make build script compilation faster.

If you were relying on this feature, please use the buildSrc feature as a replacement.

Changes to Groovy compilation when annotation processors are present

When annotation processors are “present” for a Groovy compilation operation, all generated stubs are now compiled regardless of whether they are required or not. This change was required in order to have annotation processors process the stubs. Previously the stubs were made available to the Java code under compilation via the source path, which meant that only classes actually referenced by Java code were compiled. The implication is that more compilation is now required for Groovy code when annotation processors are present, which means longer compile times.

This is unlikely to be noticeable unless the code base contains a lot of Groovy code. If this is problematic for your build, the solution is to separate the code that requires annotation processing from the code that does not to some degree.

Changes to default value for Java compilation sourcepath

The source path indicates the location of source files that may be compiled if necessary. It is effectively a complement to the class path, where the classes to be compiled against are in source form. It does not indicate the actual primary source being compiled.

The source path feature of the Java compiler is rarely needed for modern builds that use dependency management.

The default value for the source path as of this release is now effectively an empty source path. Previously Gradle implicitly used the same default as the javac tool, which is the -classpath value. This causes unexpected build results when source accidentally ends up on the classpath, which can happen when dependencies surprisingly include source as well as binaries.

This improvement was contributed by Thomas Broyer.

Changes to AuthenticationSupported.getCredentials() method

Due to the addition of support for AWS S3 backed repositories, some behavioral changes have been made to the AuthenticationSupported interface, which is implemented by MavenArtifactRepository and IvyArtifactRepository.

The getCredentials() and credentials(Action) methods now throw an IllegalStateException if the configured credentials are not of type PasswordCredentials, now that it is possible to use different types of credentials.

Changes to API of AntlrTask

The AntlrTask previous unnecessarily exposed the internal methods buildArguments() and evaluateAntlrResult().

These methods have been removed.

Updated libraries used by the Gradle API

Some dependencies used in Gradle have been updated.

These libraries are expected to be fully backwards compatible. It is expected that no Gradle builds will be negatively affected by these changes.

Updated default tool versions for code quality plugins

The default version of the corresponding tool of the following code quality plugins have been updated:

Deprecated ComponentMetadataHandler.eachComponent() has been removed

This method (and all overloads) has been removed in 2.4, after being deprecated in Gradle 2.3 and superseded by the all() method.

Removal of package scoped methods of LogLevel

The package scoped methods of the LogLevel enumeration have been removed.

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.