The Gradle team is pleased to announce Gradle 4.6.
First and foremost, this release of Gradle includes built-in support for JUnit Platform and the JUnit Jupiter/Vintage Engine, also known as JUnit 5 support. You can use the new filtering and engines functionality in JUnit 5 using the examples provided below and in the documentation.
Thank you to the JUnit team for helping to achieve JUnit Platform support, and a special thank you to Andrew Oberstar for extraordinary contributions toward this effort.
Also regarding testing, you can now improve your testing feedback loop when running JVM-based tests using the new fail-fast option for Test
tasks, which stops the build immediately after the first test failure.
// Example JUnit 5 and fail-fast test configuration
test {
useJUnitPlatform {
excludeTags 'slow'
includeEngines 'junit-jupiter', 'junit-vintage'
}
failFast = true
}
Moving on to dependency management improvements: you can now declare dependency constraints for transitive dependencies and avoid problems caused by oft-hidden upstream dependency changes.
This release also features enhanced Maven dependency compatibility: support for importing BOMs, optional dependencies, and compile/runtime separation when consuming POMs. For now you must enable these features by adding enableFeaturePreview('IMPROVED_POM_SUPPORT')
to your settings.gradle file, as they break backward compatibility in some cases.
This version of Gradle also comes with a couple especially useful new APIs for task development. You can now declare custom command-line flags for your custom tasks, for example: gradle myCustomTask --myfoo=bar
. In addition, tasks that extend Test
, JavaExec
or Exec
can declare rich arguments for invoking the underlying executable. This allows for better modeling of tools like annotation processors.
Speaking of annotation processors, it is now more convenient to declare dependencies that are annotation processors through the new annotationProcessor
dependency configuration. Using a separate dependency configuration for annotation processors is a best practice for improving performance.
Kotlin DSL v0.15.6 is included in this release of Gradle, and features initialization scripts support, nicer script compilation error reporting, performance improvements, and better IntelliJ IDEA integration. Details are available in the linked release notes.
We hope you will build happiness with Gradle 4.6, and we look forward to your feedback via Twitter or on GitHub.
play
pluginStartParameter.taskOutputCacheEnabled
Switch your build to use Gradle 4.6 quickly by updating your wrapper properties:
gradle wrapper --gradle-version=4.6
Standalone downloads are available at gradle.org/releases.
Here are the new features introduced in this Gradle release.
JUnit 5 is the latest version of the well-known JUnit
test framework. JUnit 5 is composed of several modules:
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
The JUnit Platform
serves as a foundation for launching testing frameworks on the JVM. JUnit Jupiter
is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. JUnit Vintage
provides a TestEngine
for running JUnit 3 and JUnit 4 based tests on the platform.
Gradle now provides native support for JUnit Jupiter/Vintage Engine
on top of JUnit Platform
. To enable JUnit Platform
support, you just need to add one line to your build.gradle
:
test {
useJUnitPlatform()
}
Moreover, Tagging and Filtering can be enabled via:
test {
useJUnitPlatform {
// includeTags 'fast'
excludeTags 'slow'
// includeEngines 'junit-jupiter', 'junit-vintage'
// excludeEngines 'custom-engine'
}
}
You can find more information on test grouping and filtering in the Java Plugin documentation.
To enable JUnit Jupiter
support, add the following dependencies:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.0'
}
Put your first Jupiter
test into src/test/java/foo/bar
:
package foo.bar;
import org.junit.jupiter.api.Test;
public class JUnitJupiterTest {
@Test
public void ok() {
}
}
Now you can run gradle test
to see the results of your JUnit 5 tests!
You can find a sample of test with JUnit Jupiter
at samples/testing/junitplatform/jupiter
in the '-all' distribution of Gradle.
If you want to run JUnit 3/4 tests on JUnit Platform
, you should add extra JUnit Vintage Engine
dependency:
test {
useJUnitPlatform()
}
dependencies {
testCompileOnly 'junit:junit:4.12'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.1.0'
}
You can mix JUnit 3/4 tests with Jupiter
tests without the need to rewrite old tests. A sample of mixed tests can be found at samples/testing/junitplatform/engine
in the '-all' distribution of Gradle.
Note: Use of JUnit 5 features requires Java 8 or higher.
Gradle now supports stopping Test
tasks after the first failed test. Projects with large test suites can take a long time to execute even though a failure occurred early on leading to unnecessary wait times (especially on CI). To enable this fail fast behavior in your build file, set the failFast
property to true
:
test {
failFast = true
}
In addition, this behavior can be enabled from the command line for individual build invocations. An invocation looks like:
gradle integTest --fail-fast
More information is available in the Java Plugin documentation for test execution.
In complex builds, it can become hard to interpret dependency resolution results and why a dependency declaration or a rule was added to a build script. To improve on this situation, we extended all the corresponding APIs with the capability to define a reason for each declaration or rule.
These reasons are shown in dependency insight reports and error messages if the corresponding declaration or rule influenced the resolution result. In the future, they will also be shown in build scans.
dependencies {
implementation('org.ow2.asm:asm:6.0') {
because 'we require a JDK 9 compatible bytecode generator'
}
}
With dependency constraints, Gradle adds a mechanism to express constraints over transitive dependencies which are used during dependency resolution.
dependencies {
implementation 'org.apache.httpcomponents:httpclient'
}
dependencies {
constraints {
implementation('org.apache.httpcomponents:httpclient:4.5.3') {
because 'previous versions have a bug impacting this application'
}
implementation('commons-codec:commons-codec:1.11') {
because 'version 1.9 pulled from httpclient has bugs affecting this application'
}
}
}
In the example, the version of commons-codec
that is brought in transitively is 1.9
. With the constraint, we express that we need at least 1.11
and Gradle will now pick that version during dependency resolution.
Compared to dependency management rules you can define in the resolution strategy, which are applied after dependency resolution to fix up the result, dependency constraints are declared information that participate in the dependency resolution process. This means that all constraints are considered in combination. For instance, if another dependency brings in an even higher version of commons-codec
, Gradle will respect that.
Expressing the same in a traditional dependency substitution rule requires you to repeat part of the dependency resolution process manually – which is expensive and error prone. That is, you would have to inspect the version that was selected and implement a decision based on the version:
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'commons-codec'
&& details.requested.name == 'commons-codec'
&& VersionNumber.parse(details.requested.version) < VersionNumber.parse('1.11')) {
details.useVersion '1.11'
}
}
Note: Dependency constraints are not yet published, but that will be added in a future release. This means that their use currently only targets builds that do not publish artifacts to maven or ivy repositories.
Gradle now provides support for importing bill of materials (BOM) files, which are effectively .pom
files that use <dependencyManagement>
to control the dependency versions of direct and transitive dependencies. It works by declaring a dependency on a BOM.
dependencies {
// import a BOM
implementation 'org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE'
// define dependencies without versions
implementation 'com.google.code.gson:gson'
implementation 'dom4j:dom4j'
}
Here, for example, the versions of gson
and dom4j
are provided by the Spring Boot BOM.
Note: This is a Gradle 5.0 feature preview, which means it is a potentially breaking change that will be activated by default in Gradle 5.0. It can be turned on in Gradle 4.6+ by adding enableFeaturePreview('IMPROVED_POM_SUPPORT')
in settings.gradle.
Gradle now creates a dependency constraint for each dependency declaration in a POM file with <optional>true</optional>
. This constraint will produce the expected result for an optional dependency: if the dependency module is brought in by another, non-optional dependency declaration, then the constraint will apply when choosing the version for that dependency (e.g., if the optional dependency defines a higher version, that one is chosen).
Note: This is a Gradle 5.0 feature preview, which means it is a potentially breaking change that will be activated by default in Gradle 5.0. It can be turned on in Gradle 4.6+ by adding enableFeaturePreview('IMPROVED_POM_SUPPORT')
in settings.gradle.
Since Gradle 1.0, runtime
scoped dependencies have been included in the Java compile classpath, which has some drawbacks:
runtime
files that do not impact compilation, resulting in unnecessary re-compilation when these files change.Now, if this new behavior is turned on, the Java and Java Library plugins both honor the separation of compile and runtime scopes. Meaning that the compile classpath only includes compile
scoped dependencies, while the runtime classpath adds the runtime
scoped dependencies as well. This is in particular useful if you develop and publish Java libraries with Gradle where the api/implementation dependencies separation is reflected in the published scopes.
Note: This is a Gradle 5.0 feature preview, which means it is a potentially breaking change that will be activated by default in Gradle 5.0. It can be turned on in Gradle 4.6+ by adding enableFeaturePreview('IMPROVED_POM_SUPPORT')
in settings.gradle.
Gradle now allows you to explicitly state for which metadata files it should search in a repository. Use the following to configure Gradle to fail-fast resolving a dependency if a POM file is not found first.
repositories {
mavenCentral {
metadataSources {
mavenPom() // Look for Maven '.pom' files
// artifact() - Do not look for artifacts without metadata file
}
}
}
This avoids a 2nd request for the JAR file when the POM is missing, making dependency resolution from Maven repositories faster in this case.
It is now even easier to add annotation processors to your Java projects. Simply add them to the annotationProcessor
configuration:
dependencies {
annotationProcessor 'com.google.dagger:dagger-compiler:2.8'
implementation 'com.google.dagger:dagger:2.8'
}
Declaring annotation processors on a separate configuration improves performance by preserving incremental compilation for tasks that don't require annotation processors.
Sometimes a user wants to declare the value of an exposed task property on the command line instead of the build script. Being able to pass in property values on the command line is particularly helpful if they change more frequently. With this version of Gradle, the task API now supports a mechanism for marking a property to automatically generate a corresponding command line parameter with a specific name at runtime. All you need to do is to annotate a setter method of a property with Option.
The following examples exposes a command line parameter --url
for the custom task type UrlVerify
. Let's assume you wanted to pass a URL to a task of this type named verifyUrl
. The invocation looks as such: gradle verifyUrl --url=https://gradle.org/
. You can find more information about this feature in the documentation on declaring command-line options.
import org.gradle.api.tasks.options.Option;
public class UrlVerify extends DefaultTask {
private String url;
@Option(option = "url", description = "Configures the URL to be verified.")
public void setUrl(String url) {
this.url = url;
}
@Input
public String getUrl() {
return url;
}
@TaskAction
public void verify() {
getLogger().quiet("Verifying URL '{}'", url);
// verify URL by making a HTTP call
}
}
Gradle 4.5 added the possibility to add CommandLineArgumentProvider
s to CompileOptions
, thus enabling plugin authors to better model tools like annotation processors.
Now we introduce CommandLineArgumentProvider
s to Exec
, JavaExec
and Test
, both to model command line arguments (Exec
and JavaExec
) as well as JVM options (JavaExec
and Test
).
For example, the built-in jacoco
plugin uses this new feature to declare the inputs and outputs of the JaCoCo agent added to the test task.
class JacocoAgent implements CommandLineArgumentProvider {
private final JacocoTaskExtension jacoco;
public JacocoAgent(JacocoTaskExtension jacoco) {
this.jacoco = jacoco;
}
@Nested
@Optional
public JacocoTaskExtension getJacoco() {
return jacoco.isEnabled() ? jacoco : null;
}
@Override
public Iterable<String> asArguments() {
return jacoco.isEnabled() ? ImmutableList.of(jacoco.getAsJvmArg()) : Collections.<String>emptyList();
}
}
task.getJvmArgumentProviders().add(new JacocoAgent(extension));
For this to work, JacocoTaskExtension needs to have the correct input and output annotations.
See the documentation about tasks with nested inputs for information how to leverage this feature in custom plugins.
This version of Gradle introduces a property org.gradle.caching.debug
which causes individual input property hashes to be logged on the console. For example, when running gradle compileJava -Dorg.gradle.caching.debug=true --build-cache
the output would be:
> Task :compileJava
Appending taskClass to build cache key: org.gradle.api.tasks.compile.JavaCompile_Decorated
Appending classLoaderHash to build cache key: 0e1119759d236086191ff6fbd26c610f
Appending actionType to build cache key: _BuildScript_$_run_closure1_769114ba780efdb8aed68d70a323d160
Appending actionClassLoaderHash to build cache key: c383666cbb0f1bf25d832b944f228c44
Appending actionType to build cache key: org.gradle.api.tasks.compile.JavaCompile_Decorated
Appending actionClassLoaderHash to build cache key: 0e1119759d236086191ff6fbd26c610f
Appending inputPropertyHash for 'options.class' to build cache key: 74824162f3f111308fa9dc95c82b65a6
Appending inputPropertyHash for 'options.compilerArgs' to build cache key: 8222d82255460164427051d7537fa305
...
Appending inputPropertyHash for 'source' to build cache key: 55786645cf0e6dcf6a3d48b1b43bf687
Appending outputPropertyName to build cache key: destinationDir
Build cache key for task ':compileJava' is 2221655c6648a7e9baf61a6234de8658
In earlier versions of Gradle, this output was logged on the INFO
log level. This does not happen anymore, and the --info
logs should be much less verbose now while the build cache is enabled.
play
pluginThe task PlatformScalaCompile
is now cacheable. This means that Play projects written in Scala now also benefit from the build cache!
Previous versions of Gradle would only generate Visual Studio solution files for a given component and its dependencies. This made it difficult to work on multiple components in a build at one time as a developer would potentially need to open multiple Visual Studio solutions to see all components. When the visual-studio
plugin is applied, Gradle now has a visualStudio
task on the root project that generates a solution for all components in the multi-project build. This means there is only one Visual Studio solution that needs to be opened to be able to work on any or all components in the build.
The gradle-native
has been working on adding new features for building with native languages (like C++). As mentioned above, Gradle now generates a single Visual Studio solution for a multi-project build. Other unannounced features have continued to be developed, which we hope to detail in a future blog post.
Highlights to the gradle-native
plugins will continue to be mentioned in Gradle's release notes, but more information will be provided in the gradle-native release notes.
Documentation in this release of Gradle has significantly improved in the following areas:
Please reach out to @gradle on Twitter or through GitHub to provide feedback to help ensure improvements are useful for you.
Gradle allows dependency cache expiry (i.e cacheChangingModulesFor
) to be set on a per-configuration basis. However, due to a bug in previous versions of Gradle, if a dependency was first resolved via a configuration using the default (24hr) expiry settings, any other resolve in the same build invocation would get the same result.
Normally this wouldn't be a big deal, since most users set the same expiry everywhere using configurations.all
. The catch is that plugins like io.spring.dependency-management
use detached configurations, which are excluded from configurations.all
. If a build was using one of these plugins, the detached configuration could be resolved first, causing later resolves to obtain the same (possibly stale) result.
This nasty cache-expiry bug has now been fixed. Users can trust that Gradle will return the most up-to-date SNAPSHOT
or version available as long as the dependency cache expiry is set correctly.
The JaCoCo plugin has been upgraded to use JaCoCo version 0.8.0 by default.
Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility. See the User guide section on the “Feature Lifecycle” for more information.
The following are the features that have been promoted in this Gradle release.
The build cache and task output caching were first introduced in Gradle 3.5. They are used in production by different teams, including the Gradle team itself, with great results. As of Gradle 4.6, the build cache and task output caching are no longer incubating and considered public features.
Note that the SPI to implement your own build cache service stays incubating.
TestKit was first introduced in Gradle 2.6 to support developers with writing and executing functional tests for plugins. In the course of the Gradle 2.x releases, a lot of new functionality was added. This version of Gradle removes the incubating status and makes TestKit a stable feature.
CompileOptions.annotationProcessorPath
propertyThe CompileOptions.annotationProcessorPath
property has been promoted and is now stable.
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 5.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.
-processorpath
compiler argumentPutting processors on the compile classpath or using an explicit -processorpath
compiler argument has been deprecated and will be removed in Gradle 5.0. Annotation processors should be added to the annotationProcessor
configuration instead. If you don't want any processing, but your compile classpath contains a processor unintentionally (e.g. as part of some library you use), use the -proc:none
compiler argument to ignore it.
The use of Play 2.2 with the the Play plugin has been deprecated and will be removed with Gradle 5.0. It is highly recommended to upgrade to a newer version of Play.
CompilerArgumentProvider
replaced by CommandLineArgumentProvider
The interface CompilerArgumentProvider
has been deprecated. Use CommandLineArgumentProvider
instead.
Previously, Gradle would clean up the local build cache directory only if the size of its contents reached 5 GB, or whatever was configured in targetSizeInMB
. From now on Gradle will instead clean up everything older than 7 days, regardless of the size of the cache directory. As a consequence targetSizeInMB
is now deprecated, and changing its value has no effect.
The minimum age for entries to be cleaned up can now be configured in settings.gradle
via the removeUnusedEntriesAfterDays
property:
buildCache {
local {
removeUnusedEntriesAfterDays = 30
}
}
The java-base
plugin will now add an <sourceSetName>AnnotationProcessor
configuration for each source set. This might break when the user already defined such a configuration. We recommend removing your own and using the configuration provided by java-base
.
VisualStudioExtension
no longer has a solutions
property. There is now only a single solution for a multi-project build that can be accessed through the VisualStudioRootExtension
on the root project. For instance:
model {
visualStudio {
solution {
solutionFile.location = "vs/${name}.sln"
}
}
}
There are no longer tasks to generate Visual Studio solution files for each component in the build. There is now only a single task (visualStudio
) in the root project that generates a solution containing all components in the build.
StartParameter.taskOutputCacheEnabled
The deprecated property StartParameter.taskOutputCacheEnabled
has been removed. Use StartParameter.buildCacheEnabled
instead.
Gradle has been upgraded to embed HttpClient version 4.5.5 over 4.4.1.
Gradle now bundles the Kotlin Standard Library Java 8 artifact kotlin-stdlib-jdk8
instead of kotlin-stdlib-jre8
as a follow up to the upgrade to Kotlin 1.2. This change might affect your build, please see the Kotlin documentation about this change.
We would like to thank the following community members for making contributions to this release of Gradle.
PlatformScalaCompile
cacheable (gradle/gradle#3804)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.