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.
maven-publish
pluginMavenDeployer
no longer uses global Maven settings.xml
PublishToMavenLocal.repository
property has been removedCommandLineToolConfiguration.withArguments()
usagesourcepath
AuthenticationSupported.getCredentials()
methodAntlrTask
LogLevel
Here are the new features introduced in this Gradle release.
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.
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.
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.
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.
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.
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.
maven-publish
pluginIn 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.
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.
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.
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.
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.
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:
GradleProject.getProjectDirectory()
returns the project directory of the project.GradleEnvironment.getGradleUserHome()
returns the effective Gradle user home directory that will be used for operations performed through the Tooling API.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:
@Defaults
and @Validate
lifecycle rules.CollectionBuilder
and ManagedSet
that allow rules to be applied to all elements in the collection, or to a particular element, or all elements of a given type.It is now also possible to create model elements via the DSL.
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.
--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
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.
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.
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.
There have been some changes to the behaviour of the model { ... }
block:
tasks
container now delegates to a CollectionBuilder<Task>
instead of a TaskContainer
.components
container now delegates to a CollectionBuilder<ComponentSpec>
instead of a ComponentSpecContainer
.binaries
container now delegates to a CollectionBuilder<BinarySpec>
instead of a BinaryContainer
.Generally, the DSL should be the same, except:
model { tasks { myTask(Task) { ... } }
create
method returns void.withType()
method selects elements based on the public contract type rather than implementation type.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 removedPreviously, 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.
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.
CommandLineToolConfiguration.withArguments()
usageThe 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.
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.
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.
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.
AuthenticationSupported.getCredentials()
methodDue 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.
AntlrTask
The AntlrTask
previous unnecessarily exposed the internal methods buildArguments()
and evaluateAntlrResult()
.
These methods have been removed.
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.
The default version of the corresponding tool of the following code quality plugins have been updated:
checkstyle
plugin now uses version 5.9 as default (was 5.7).LeftCurly
rule introduced in checkstyle 5.8 (see https://github.com/checkstyle/checkstyle/issues/247)pmd
plugin now uses version 5.2.3 as default (was 5.1.1).findbugs
plugin now uses version 3.0.1 as default (was 3.0.0).codenarc
plugin now uses version 0.23 as default (was 0.21).This method (and all overloads) has been removed in 2.4, after being deprecated in Gradle 2.3 and superseded by the all()
method.
LogLevel
The package scoped methods of the LogLevel
enumeration have been removed.
We would like to thank the following community members for making contributions to this release of Gradle.
test.testLogging.showStandardStreams = false
(GRADLE-3218)GenerateEclipseWtpFacet
Spec
implementationsEclipseWtpComponent.resource()
and EclipseWtpComponent.property()
We love getting contributions from the Gradle community. For information on contributing, please see gradle.org/contribute.
Known issues are problems that were discovered post release that are directly related to changes made in this release.