The big news in Gradle 2.1 is the new, simpler, mechanism for using community plugins in your build, integrated with the newGradle Plugin Portal. This is one of many improvements planned to expand the Gradle platform by making the lives of both plugins developers and users better through new features and tooling.
Another very new exciting feature is the addition of incremental Java compilation, which promises to significantly reduce compilation times during the development cycle. Users of Apache Ant and Apache Maven may be familiar with incremental Java compilation from those tools. Gradle's incremental Java compiler is not based on the same approach as these tools and does not suffer from the same set of problems that plague incremental compilation with these tools. Please see the “Incremental Java compilation” section in “New and noteworthy” for more information.
We are particularly proud of Gradle 2.1 containing contributions from 18 people outside of the core Gradle development team, which is a new record for the project. Thank you to everyone who contributed. Also, thanks to all who raise issue reports for the Gradle 2.0 release allowing us to make Gradle 2.1 even better.
As usual there's also a smattering of other improvements and bug fixes, detailed below.
We hope you enjoy Gradle 2.1.
New and noteworthy
Here are the new features introduced in this Gradle release.
The new plugin resolution mechanism, backed by the newGradle Plugin Portal, makes it easier to use community Gradle plugins. Instead of combining abuildscript
script block and anapply
statement, both statements can be replaced by aplugins script block.
plugins { id 'com.company.myplugin' version '1.3'}
Gradle will query the Plugin Portal for the implementation details of the specified plugins. The Plugin Portal's pluginbrowsing interface provides copy/paste friendly snippets.
All plugin authors are encouraged to submit their plugins for inclusion in the Plugin Portal. Submission instructions can be foundon the Plugin Portal site.
Many enhancements and features are planned for both the Plugin Portal and plugins in general. The newplugins {}
block is not yet a complete replacement for the existingapply()
method that is used to apply plugins. Its functionality will be expanded over coming releases.
Gradle 2.1 adds, incubating, support for compiling Java code incrementally.
Gradle has long had the ability to perform any build task incrementally by only performing the task if the inputs or outputs of the task change. When applied to Java compilation, this means that all the source for a given task will be compiled if any source file needs to be recompiled. The new incremental compilation feature compliments incremental task execution by only recompiling the actual source that needs to be recompiled, instead of all the source.
Incremental compilation has two key benefits:
- Reduced compilation time during development due to less files being compiled
- Class files whose content is unchanged by a compile are not updated on the filesystem
The second point above is important for tools such asJRebel that watch for changed class files in order to reload the class at runtime.
Incremental compilation can be enabled via theoptions
property of theJavaCompile
task. The following example illustrates enabling incremental compilation for allJavaCompile
tasks.
allprojects { tasks.withType(JavaCompile) { options.incremental = true }}
Incremental compilation requires extra work and record keeping during compilation to achieve. This means that a full compile when incremental compile is enabled can be slower than if it was not enabled. However, this cost is offset for subsequent compile operations as only a subset of the source is compiled.
The current implementation is not able to fully analyze the impact of all changes to the source code in terms of identifying exactly which classes need to be recompiled. In such situations, all of the source will be recompiled in order to avoid inconsistent compilation results. Incremental Java compilation will improve over coming Gradle versions to be generally faster, and to invoke a full recompile in response to fewer types of changes.
It is worthwhile to note that Gradle's incremental Java compiler is not based on Apache Ant's incremental compiler (which is also used by Apache Maven). Incremental compilation with Ant (and Maven) has severe limitations and is notorious for producing inconsistent results. That is, it frequently produces different set of bytecode to what a full recompile would produce. This is due to it being based on timestamp comparisons and dependency analysis through bytecode analysis alone. The Gradle incremental compiler is not based on timestamps and also employs bytecodeand source analysis in order to more thoroughly analyze the impact of a change.
While we have extensively tested this feature during development, it will significantly benefit from usage “in the field”. Please try out this exciting new feature and report any problems encountered via theGradle Forums.
For more information please see the user guide section on “Incremental Java Compilation”.
Use of HTTPS for mavenCentral() and jcenter() dependency repositories
The commonly used Maven Central and Bintray jCenter repositories are now accessed over the HTTPS protocol. No change is required to builds to take advantage of this change.
If you are using themavenCentral()
orjcenter()
repository notations your build will now access these repositories via HTTPS.
Groovy version upgraded to 2.3.6
Gradle 2.1 includes Groovy 2.3.6, where Gradle 2.0 included Groovy 2.3.4.
This is a non breaking change. All build scripts and plugins that work with Gradle 2.0 will continue to work without change.
Child process descriptions in process listings
Gradle often launches child processes during a build to perform work. For example, Gradle executes test in a forked JVM process. During a large build, particularly whenbuilding in parallel, there may be more than one forked Gradle process at any time. In previous Gradle versions, there was no practical way to determine which process was doing what without looking inside the JVM of each process. Processes are now started with a description as a command line argument. Command line arguments are usually displayed by process listing utilities such asps
andjps
, which makes it easy to now identify what kind of Gradle process it is.
The following is an example of output from'jps -m'
during a Gradle 2.1 build:
28649 GradleWorkerMain 'Gradle Test Executor 17'28630 GradleWorkerMain 'Gradle Compiler Daemon 1'
This feature was contributed byRob Spieldenner during the“Contributing To Gradle Workshop” at theGradle Summit 2014 Conference.
Groovy Compiler Configuration Script Supportincubating feature
It is now possible to perform advanced Groovy compilation configuration by way of the newGroovyCompileOptions.configurationScript
property (theGroovyCompileOptions
instance is available as thegroovyOptions
property of theGroovyCompile
task). This makes it possible to impose global compiler transformations and other configuration.
For example, to globally enable Groovy's strict type checking, a compiler config script can be created with…
import groovy.transform.TypeCheckedwithConfig(configuration) { ast(TypeChecked)}
And specified in the build script as…
compileGroovy { groovyOptions.configurationScript = file("myConfigScript.groovy")}
Wherefile("myConfigScript.groovy")
contains the Groovy code from above.
This feature was contributed byCédric Champeau.
It is now possible to havePMD static analysis print results directly to the console.
pmd { consoleOutput = true}
Output will be written toSystem.out
in addition to any configured reports.
This feature was contributed byVyacheslav Blinov.
Dependency exclusions are included in POM file bymaven-publish
pluginincubating feature
The incubatingmaven-publish plugin will now handle dependency excludes when generating a POM file for publishing.
So for a dependency declaration like:
dependencies { compile("my.org:my-module:1.2") { exclude group: 'commons-logging', module: 'commons-logging' exclude group: 'commons-collections' }}
The generated POM file will contain the following content:
<dependency> <groupId>my.org</groupId> <artifactId>my-module</artifactId> <version>1.2</version> <scope>runtime</scope> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> <exclusion> <groupId>commons-collections</groupId> <artifactId>*</artifactId> </exclusion> </exclusions></dependency>
This feature addresses [GRADLE-2945] and was contributed byBiswa Dahal.
Support for the 'branch' attribute when publishing or resolving Ivy modulesincubating feature
The incubatingivy-publish plugin now supports setting the 'branch' attribute on the module being published:
publishing { publications { ivy(IvyPublication) { descriptor.branch = 'testing' } }}
When resolving Ivy modules, component metadata rules can also access the branch attribute via theIvyModuleDescriptor interface.
dependencies { components { eachComponent { ComponentMetadataDetails details, IvyModuleDescriptor ivyModule -> if (details.id.group == 'my.org' && ivyModule.branch == 'testing') { details.changing = true } } }}
Support for publishing extra 'info' elements when publishing Ivy modulesincubating feature
The incubatingivy-publish plugin now supports publishing extra'info'
elements to the ivy.xml file generated via theIvyModuleDescriptorSpec interface. Configured extra info elements are added as children of the ivy'info'
element.
publishing { publications { ivy(IvyPublication) { descriptor.extraInfo 'http://my.namespace', 'myElement', 'Some value' } }}
Note that theivy schema demands that any extra info elements be added after any child elements of'info'
that are defined in the schema (e.g.'description'
or'ivyauthor'
).
This means that anywithXml() actions must take care to insert any schema-defined 'info' child elementsbefore any extra'info'
elements that may have been added.
Furthermore, retrieving extra info elements with namespace when resolving Ivy modules is also available now.
This is exposed via theIvyExtraInfo object in component metadata rules.
dependencies { components { eachComponent { ComponentMetadataDetails details, IvyModuleDescriptor ivyModule -> if (ivyModule.extraInfo.get('http://my.namespace', 'myElement') == 'changing') { details.changing = true } } }}
Note that theMap<String, String>
representation for extra info elements inIvyModuleDescriptor has been replaced withIvyExtraInfo.
Tooling API improvements
Thetooling API is used to embed and programmatically invoke Gradle builds. This release sees some new features added to the tooling API.
The Tooling API now provides a way to canceloperations, such as running a build, using theCancellationTokenSource API to submit cancel requests. The current implementation attempts to cancel the build first, and then will resort to stopping the daemon.
Task visibility is exposed in Tooling APIincubating feature
This release sees further improvements to theBuildInvocations
model added in Gradle 1.12. In particular, tasks and selectors accessible from this model now expose information about theirvisibility as thepublic
property.
This change means that it is now possible to implement the equivalent ofgradle tasks
using the tooling API.
Command line report to show details of the components produced by the buildincubating feature
Sometimes it can be difficult to figure out exactly how Gradle has been configured and what a given build will produce. To help address this, Gradle now includes a new command line report that shows you some useful details about the components that your project produces. To use the report, simply rungradle components
.
In this release, the report shows details of the native libraries and executables defined by the native language plugins. It also shows some basic details about the components defined by the Jvm language plugins. Over the next few releases, this report will grow to include more information about other types of components.
Potential breaking changes
Upgrade to Groovy 2.3.6
The version of Groovy that Gradle uses to compile and run build scripts has been upgraded from 2.3.4 to 2.3.6. This should be a non-breaking change, but is mentioned as it is an update to a library that is used by all Gradle builds.
Changed Java compiler integration for joint Java - Scala compilation
TheScalaCompile
task type now uses the same Java compiler integration as theJavaCompile
andGroovyCompile
task types for performing joint Java - Scala compilation. Previously it would use the old Ant-based Java compiler integration, which is no longer supported in the Gradle 2.x stream.
This change should be backwards compatible for all users, and should improve compilation time when compiling Java and Scala together.
jcenter() repository notation now uses HTTPS instead of HTTP
Thejcenter()
repository definition now uses HTTPS instead of HTTP. This should be backwards compatible for all users. If for any reason you want to use explicitly HTTP for connecting the Bintray's JCenter repository you can simply reconfigure the URL:
repositories { jcenter { url = "http://jcenter.bintray.com/" }}
mavenCentral() repository notation now uses HTTPS instead of HTTP
ThemavenCentral()
repository definition now uses HTTPS instead of HTTP. This should be backwards compatible for all users. If for any reason you want to use explicitly HTTP for connecting the Maven Central repository you can simply add the repo with the HTTP protocol explicitly:
repositories { maven { url = "http://repo1.maven.org/maven2/" }}
Default FindBugs version was upgraded to 3.0.0
This way the FindBugs plugin works out of the box with newer Java versions (most notably: Java 1.8). If you use Java 1.6 you need to configure an older version of FindBugs explicitly:
findbugs { toolVersion = '2.0.3'}
Changes to incubating native language plugins
The Gradle team is currently working hard on a new, faster configuration model as well as rework that will enable full dependency management support for native binaries. As part of this work, many changes have been made to the incubating native language plugins. While some effort has been made to avoid unnecessary breakages, in many cases such changes have been required.
It is anticipated that these plugins will remain unstable for the next release or two. Considering that fact, it may be prudent to hold off upgrading your native build until the underlying infrastructure has stabilised. Naturally, we'll behappy to assist with your migration, whether you choose to stick with the 'bleeding-edge' or prefer to wait.
Native language plugins no longer apply the base plugin
The native language plugins now apply theLifecycleBasePlugin
instead of theBasePlugin
. This means that the default values defined by theBasePlugin
are not available.
Of note, the following actions of theBasePlugin
will be missing:
- The
org.gradle.api.plugins.BasePluginConvention
and it's use to configure thedists
directory,libs
directory andarchivesBaseName
- The
build<Configuration>
task rule - The
upload<Configuration>
task rule - Any default
Configuration
instances
Domain model reorganisation
Many domain model classes have been renamed for consistency, and to permit better integration with the newjvm
component model.
In general, model classes that define how a component or binary is built have been renamed with theSpec
suffix. (Previously, we inconsistently used theProject
prefix for this purpose). For example,ProjectNativeComponent
is nowNativeComponentSpec
andCUnitTestSuiteBinary
is nowCUnitTestSuiteBinarySpec
.
In addition to these renames for consistency, the following changes were made:
- Merged
NativeTestSuite
andProjectComponentNativeTestSuite
NativeTestSuiteBinary
no longer extendsNativeExecutableBinary
- Merged
TestSuiteExecutableBinary
intoNativeTestSuiteBinary
Changes to native cross compilation and custom platforms support
To avoid a proliferation of methods onPlatformConfigurableToolChain, we removed:
target(Platform, Action)
target(Platform)
target(Iterable<? extends Platform>)
target(List<String>)
target(String... platformNames)
target(Iterable<? extends Platform>, Action<? super TargetedPlatformToolChain>)
Changes tosources
DSL
When a language plugin is applied, aLanguageSourceSet
is only added to aFunctionalSourceSet
when thatFunctionalSourceSet
is associated with a component. In practise, this means that a build script should configure any language source sets after the components have been defined.
More details are available in the following section:Changes to the incubatingLanguageBasePlugin
.
Changes to CUnit configuration DSL
- The C language source set for CUnit test sources has been renamed from 'cunit' to 'c'. This means that by convention Gradle will look for test sources in
src/<test-suite-name>/c
. The CUnit test suite components are created via model rules, and must be configured via model rules:
model { testSuites { helloTest { binaries.all { lib library: "cunit", linkage: "static" } } } }
The source set for a test suite component is created via model rules, and must be configured via model rules:
model { sources { variantTest { c { lib sources.hello.c lib sources.helloTest.cunitLauncher } } } }
TheRunTestExecutable
task now implementsExecSpec
, allow test execution to be further configured.
- The
RunTestExecutable.testExecutable
property has been removed and replaced byRunTestExecutable.executable
.
Removed old mechanism for declaring dependencies
Very early versions of thecpp-lib
andcpp-exe
plugins had rudimentary support for publishing and resolving native components. This support was never fully functional, and has now been completely removed in preparation for full support in the upcoming releases.
Changes to the incubatingLanguageBasePlugin
TheLanguageBasePlugin
serves as a basis for the new component-based native and java language plugin suites. As part of ongoing work in these domains, major changes have been made to this base plugin.
Domain model reorganisation
- Renamed
ProjectComponent
->ComponentSpec
- Renamed
ProjectComponentContainer
->ComponentSpecContainer
- Renamed
ComponentSpecIdentifier
->NamedProjectComponentIdentifier
- Renamed
ProjectBinary
->BinarySpec
RenamedprojectComponents
container tocomponentSpecs
TheprojectComponents
container extension has been renamed tocomponentSpecs
. This container is now added by theComponentModelBasePlugin
and not by theLanguageBasePlugin
.
Creation of defaultLanguageSourceSet
instances
In previous Gradle versions each language plugin applied triggered the automatic creation of aLanguageSourceSet
for each FunctionalSourceSet in the project. With Gradle 2.1, this has been changed to that only languages appropriate to the respective component are added to theFunctionalSourceSet
.
To facilitate this change, a functional source set is created for each declared component in the build at the point of constructing the component.
Consider the example:
apply plugin: 'cpp'apply plugin: 'java-lang'executables { main}
This example defines aNativeExecutable
component named 'main' and will also create theFunctionalSourceSet
'sources.main'. ACppSourceSet
'cpp' will be added to 'sources.main', but noJavaSourceSet
will be added because this language is not applicable to aNativeExecutable
.
Similarly, when a jvm library is defined noc
orcpp
source sets will be created, even when thec
andcpp
language plugins are applied.
If the source sets of a component require further configuration, it is necessary to place this configurationafter the declaration of the component:
executables { main}sources { main { cpp { source { srcDirs "src/main/cpp", "src/shared/c++" include "**{@literal /}*.cpp" } } }}
Alternatively, you can create and configure anyFunctionalSourceSet
andLanguageSourceSet
instances directly via thesources
DSL at any time:
apply plugin:'cpp'sources { lib { // explicitly create a cpp source set of type CppSourceSet cpp(CppSourceSet) }}
Changes to incubating Java language plugins
To better support the production of multiple binary outputs for a single set of sources, a new set of Java language plugins was introduced in Gradle 1.x. This development continues in this release, with the removal of thejvm-lang
plugin, and the replacement of thejava-lang
plugin with a completely new implementation.
The existingjava
plugin is unchanged: only users who explicitly applied thejvm-lang
orjava-lang
plugins will be affected by this change.
Plugin reorganisation
The plugin classesorg.gradle.api.plugins.JvmLanguagePlugin
andorg.gradle.api.plugins.JavaLanguagePlugin
were merged intoorg.gradle.api.plugins.LegacyJavaComponentPlugin
to avoid confusions withorg.gradle.language.java.plugins.JavaLanguagePlugin
.
The new plugin classorg.gradle.language.java.plugins.LegacyJavaComponentPlugin
does not register a factory forJavaSourceSet
andResourceSourceSet
on eachFunctionalSourceSet
.
Domain model reorganisation
- Renamed
ProjectClassDirectoryBinary
->ClassDirectoryBinarySpec
- Renamed
ProjectJarBinary
->JarBinarySpec
Generated maven pom contains dependency exclusions
Themaven-publish
plugin will now correctly add required 'exclusion' elements to the generated POM. If you have a build or plugin that applies these exclusions itself, the generated POM file may contain duplicate 'exclusion' elements.
Internal methods removed
- The internal method
Javadoc.setJavadocExecHandleBuilder()
has been removed. You should usesetToolChain()
instead.
Changes to JUnit class loading
Previously, Gradle initialized test classes before trying to execute any individual test case. As of Gradle 2.1, classes are not initialized until the execution of the first test case (GRADLE-3114). This change was made for compatibility with the popular Android unit testing library,Robolectric.
This change impacts how classes that fail to initialize are reported. Previously a single failure would be reported with a test case name ofinitializerError
with the details of the failure. After this change, the first test case of the class that cannot be initialized will contain details of the failure, while subsequent test cases of the class will fail with aNoClassDefFoundError
.
This change will not cause tests that previously passed to start failing.
configuration.exclude now validates the input
Previously, a typo in a configuration-level dependency exclude rule remained undetected and led to problems likeGRADLE-3124. Now the build fails fast when exclude rule is configured with a wrong key.
//fails fast now, 'module' is the correct keyconfigurations.compile.exclude modue: "kafka"
We suspect that the impact will be minimal to none hence we don't deprecate this behavior.
Container creation methods now take precedence over other methods with the same signature
In response to the Gradle 2.0 regressionGRADLE-3126, a change has been made to how container element configuration methods are dispatched. This is unlikely to impact builds as the actual implementation now matches what is usually the intended behavior.
Prior to Gradle 2.1, the following build script would fail:
apply plugin: "java"task integrationTest {}sourceSets { integrationTest {}}assert sourceSets.findByName("integrationTest") != null
TheintegrationTest
source set would not be created because there is already a viableintegrationTest {}
method.
As of Gradle 2.1 the above script will not fail because it is interpreted that the intent is to create a new source set namedintegrationTest
. This applies to all named domain object containers in Gradle.
ModelRule, ModelFinalizer, ModelRules removed
These incubating classes formed the API being used to manage model configuration by plugins. They have been removed in favor of a different approach.
The replacement mechanism is currently undocumented and not yet designed for public use.
TaskParameter replaced with TaskExecutionRequest
- Incubating class
TaskParameter
has been replaced withTaskExecutionRequest
. - Incubating property
StartParameter.taskParameters
has been replaced withStartParameter.taskRequests
.
IvyModuleDescriptor renamed to IvyModuleDescriptorSpec
- Incubating class
IvyModuleDescriptor
has been renamed toIvyModuleDescriptorSpec
IvyModuleMetadata renamed to IvyModuleDescriptor
- Incubating class
IvyModuleMetadata
has been renamed toIvyModuleDescriptor
- Incubating method
IvyModuleDescriptor.getExtraInfo()
now returns anIvyExtraInfo instead of Map<String, String>