// Copyright 2022 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[upgrading_version_8]]
= Upgrading your build from Gradle 8.x to the latest

This chapter provides the information you need to migrate your Gradle 8.x builds to the latest Gradle release.
For migrating from Gradle 4.x, 5.x, 6.x, or 7.x, see the <<upgrading_version_7.adoc#upgrading_version_7, older migration guide>> first.

We recommend the following steps for all users:

. Try running `gradle help --scan` and view the https://gradle.com/enterprise/releases/2018.4/#identify-usages-of-deprecated-gradle-functionality[deprecations view] of the generated build scan.
+
image::deprecations.png[Deprecations View of a Gradle Build Scan]
+
This is so you can see any deprecation warnings that apply to your build.
+
Alternatively, you could run `gradle help --warning-mode=all` to see the deprecations in the console, though it may not report as much detailed information.
. Update your plugins.
+
Some plugins will break with this new version of Gradle, for example because they use internal APIs that have been removed or changed.
The previous step will help you identify potential problems by issuing deprecation warnings when a plugin does try to use a deprecated part of the API.
+
. Run `gradle wrapper --gradle-version {gradleVersion}` to update the project to {gradleVersion}.
. Try to run the project and debug any errors using the <<troubleshooting.adoc#troubleshooting, Troubleshooting Guide>>.

[[changes_8.1]]
== Upgrading from 8.0 and earlier

[[cache_marking]]
=== CACHEDIR.TAG files are created in global cache directories
Gradle now emits a `CACHEDIR.TAG` file in some global cache directories, as specified in <<directory_layout#dir:gradle_user_home:cache_marking>>.

This may cause these directories to no longer be searched or backed up by some tools. To disable it, use the following code in an <<init_scripts#sec:using_an_init_script,init script>> in the Gradle user home directory:

====
[.multi-language-sample]
=====
.init.gradle.kts
[source,kotlin]
----
beforeSettings {
    caches {
        // Disable cache marking for all caches
        markingStrategy.set(MarkingStrategy.NONE)
    }
}
----
=====
[.multi-language-sample]
=====
.init.gradle
[source,groovy]
----
beforeSettings { settings ->
    settings.caches {
        // Disable cache marking for all caches
        markingStrategy = MarkingStrategy.NONE
    }
}
----
=====
====

[[configuration_caching_options_renamed]]
=== Configuration cache options renamed

In this release, the configuration cache feature was promoted from incubating to stable, and as such, all properties
originally mentioned in the feature documentation (which had an `unsafe` part in their names, e.g. `org.gradle.unsafe.configuration-cache`)
were renamed, in some cases, by just removing the `unsafe` bit.

[cols="1,1", options="header"]
|===

| Incubating property
| Finalized property

|`org.gradle.unsafe.configuration-cache`
|`org.gradle.configuration-cache`

|`org.gradle.unsafe.configuration-cache-problems`
|`org.gradle.configuration-cache.problems`*

|`org.gradle.unsafe.configuration-cache.max-problems`
|`org.gradle.configuration-cache.max-problems`
|===

Note that the original `org.gradle.unsafe.configuration-cache...` properties continue to be honored in this release,
and no warnings will be produced if they are used, but they will be deprecated and removed in a future release.

=== Potential breaking changes

==== Kotlin DSL scripts emit compilation warnings

Compilation warnings from Kotlin DSL scripts are printed to the console output.
For example, the use of deprecated APIs in Kotlin DSL will emit warnings each time the script is compiled.

This is a potentially breaking change if you are consuming the console output of Gradle builds.

==== Configuring Kotlin compiler options with the `kotlin-dsl` plugin applied

If you are configuring custom Kotlin compiler options on a project with the <<kotlin_dsl.adoc#sec:kotlin-dsl_plugin, kotlin-dsl>> plugin applied you might encounter a breaking change.

In previous Gradle versions, the `kotlin-dsl` plugin was adding required compiler arguments on link:{javadocPath}/org/gradle/api/Project.html#afterEvaluate-org.gradle.api.Action-[afterEvaluate {}].
Now that the Kotlin Gradle Plugin provides <<lazy_configuration.adoc#lazy_configuration, lazy configuration>> properties, our `kotlin-dsl` plugin switched to adding required compiler arguments to the lazy properties directly.
As a consequence, if you were setting `freeCompilerArgs` the `kotlin-dsl` plugin is now failing the build because its required compiler arguments are overridden by your configuration.

