Gradle Release Notes

The Gradle team is excited to announce Gradle 8.5.

Gradle now supports running on Java 21.

This release features Kotlin DSL improvements, including faster first use and version catalog support in precompiled Kotlin script plugins.

Additionally, this release comes with more helpful error and warning messages, improvements to build init, dependency verification and several new APIs for build and plugin authors. See the full release notes for details.

We would like to thank the following community members for their contributions to this release of Gradle: Ahmed Ehab, Alex Landau, Aurimas, Björn Kautler, bodhili, Daniel Le Berre, davidburstrom, Franz Wimmer, Jongwoo Han, Ken, Leonardo Silveira, Martin Bonnin, Matthew Von-Maszewski, Nik Clayton, noeppi_noeppi, Philip Wedemann, Philipp Schneider, Tomas Bjerre

Be sure to check out the Public Roadmap for insight into what's planned for future releases.

Table Of Contents

Upgrade instructions

Switch your build to use Gradle 8.5 by updating your wrapper:

./gradlew wrapper --gradle-version=8.5

See the Gradle 8.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading to Gradle 8.5.

For Java, Groovy, Kotlin, and Android compatibility, see the full compatibility notes.

New features and usability improvements

Full Java 21 support

Gradle 8.4 supported compiling and testing with Java 21 using Java toolchains, but running Gradle itself on Java 21 was not yet supported.

With this release, Gradle now fully supports compiling, testing and running on Java 21.

See the full compatibility documentation for details.

Kotlin DSL improvements

Gradle's Kotlin DSL provides an enhanced editing experience in supported IDEs compared to the traditional Groovy DSL — auto-completion, smart content assist, quick access to documentation, navigation to source, and context-aware refactoring.

Faster first use

When using a Gradle version for the first time, Gradle will start compiling your build logic faster than before.

Previously, there was about four seconds of overhead on powerful machines (and much longer on slower machines) to run a build with Kotlin DSL scripts for the first time. Typically, this happened on every build for ephemeral CI agents, as they have an empty Gradle user home directory. The fact that ephemeral CI agents often have a cold Gradle daemon made this even slower. This is because up to this release Gradle generated a Gradle API Kotlin DSL Extensions JAR before compiling the first .gradle.kts script.

The Kotlin extensions for the Gradle API now ship as part of the Gradle distribution. Consequently, the first use of a Gradle version for compiling .gradle.kts scripts is much faster. This is especially noticeable on ephemeral CI agents or Gradle plugin cross-version tests.

First use of a single project build, running the help task

Version catalog API in precompiled scripts

The versionCatalogs extension accessor is now available in Kotlin DSL precompiled scripts.

It provides an API for accessing version catalogs available on the projects where the precompiled script will be applied. The following example conditionally declares a dependency on a module defined in a version catalog:

// buildSrc/src/main/kotlin/my-convention-plugin.gradle.kts
versionCatalogs                   // This is the extension now available
    .named("libs")                // Assumes there is a libs catalog, throws exception otherwise
    .findLibrary("assertj-core")  // Search the catalog for an assertj-core entry
    .ifPresent { assertjCore ->   // If there is one ... 
        dependencies {            // ... Add a dependency to it 
            testImplementation(assertjCore) 
        }
    }

Check the version catalog API for all supported methods.

Ability to enable Kotlin metadata version check for script compilation

Kotlin/JVM metadata is backward-compatible with all Kotlin releases and forward-compatible with one Kotlin release. For example, Kotlin 1.9 supports Kotlin metadata from Kotlin 1.0 up to Kotlin 2.0, but not from Kotlin 2.1.

The Kotlin compiler checks that the metadata of all dependencies is compatible. Skipping that check is the current default for Gradle script compilation. This may lead to hard-to-troubleshoot errors when libraries built with Kotlin versions unsupported by the Kotlin embedded in Gradle are used in build logic.

Skipping the check will be deprecated soon. Starting with Gradle 9.0, the Kotlin metadata version check will be enabled by default.

To opt-in early to the future-proof behavior, set the org.gradle.kotlin.dsl.skipMetadataVersionCheck property to false. This will enable the metadata check.

To enable the check persistently, set the property in the gradle.properties file of your build root directory:

org.gradle.kotlin.dsl.skipMetadataVersionCheck=false

Error and warning reporting improvements

Gradle provides a rich set of error and warning messages to help you understand and resolve problems in your build.

Improved deprecation messages when creating configurations with reserved names

Gradle now provides more helpful messages when you attempt to create a configuration with a "reserved" name prior to Gradle creating it.

Example of deprecation warning:

