The Gradle team is excited to announce Gradle 8.1.
You'll be happy to know that the configuration cache is now stable and ready for general use. The configuration cache was introduced in Gradle 6.6 to help speed up builds by caching the result of the configuration phase and reusing it for subsequent builds. Plus, there are several other improvements that enhance its usability and compatibility that pave the way for further performance boosts.
The Kotlin DSL has undergone significant improvements to make it easier for build authors to create simpler build scripts and better plugins. As an experimental feature, Kotlin DSL also has a simple assignment for Gradle Property
types.
In JVM-based projects, it is now possible to use Java 20 for compiling, testing, and running Java projects. Additionally, CodeNarc analysis runs in parallel by default, allowing for faster code quality analysis.
This release also contains several other improvements and bug fixes.
See the What's new in Gradle 8.0 for a discussion of changes from 7.0 to 8.0.
We would like to thank the following community members for their contributions to this release of Gradle: André Sousa, Attila Király, Aurimas, Björn Kautler, Christoph Dreis, David Morris, DJtheRedstoner, Gabriel Feo, J.T. McQuigg, JavierSegoviaCordoba, JayaKrishnan Nair K, Jeff Widman, kackey0-1, Martin Bonnin, Martin Kealey, modmuss50, pan93412, Sebastian Schuberth, Simon Marquis, TheDadda, Thrillpool, valery1707, Xin Wang, Yanshun Li
Switch your build to use Gradle 8.1 by updating your wrapper:
./gradlew wrapper --gradle-version=8.1
See the Gradle 8.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading to Gradle 8.1.
For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.
The configuration cache improves build time by caching the result of the configuration phase and reusing it for subsequent builds. This feature, now promoted to stable status, can significantly improve build performance.
To mitigate the risk of accidental exposure of sensitive data, Gradle now encrypts the configuration cache. Gradle will transparently generate a machine-specific secret key as required, cache it under the Gradle user home directory and use it to encrypt the data in the project specific caches.
By default, the Gradle configuration cache is located under .gradle/configuration-cache
in your project directory.
Every cache entry contains information about the set of tasks to run, along with their configuration and dependency information.
However, based on a task's implementation or the way it is configured by a plugin or build script, its configuration might contain sensitive information. It is crucial to keep this information secure.
To enhance security further, make sure to:
.gradle/configuration-cache
folder from being committed to source control or exposed in CI environments;The configuration cache now fully supports dependency verification. Changes to associated files (keyring files or verification-metadata.xml
) are correctly detected and invalidate the configuration cache if necessary.
The configuration cache now fully supports file-system-based Ivy and Maven repositories. In particular, this release adds support for dynamic dependencies. Suppose a dynamic dependency is declared in the build script. In that case, changes to the dependency in the file-system-based repository now invalidate the configuration cache to pick up an updated version.
The Ivy publishing plugin and the Signing plugin are now compatible with the configuration cache.
The current status of the configuration cache support for all core Gradle plugins can be found in the configuration cache documentation.
Gradle can now restore user-provided lambdas from the configuration cache. Using anonymous classes to implement Single Abstract Method (SAM) interfaces is no longer necessary. This also applies to Kotlin code: there is no more need to configure the Kotlin compiler to generate classes instead of lambdas during SAM conversion.
This release also improves error reporting for lambdas that capture unsupported types, like Configuration
.
This release improves error reporting of unsupported method calls in Groovy closures. For example, a doFirst
/doLast
action uses a method or property of the Project
, which is unsupported with the configuration cache:
tasks.register('echo') {
doLast { println buildDir }
}
Previously, a confusing message of Could not get unknown property 'buildDir' for task ':echo'
was displayed, but now the error is more accurate:
* Where:
Build file 'build.gradle' line: 2
* What went wrong:
Execution failed for task ':echo'.
> Cannot reference a Gradle script object from a Groovy closure as these are not supported with the configuration cache.
The configuration cache needs to detect when the build logic accesses the "outside world" at configuration time (for example, reading files or environment variables) to invalidate the cache if accessed information changes. Every recent Gradle release added new detection capabilities, and this release is no exception. Gradle now detects:
FileCollection
s queried at configuration time.java.io.File
class used to check file existence and read directory contents.java.nio.files.File
class used to open files for reading and to check file existence.Gradle's Kotlin DSL provides an alternative syntax to the Groovy DSL with an enhanced editing experience in supported IDEs — superior content assistance, refactoring documentation, and more.
As an opt-in feature, it is now possible to use the =
operator to assign values to Property
types in Kotlin scripts as an alternative to the set()
method:
interface Extension {
val description: Property<String>
}
// register "extension" with type Extension
extension {
// Current: Using the set() method call
description.set("Hello Property")
// Experimental: lazy property assignment enabled
description = "Hello Property"
}
This reduces the verbosity of Kotlin DSL when lazy property types are used to configure tasks and extensions. It also makes Kotlin DSL behavior consistent with Groovy DSL behavior, where using =
to assign lazy properties has always been available.
Lazy property assignment for Kotlin scripts is an experimental opt-in feature. It is enabled by adding systemProp.org.gradle.unsafe.kotlin.assignment=true
to the gradle.properties
file.
There are three known issues with the IDE integration: KT-56941, KT-56221 and KTIJ-24390.
For more information and current limitations, see the Kotlin DSL Primer.
plugins {}
blockVersion catalog accessors for plugin aliases in the plugins {}
block aren't shown as errors in IntelliJ IDEA and Android Studio Kotlin script editor anymore.
plugins {
alias(libs.plugins.jmh)
}
If you were using a workaround for this before, see the corresponding section in the upgrading guide.
Gradle Kotlin DSL scripts are compiled by Gradle during the configuration phase of your build.
Deprecation warnings found by the Kotlin compiler are now reported on the console when compiling build scripts. This makes it easier to spot usages of deprecated members in your build scripts.
> Configure project :
w: build.gradle.kts:4:5: 'getter for uploadTaskName: String!' is deprecated. Deprecated in Java
Moreover, Kotlin DSL script compilation errors are now always reported in the order they appear in the file. This makes it easier to figure out the first root cause of a script compilation failure.
* Where:
Build file 'build.gradle.kts' line: 5
* What went wrong:
Script compilation errors:
Line 5: functionDoesNotExist()
^ Unresolved reference: functionDoesNotExist
Line 8: doesNotExistEither = 23
^ Unresolved reference: doesNotExistEither
2 errors
Gradle
objectThe Gradle
type now declares that it is ExtensionAware
. This allows access to extensions without casting to ExtensionAware
from Kotlin. This can be useful in initialization scripts.
// Assuming the Gradle object has an extension of type MyExtension
configure<MyExtension> {
someProperty.set("value")
}
// Assuming the Gradle object has an optional extra property named 'myOption'
val myOption: String? by extra
See the ExtensionAware type documentation for more information.
Test.forkEvery
from KotlinIt is now easier to configure the forkEvery
property of Test
tasks from Kotlin to set the maximum number of test classes to execute in a forked test process. Instead of requiring to use its setForkEvery(<number>)
setter you can now simply assign it a value:
tasks.test {
forkEvery = 8
}
See the Test.forkEvery property documentation for more information.
The kotlin-dsl
plugin provides a convenient way to develop Kotlin-based plugins that contribute build logic.
In addition to plugins written as standalone projects, Gradle also allows you to provide build logic written in Kotlin as precompiled script plugins. You write these as *.gradle.kts
files in src/main/kotlin
directory.
Customization of Kotlin options in your build logic is now easier and no longer requires afterEvaluate {}
.
plugins {
`kotlin-dsl`
}
tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_1_9)
}
}
The standalone script compilation for build scripts, init scripts, and applied scripts are configured to skip the pre-release check to allow referencing Kotlin code compiled with more recent Kotlin language versions on a best-effort basis.
kotlin-dsl
published with proper licensing informationThe kotlin-dsl
plugin is now published to the Gradle Plugin Portal with proper licensing information in its metadata. The plugin is published under the same license as the Gradle Build Tool: the Apache License Version 2.0.
This makes using the kotlin-dsl
plugin easier in an enterprise setting where published licensing information is required.
--offline
when building precompiled script pluginsBuilding precompiled script plugins now respects the --offline command line execution option.
This makes using Gradle plugins that react to --offline
from precompiled script plugins easier.
Building precompiled script plugins includes applying plugins to synthetic projects. This can produce some console output.
The output is now captured and only shown in case of failures. By default, this is now less verbose and does not clutter the console output.
Precompiled script plugins must respect the documented naming conventions. Gradle will now fail with an explicit and helpful error message when naming conventions are not followed. For example:
Precompiled script 'src/main/kotlin/settings.gradle.kts' file name is invalid, please rename it to '<plugin-id>.settings.gradle.kts'.
Moreover, .gradle.kts
files present in resources src/main/resources
are not considered as precompiled script plugins anymore. This makes it easier to ship Gradle Kotlin DSL scripts in plugins resources.
Gradle now supports using Java 20 for compiling, testing, and starting other Java programs. This can be accomplished by configuring your build or task to use a Java 20 toolchain.
You cannot currently run Gradle on Java 20 because Kotlin lacks support for JDK 20. However, you can expect support for running Gradle with Java 20 in a future version.
The Codenarc plugin performs quality checks on your project’s Groovy source files using a static code analyzer. It now uses the Gradle worker API and JVM toolchains.
CodeNarc now performs analysis via an external worker process which allows it to run in parallel within a single project.
In Groovy projects, this tool will use the same version of Java the project requires. In other types of projects, it will use the same version of Java used by the Gradle daemon.
For more details, see the user manual.
Version 1.2.0 of the com.gradle.plugin-publish
plugin is now available. It is required to benefit from the features and bugfixes listed below.
See documentation for more details.
A new option is added to publishPlugins
task. You can validate your plugins before actually publishing them using the --validate-only
flag:
$ ./gradlew publishPlugins --validate-only
With a plugin for doing sigstore signing, the portal accepts *.sigstore
bundle files as an alternate signing solution.
The bug in integration with Shadow plugin that caused JAR manifest to contain Gradle API jars has been fixed.
The --gradle-version
parameter for the wrapper task now supports using predefined labels to select a version.
The recognized labels are:
latest
selects the latest stable versionrelease-candidate
selects the latest release candidate versionnightly
selects the latest unstable nightly versionrelease-nightly
selects the latest unstable nightly version for the next releaseMore details can be found in the Gradle Wrapper section.
When generating a new project with the init
task with the --incubating
option, parallel project execution and task output caching will be enabled for the generated project by creating a gradle.properties
file and setting the appropriate flags in it.
To better manage memory usage, Gradle proactively stops unused worker processes before starting new ones.
Gradle first checks if the available physical memory can accommodate the maximum heap requirements of a new worker process. If not, it searches for unused worker processes that can be stopped to free up enough physical memory for the new process.
Previously, Gradle sought to acquire enough memory to satisfy the minimum heap requirements of the new process. However, in cases where the minimum heap and maximum heap of the worker process are very different, the memory freed up before the process starts may not be close to sufficient for the eventual size of the process.
Gradle now attempts to acquire enough memory to satisfy the new process's maximum heap requirements.
This causes the physical memory management to be more aggressive when starting up new processes, and in many cases, will result in better overall memory usage.
See the userguide for more information on configuring JVM memory options.
There is a new @ServiceReference
annotation that makes it easier to consume shared build services.
By annotating a property with @ServiceReference
, you no longer need to remember to explicitly declare that your task uses a shared build service via Task#usesService()
.
If you also provide the name of the service in the annotation, you no longer need to obtain and assign a build service reference to the property explicitly; if a service registration with the given name exists, the corresponding reference is automatically assigned to the property.
More details in the Shared Build Services documentation on using build services.
buildFinished
listenersPreviously, Gradle had only Gradle.buildFinished
listeners to handle the result of the build. For many reasons, this API doesn't work well with the configuration cache, but there were no proper replacements. With the new Dataflow Actions you can now schedule pieces of work to process the result of the build in a way that is configuration-cache compatible. For example, you can add code to play a sound when the build completes successfully:
class FFPlay implements FlowAction<FFPlay.Parameters> {
interface Parameters extends FlowParameters {
@Input
Property<File> getMediaFile();
}
@Inject
protected abstract ExecOperations getExecOperations();
@Override
public void execute(Parameters parameters) {
getExecOperations().exec(spec -> {
spec.commandLine(
"ffplay", "-nodisp", "-autoexit", "-hide_banner", "-loglevel", "quiet",
parameters.getMediaFile().get().getAbsolutePath()
);
spec.setIgnoreExitValue(true);
});
}
}
flowScope.always(FFPlay.class, spec ->
spec.getParameters().getMediaFile().fileProvider(
flowProviders.getBuildWorkResult().map(result ->
new File(
soundsDir,
result.getFailure().isPresent() ? "sad-trombone.mp3" : "tada.mp3"
)
)
)
);
Unlike callbacks, actions provide the necessary level of isolation to ensure safe configuration caching.
In this release, dataflow actions only provide a replacement for the deprecated Gradle.buildFinished
callback, but more options to add work outside the task graph are planned.
CACHEDIR.TAG
Caches in the Gradle user home can become very large and typically do not contain files that need to be searched or backed up. The CACHEDIR.TAG specification proposes a way for archive and backup tools to automatically skip these directories, which makes it unnecessary to explicitly exclude them. Gradle now marks directories that should be ignored with a CACHEDIR.TAG
file.
See the userguide for more information on this feature. See the upgrading guide for details on disabling this if needed.
The following improvements are for IDE integrators. They will be available for end-users in future IDE releases once they are used by IDE vendors.
Previously, when executing a build via the IDE, the log level settings provided in the project's gradle.properties
file were ignored. Some IDE vendors worked around this shortcoming by setting the log level in other ways to meet user expectations.
The Tooling API now honors the org.gradle.logging.loglevel
setting in the project's gradle.properties
and applies it as expected to builds started from the IDE.
Learn more about changing log levels in the user manual.
Promoted features are features that were incubating in previous versions of Gradle but are now supported and subject to backwards compatibility.
See the user manual section on the “Feature Lifecycle” for more information.
The following are the features that have been promoted in this Gradle release.
The configuration cache feature is now officially out of incubation and is ready for general use. It is important to note, however, that utilizing this feature may require modifications to build logic and applied plugins to ensure full support.
The implementation of the configuration cache is not yet complete. However, you can expect the configuration cache to evolve with new features and enhancements in upcoming Gradle versions, offering support for a broader range of use cases. To explore the features currently under consideration for implementation, please refer to the documentation.
Enabling the configuration cache can yield a significant boost in build performance, as it caches the result of the configuration phase and reuses it for subsequent builds. This means that subsequent builds no longer have to re-execute the configuration phase, resulting in faster and more efficient builds.
Configuration cache was introduced as an experimental feature back in Gradle 6.6.
To learn how to benefit from this feature, refer to the Configuration Cache documentation.
See the upgrading guide if you were already using this feature in previous releases, as all org.gradle.unsafe.configuration-cache...
properties were renamed to reflect the fact they are now fully supported.
The ValueSource
API is no longer incubating. The following classes and methods are now considered stable:
Known issues are problems that were discovered post release that are directly related to changes made in this release.
We love getting contributions from the Gradle community. For information on contributing, please see gradle.org/contribute.
If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure that you're encountering a bug, please use the forum.
We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.