====
[.multi-language-sample]
=====
.build.gradle.kts
[source,kotlin]
----
plugins {
    `kotlin-dsl`
}

tasks.withType(KotlinCompile::class).configureEach {
    kotlinOptions { // Deprecated non-lazy configuration options
        freeCompilerArgs = listOf("-Xcontext-receivers")
    }
}
----
=====
====

With the configuration above you would get the following build failure:

[source,text]
----
* What went wrong
Execution failed for task ':compileKotlin'.
> Kotlin compiler arguments of task ':compileKotlin' do not work for the `kotlin-dsl` plugin. The 'freeCompilerArgs' property has been reassigned. It must instead be appended to. Please use 'freeCompilerArgs.addAll(\"your\", \"args\")' to fix this.
----

You must change this to adding your custom compiler arguments to the lazy configuration properties of the Kotlin Gradle Plugin in order for them to be appended to the ones required by the `kotlin-dsl` plugin:

====
[.multi-language-sample]
=====
.build.gradle.kts
[source,kotlin]
----
plugins {
    `kotlin-dsl`
}

tasks.withType(KotlinCompile::class).configureEach {
    compilerOptions { // New lazy configuration options
        freeCompilerArgs.addAll("-Xcontext-receivers")
    }
}
----
=====
====

If you were already adding to `freeCompilerArgs` instead of setting its value, then you should not experience a build failure.

==== New API introduced may clash with existing Gradle DSL code

When a new property or method is added to an existing type in the Gradle DSL, it may clash with names already in use in user code.

When a name clash occurs, one solution is to rename the element in user code.

This is a non-exhaustive list of API additions in 8.1 that may cause name collisions with existing user code.

* link:{javadocPath}/org/gradle/api/tasks/JavaExec.html#getJvmArguments--[`JavaExec.getJvmArguments()`]
* link:{javadocPath}/org/gradle/process/JavaExecSpec.html#getJvmArguments--[`JavaExecSpec.getJvmArguments()`]

==== Using unsupported API to start external processes at configuration time is no longer allowed with the configuration cache enabled

Since Gradle 7.5, using `Project.exec`, `Project.javaexec`, and standard Java and Groovy APIs to run external processes at configuration time has been considered an error only if the <<configuration_cache.adoc#config_cache:stable,feature preview `STABLE_CONFIGURATION_CACHE`>> was enabled.
With the configuration cache promotion to a stable feature in Gradle 8.1, this error is detected regardless of the feature preview status.
The <<configuration_cache#config_cache:requirements:external_processes,configuration cache chapter>> has more details to help with the migration to the new provider-based APIs to execute external processes at configuration time.

Builds that do not use the configuration cache, or only start external processes at execution time are not affected by this change.

=== Deprecations

[[configurations_allowed_usage]]
==== Mutating core plugin configuration usage

The allowed usage of a configuration should be immutable after creation.
Mutating the allowed usage on a configuration created by a Gradle core plugin is deprecated.
This includes calling any of the following `Configuration` methods:

- `setCanBeConsumed(boolean)`
- `setCanBeResolved(boolean)`

These methods now emit deprecation warnings on these configurations, except for certain special cases which make allowances for the existing behavior of popular plugins.
This rule does not yet apply to detached configurations or configurations created
in buildscripts and third-party plugins.
Calling `setCanBeConsumed(false)` on `apiElements` or `runtimeElements`
is not yet deprecated in order to avoid warnings that would be otherwise emitted when
using select popular third-party plugins.

This change is part of a larger ongoing effort to make the intended behavior of configurations more consistent and predictable, and to unlock further speed and memory improvements in this area of Gradle.

The ability to change the allowed usage of a configuration after creation will be removed in Gradle 9.0.

[[java_extension_without_java_component]]
==== Calling select methods on the `JavaPluginExtension` without the `java` component present

Starting in Gradle 8.1, calling any of the following methods on `JavaPluginExtension` without
the presence of the default `java` component is deprecated:

- `withJavadocJar()`
- `withSourcesJar()`
- `consistentResolution(Action)`

This `java` component is added by the `JavaPlugin`, which is applied by any of the Gradle JVM plugins including:

- `java-library`
- `application`
- `groovy`
- `scala`