> Configure project :
The configuration customCompileOnly was created explicitly. This configuration name is reserved for creation by Gradle. This behavior has been deprecated. This behavior is scheduled to be removed in Gradle 9.0. Do not create a configuration with the name customCompileOnly. Consult the upgrading guide for further information: https://docs.gradle.org/8.5/userguide/upgrading_version_8.html#configurations_allowed_usage
When creating configurations during sourceSet custom setup, Gradle found that configuration customCompileOnly already exists with permitted usage(s):
    Consumable - this configuration can be selected by another project as a dependency
    Resolvable - this configuration can be resolved by this project to a set of files
    Declarable - this configuration can have dependencies added to it
Yet Gradle expected to create it with the usage(s):
    Declarable - this configuration can have dependencies added to it
Gradle will mutate the usage of configuration customCompileOnly to match the expected usage. This may cause unexpected behavior. Creating configurations with reserved names has been deprecated. This will fail with an error in Gradle 9.0. Create source set custom prior to creating or accessing the configurations associated with it. For more information, please refer to https://docs.gradle.org/8.5/userguide/building_java_projects.html#sec:implicit_sourceset_configurations in the Gradle documentation.

See authoring maintainable builds to remove these warnings.

Improved handling of wrapped assertion errors when running tests

The way Gradle handles wrapped assertion failures in tests has been significantly improved.

Previously, if a test framework or library wrapped an assertion exception in a more generic exception, the information about the underlying error could not be displayed in the IDE.

As an example, the following code, instead of reporting the underlying assertion error of getting “Actual text” instead of “Expected text”, just returned a blank assertion failed message to listeners.

class TestCase { 
    @Test 
    public void wrappedAssertion() {
        try {
            Assertions.assertEquals("Expected text", "Actual text", "Assertion message");
        } catch (AssertionFailedError ex) {
            // Wrap the actual cause in another AssertionError
            throw new AssertionError("Additional message", ex);
            // Or alternatively in any exception, like RuntimeException
            // throw new RuntimeException(“Additional message”, ex);
        }
    }
}

From now on, thrown exceptions’ causes will be analyzed deeper, and the true underlying assertion errors will be extracted. In the case above, test event listeners will be notified about the fact that a failed comparison was the underlying issue.

These changes will be effective as soon as Gradle 8.5 is used and should not require upgrade of the IDE.

For example, when using Gradle 8.4, the built-in comparison tools won’t be visible in IntelliJ IDEA for the example above.

Error without expected / actual display

As soon as Gradle 8.5 is used, the inner cause will be reported to IntelliJ IDEA, and the familiar comparison tools will immediately appear.

Error with expected / actual display

Better diagnostics when unable to delete files

When Gradle fails to delete files, it will now provide extended diagnostics. This helps troubleshoot issues with locked files, concurrent writes, etc.

The list of files that failed to be deleted is reported. If new files appear under a directory during deletion, their paths will be reported separately. The root cause exceptions for each file deletion failure will also be attached to the stack trace.

Build init improvements

The build init plugin allows users to create a new Gradle build, supporting various types of projects.

Build init utilizing version catalogs

Version catalogs are the recommended way to centrally define dependency modules, plugins, and their versions. Starting from this release, the build init plugin generates projects utilizing version catalogs in the conventional location gradle/libs.versions.toml. This encourages version catalog usage since it became a stable feature in Gradle 8.0.

Refer to the user manual and the TOML file format for information on version catalogs.

New --java-version parameter

By default, the init command enters interactive mode and prompts the user when required information for the selected project type is missing.

To support generating Java projects non-interactively, the --java-version parameter was added to the init task. This parameter allows you to specify the major version of Java to use in the generated project when launching the init task in a non-interactive mode.

  --type java-application \
  --dsl kotlin \
  --test-framework junit-jupiter \
  --package sample.structure \
  --project-name my-gradle-project  \
  --no-split-project  \
  --java-version 17

Wrapper improvements

The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short, “Wrapper”). The Wrapper invokes a declared version of Gradle, downloading it beforehand if necessary.

Smaller Wrapper JAR

The Wrapper JAR file size was reduced from ~65K to ~45K by eliminating unused code.

Wrapper JAR LICENSE file

The Wrapper JAR now contains a META-INF/LICENSE file.

This was done to alleviate any doubts regarding the licensing of the Wrapper JAR file. The Wrapper and the Gradle Build Tool are licensed under the Apache Software License 2.0. The JAR file is now self-attributing, so you don't need to add a separate LICENSE file in your codebase.

Build authoring improvements

Gradle provides rich APIs for plugin authors and build engineers to develop custom build logic.

Improvements to Javadoc of generated version catalog accessors

The Javadoc for generated accessors for plugins and libraries from a version catalog now includes information about the version of the plugin or library. This version information can be either a value, a version reference, or the indication that no version was provided.