Starting in Gradle 9.0, calling any of the above listed methods without the presence of the default `java` component
will become an error.

[[war_plugin_configure_configurations]]
==== `WarPlugin#configureConfiguration(ConfigurationContainer)`

Starting in Gradle 8.1, calling `WarPlugin#configureConfiguration(ConfigurationContainer)` is deprecated. This method was
intended for internal use and was never intended to be used as part of the public interface.

Starting in Gradle 9.0, this method will be removed without replacement.

[[test_task_default_classpath]]
==== Relying on conventions for custom Test tasks

By default, when applying the link:java_plugin.html[`java`] plugin, the `testClassesDirs`
and `classpath` of all `Test` tasks have the same convention. Unless otherwise changed,
the default behavior is to execute the tests from the default `test` link:jvm_test_suite_plugin.html[`TestSuite`]
by configuring the task with the `classpath` and `testClassesDirs` from the `test` suite.
This behavior will be removed in Gradle 9.0.

While this existing default behavior is correct for the use case of executing the default unit
test suite under a different environment, it does not support the use case of executing
an entirely separate set of tests.

If you wish to continue including these tests, use the following code to avoid the deprecation warning in 8.1
and prepare for the behavior change in 9.0. Alternatively, consider migrating to test suites.

====
[.multi-language-sample]
=====
.build.gradle.kts
[source,kotlin]
----
val test by testing.suites.existing(JvmTestSuite::class)
tasks.named<Test>("myTestTask") {
    testClassesDirs = files(test.map { it.sources.output.classesDirs })
    classpath = files(test.map { it.sources.runtimeClasspath })
}
----
=====
[.multi-language-sample]
=====
.build.gradle
[source,groovy]
----
tasks.myTestTask {
    testClassesDirs = testing.suites.test.sources.output.classesDirs
    classpath = testing.suites.test.sources.runtimeClasspath
}
----
=====
====


[[gmm_modification_after_publication_populated]]
==== Modifying Gradle Module Metadata after a publication has been populated

Altering the link:publishing_gradle_module_metadata.html[GMM] (e.g., changing a component configuration variants) *after* a Maven or Ivy publication has been populated from their components is now deprecated.
This feature will be removed in Gradle 9.0.

Eager population of the publication can happen if the following methods are called:

* Maven
** link:{javadocPath}/org/gradle/api/publish/maven/MavenPublication.html#getArtifacts--[MavenPublication.getArtifacts()]
* Ivy
** link:{javadocPath}/org/gradle/api/publish/ivy/IvyPublication.html#getArtifacts--[IvyPublication.getArtifacts()]
** link:{javadocPath}/org/gradle/api/publish/ivy/IvyPublication.html#getConfigurations--[IvyPublication.getConfigurations()]
** link:{javadocPath}/org/gradle/api/publish/ivy/IvyPublication.html#configurations(Action)--[IvyPublication.configurations(Action)]

Previously, the following code did not generate warnings, but it created inconsistencies between published artifacts:

====
[.multi-language-sample]
=====
.build.gradle.kts
[source,kotlin]
----
publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["java"])
        }
        create<IvyPublication>("ivy") {
            from(components["java"])
        }
    }
}

// These calls eagerly populate the Maven and Ivy publications

(publishing.publications["maven"] as MavenPublication).artifacts
(publishing.publications["ivy"] as IvyPublication).artifacts

val javaComponent = components["java"] as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(configurations["apiElements"]) { skip() }
javaComponent.withVariantsFromConfiguration(configurations["runtimeElements"]) { skip() }
----
=====
[.multi-language-sample]
=====
.build.gradle
[source,groovy]
----
publishing {
    publications {
        maven(MavenPublication) {
            from components.java
        }
        ivy(IvyPublication) {
            from components.java
        }
    }
}

// These calls eagerly populate the Maven and Ivy publications

publishing.publications.maven.artifacts
publishing.publications.ivy.artifacts

components.java.withVariantsFromConfiguration(configurations.apiElements) { skip() }
components.java.withVariantsFromConfiguration(configurations.runtimeElements) { skip() }
----
=====
====

In this example, the Maven and Ivy publications will contain the main JAR artifacts for the project, whereas the GMM link:https://github.com/gradle/gradle/blob/master/subprojects/docs/src/docs/design/gradle-module-metadata-latest-specification.md[module file] will omit them.

[[minimum_test_jvm_version]]
==== Running tests on JVM versions 6 and 7

Running JVM tests on JVM versions older than 8 is deprecated.
Testing on these versions will become an error in Gradle 9.0

[[kotlin_dsl_precompiled_gradle_lt_6]]
==== Applying Kotlin DSL precompiled scripts published with Gradle < 6.0

Applying Kotlin DSL precompiled scripts published with Gradle < 6.0 is deprecated.
Please use a version of the plugin published with Gradle >= 6.0.

[[kotlin_dsl_with_kgp_lt_1_8_0]]
==== Applying the `kotlin-dsl` together with Kotlin Gradle Plugin < 1.8.0

Applying the `kotlin-dsl` together with Kotlin Gradle Plugin < 1.8.0 is deprecated.
Please let Gradle control the version of `kotlin-dsl` by removing any explicit `kotlin-dsl` version constraints from your build logic.
This will let the `kotlin-dsl` plugin decide which version of the Kotlin Gradle Plugin to use.
If you explicitly declare which version of the Kotlin Gradle Plugin to use for your build logic, update it to >= 1.8.0.

[[kotlin_dsl_deprecated_catalogs_plugins_block]]
==== Accessing `libraries` or `bundles` from dependency version catalogs in the `plugins {}` block of a Kotlin script

Accessing `libraries` or `bundles` from dependency version catalogs in the `plugins {}` block of a Kotlin script is deprecated.
Please only use `versions` or `plugins` from dependency version catalogs in the `plugins {}` block.

[[validate_plugins_without_java_toolchain]]
==== Using `ValidatePlugins` task without a Java Toolchain

Using a task of type link:{javadocPath}/org/gradle/plugin/devel/tasks/ValidatePlugins.html[ValidatePlugins] without applying the link:toolchains.html[Java Toolchains] plugin is deprecated, and will become an error in Gradle 9.0.

To avoid this warning, please apply the plugin to your project:

====
[.multi-language-sample]
=====
.build.gradle.kts
[source,kotlin]
----
plugins {
    id("jdk-toolchains")
}
----
=====
[.multi-language-sample]
=====
.build.gradle
[source,groovy]
----
plugins {
    id 'jdk-toolchains'
}
----
=====
====

The Java Toolchains plugin is applied automatically by the link:java_plugin.html[Java plugin],
so you can also apply it to your project and it will fix the warning.

[[org_gradle_util_reports_deprecations]]
==== Deprecated members of the `org.gradle.util` package now report their deprecation

These members will be removed in Gradle 9.0.

* `WrapUtil.toDomainObjectSet(...)`
* `GUtil.toCamelCase(...)`
* `GUtil.toLowerCase(...)`
* `ConfigureUtil.configureByMap(...)`

[[ibm_semeru_should_not_be_used]]
==== Deprecated JVM vendor IBM Semeru

The enum constant `JvmVendorSpec.IBM_SEMERU` is now deprecated and will be removed in Gradle 9.0.

Please replace it by its equivalent `JvmVendorSpec.IBM` to avoid warnings and potential errors in the next major version release.

[[configuring_custom_build_layout]]
==== Setting custom build layout on `StartParameter` and `GradleBuild`

Following the <<upgrading_version_7.adoc#configuring_custom_build_layout, related previous deprecation>> of the behaviour in Gradle 7.1, it is now also deprecated to use related link:{javadocPath}/org/gradle/StartParameter.html[StartParameter] and link:{javadocPath}/org/gradle/api/tasks/GradleBuild.html[GradleBuild] properties.
These properties will be removed in Gradle 9.0.

Setting custom build file using link:{groovyDslPath}/org.gradle.api.tasks.GradleBuild.html#org.gradle.api.tasks.GradleBuild:buildFile[buildFile] property in link:{groovyDslPath}/org.gradle.api.tasks.GradleBuild.html[GradleBuild] task has been deprecated.

Please use the link:{groovyDslPath}/org.gradle.api.tasks.GradleBuild.html#org.gradle.api.tasks.GradleBuild:dir[dir] property instead to specify the root of the nested build.
Alternatively, consider using one of the recommended alternatives for link:{groovyDslPath}/org.gradle.api.tasks.GradleBuild.html[GradleBuild] task as suggested in <<authoring_maintainable_build_scripts#sec:avoiding_use_of_gradlebuild, Avoid using the GradleBuild task type>> section.

Setting custom build layout using link:{javadocPath}/org/gradle/StartParameter.html[StartParameter] methods link:{javadocPath}/org/gradle/StartParameter.html#setBuildFile-java.io.File-[setBuildFile(File)] and link:{javadocPath}/org/gradle/StartParameter.html#setSettingsFile-java.io.File-[setSettingsFile(File)] as well as the counterpart getters link:{javadocPath}/org/gradle/StartParameter.html#getBuildFile--[getBuildFile()] and link:{javadocPath}/org/gradle/StartParameter.html#getSettingsFile--[getSettingsFile()] have been deprecated.

Please use standard locations for settings and build files:

* settings file in the root of the build
* build file in the root of each subproject

[[disabling_user_home_cache_cleanup]]
==== Deprecated org.gradle.cache.cleanup property

The `org.gradle.cache.cleanup` property in `gradle.properties` under Gradle user home has been deprecated.  Please use the <<directory_layout#dir:gradle_user_home:configure_cache_cleanup,cache cleanup DSL>> instead to disable or modify the cleanup configuration.

Since the `org.gradle.cache.cleanup` property may still be needed for older versions of Gradle, this property may still be present and no deprecation warnings will be printed as long as it is also configured via the DSL.
The DSL value will always take preference over the `org.gradle.cache.cleanup` property.
If the desired configuration is to disable cleanup for older versions of Gradle (using `org.gradle.cache.cleanup`), but to enable cleanup with the default values for Gradle versions at or above Gradle 8, then cleanup should be configured to use link:{javadocPath}/org/gradle/api/cache/Cleanup.html#DEFAULT[Cleanup.DEFAULT]:

====
[.multi-language-sample]
=====
.cache-settings.gradle
[source,groovy]
----
if (GradleVersion.current() >= GradleVersion.version('8.0')) {
    apply from: "gradle8/cache-settings.gradle"
}
----
=====
[.multi-language-sample]
=====
.cache-settings.gradle.kts
[source,kotlin]
----
if (GradleVersion.current() >= GradleVersion.version("8.0")) {
    apply(from = "gradle8/cache-settings.gradle")
}
----
=====
====
====
[.multi-language-sample]
=====
.gradle8/cache-settings.gradle
[source,groovy]
----
beforeSettings { settings ->
    settings.caches {
        cleanup = Cleanup.DEFAULT
    }
}
----
=====
=====
.gradle8/cache-settings.gradle.kts
[source,kotlin]
----
beforeSettings {
    caches {
        cleanup.set(Cleanup.DEFAULT)
    }
}
----
=====
====

[no_relative_paths_for_java_executables]
==== Deprecated using relative paths to specify Java executables
Using relative file paths to point to Java executables is now deprecated and will become an error in Gradle 9.
This is done to reduce confusion about what such relative paths should resolve against.

[[task_convention]]
==== Calling `Task.getConvention()`, `Task.getExtensions()` from a task action

Calling link:{javadocPath}/org/gradle/api/Task.html#getConvention--[Task.getConvention()], link:{javadocPath}/org/gradle/api/Task.html#getExtensions--[Task.getExtensions()] from a task action at
execution time is now deprecated and will be made an error in Gradle 9.0.

See the <<configuration_cache#config_cache:requirements:disallowed_types,configuration cache chapter>> for details on
how to migrate these usages to APIs that are supported by the configuration cache.

=== Changes in the IDE integration

[[kotlin_dsl_plugins_catalogs_workaround]]
==== Workaround for false positive errors shown in Kotlin DSL `plugins {}` block using version catalog is not needed anymore

Version catalog accessors for plugin aliases in the `plugins {}` block aren't shown as errors in IntelliJ IDEA and Android Studio Kotlin script editor anymore.

If you were using the `@Suppress("DSL_SCOPE_VIOLATION")` annotation as a workaround, you can now remove it.

If you were using the link:https://plugins.jetbrains.com/plugin/18949-gradle-libs-error-suppressor[Gradle Libs Error Suppressor] IntelliJ IDEA plugin, you can now uninstall it.

After upgrading Gradle to 8.1 you will need to clear the IDE caches and restart.

Also see <<upgrading_version_8.adoc#kotlin_dsl_deprecated_catalogs_plugins_block, the deprecated usages of version catalogs in the Kotlin DSL `plugins {}` block>> above.
