本章提供将 Gradle 8.x 版本迁移到最新 Gradle 版本所需的信息。要从 Gradle 4.x、5.x、6.x 或 7.x 迁移,请首先参阅旧版迁移指南

我们建议所有用户执行以下步骤:

  1. 尝试运行gradle help --scan并查看生成的构建扫描的弃用视图。

    Deprecations View of a Gradle Build Scan

    这样您就可以看到适用于您的构建的任何弃用警告。

    或者,您可以运行gradle help --warning-mode=all以在控制台中查看弃用信息,尽管它可能不会报告那么多详细信息。

  2. 更新您的插件。

    一些插件将与这个新版本的 Gradle 兼容,例如因为它们使用已删除或更改的内部 API。当插件尝试使用 API 的已弃用部分时,上一步将通过发出弃用警告来帮助您识别潜在问题。

  3. 运行gradle wrapper --gradle-version 8.7将项目更新到8.7。

  4. 尝试运行该项目并使用故障排除指南调试任何错误。

从 8.6 及更早版本升级

潜在的重大变化

升级到 Kotlin 1.9.22

嵌入式 Kotlin 已更新至Kotlin 1.9.22

升级到 Apache SSHD 2.10.0

Apache SSHD 已从 2.0.0 更新到2.10.0

JSch的更换和升级

JSch已被替换com.github.mwiede:jsch并从 0.1.55 更新到0.2.16

升级到 Eclipse JGit 5.13.3

Eclipse JGit 已从 5.7.0 更新到5.13.3

这包括通过从 JSch 迁移到 Apache SSHD,重新设计 Gradle 为 SSH 操作配置 JGit 的方式。

升级到 Apache Commons 压缩 1.25.0

Apache Commons Compress 已从 1.21 更新到1.25.0。此更改可能会影响生成的 jar、zip 和其他存档类型的校验和,因为生成的工件的元数据可能有所不同。

升级到ASM 9.6

ASM 从 9.5 升级到9.6,以更好地支持多版本 jar。

版本目录解析器升级

版本目录解析器已升级,现在符合TOML 规范 1.0.0 版

这不应影响使用推荐语法或由 Gradle 生成用于发布的目录。

弃用

已弃用插件约定的注册

自 Gradle 8.2 以来,使用插件约定一直发出警告。现在,注册插件约定也会触发弃用警告。有关更多信息,请参阅有关插件约定弃用的部分

"name"()在 Kotlin DSL 中引用任务和域对象

在 Kotlin DSL 中,可以使用符号通过名称来引用任务或其他域对象"name"()

有多种方法可以按名称查找容器中的元素:

tasks {
    "wrapper"() // 1 - returns TaskProvider<Task>
    "wrapper"(Wrapper::class) // 2 - returns TaskProvider<Wrapper>
    "wrapper"(Wrapper::class) { // 3 - configures a task named wrapper of type Wrapper
    }
    "wrapper" { // 4 - configures a task named wrapper of type Task
    }
}

第一个表示法已弃用,并将在 Gradle 9.0 中删除。不要使用"name"()来引用任务或域对象,而是使用named("name")或其他受支持的符号之一。

上面的例子可以写成:

tasks {
    named("wrapper") // returns TaskProvider<Task>
}

Groovy DSL 构建脚本和 Gradle API 不受此影响。

已弃用无效 URL 解码行为

在 Gradle 8.3 之前,Gradle 会使用接受无效 URL 并错误解码其他 URL 的算法CharSequence来解码给定内容。 Project.uri(Object)Gradle 现在使用该类URI来解析和解码 URL,但在发生错误时会回退到旧行为。

从 Gradle 9.0 开始,回退将被删除,并且会抛出错误。

要修复弃用警告,需要旧行为的无效 URL 应重新编码为有效 URL,如下例所示:

表 1. 旧版 URL 转换
原始输入 新输入 推理

file:relative/path

relative/path

file方案不支持相对路径。

file:relative/path%21

relative/path!

如果没有方案,路径将按原样采用,无需解码。

https://example.com/my folder/

https://example.com/my%20folder/

URL 中的空格无效。

https://example.com/my%%badly%encoded%path

https://example.com/my%25%25badly%25encoded%25path

%%25必须按照URL进行编码,并且任何%转义符都不应无效。

已弃用SelfResolvingDependency

SelfResolvingDependency接口已在 Gradle 9.0 中弃用并删除。这种类型可以追溯到 Gradle 的第一个版本,其中一些依赖项可以独立解决。现在,所有依赖项都应该使用Configuration.

目前,ProjectDependencyFileCollectionDependency实现了这个接口。在 Gradle 9.0 中,这些类型将不再实现SelfResolvingDependency.相反,他们都将直接实现Dependency.

因此,以下ProjectDependency和方法FileCollectionDependency将不再可用:

  • resolve

  • resolve(boolean)

  • getBuildDependencies

请考虑以下脚本,这些脚本展示了已弃用的接口及其替代品:

build.gradle.kts
plugins {
    id("java-library")
}

dependencies {
    implementation(files("bar.txt"))
    implementation(project(":foo"))
}

tasks.register("resolveDeprecated") {
    // Wire build dependencies (calls getBuildDependencies)
    dependsOn(configurations["implementation"].dependencies.toSet())

    // Resolve dependencies
    doLast {
        configurations["implementation"].dependencies.withType<FileCollectionDependency>() {
            assert(resolve().map { it.name } == listOf("bar.txt"))
            assert(resolve(true).map { it.name } == listOf("bar.txt"))
        }
        configurations["implementation"].dependencies.withType<ProjectDependency>() {
            // These methods do not even work properly.
            assert(resolve().map { it.name } == listOf<String>())
            assert(resolve(true).map { it.name } == listOf<String>())
        }
    }
}

tasks.register("resolveReplacement") {
    val conf = configurations["runtimeClasspath"]

    // Wire build dependencies
    dependsOn(conf)

    // Resolve dependencies
    val files = conf.files
    doLast {
        assert(files.map { it.name } == listOf("bar.txt", "foo.jar"))
    }
}

包中已弃用的成员org.gradle.util现在报告其弃用情况

这些成员将在 Gradle 9.0 中删除。

  • Collection.stringize(Collection)

从 8.5 及更早版本升级

潜在的重大变化

升级到JaCoCo 0.8.11

JaCoCo 已更新至0.8.11

DependencyAdder重命名为DependencyCollector

孵化DependencyAdder界面已更名为DependencyCollectorgetDependencies接口中添加了一个方法,该方法返回所有声明的依赖项。

弃用

已弃用registerFeature使用main源集的调用

使用源集调用registerFeature扩展已被弃用,并将改变 Gradle 9.0 中的行为。javamain

目前,使用源集调用时创建的要素的usingSourceSet初始化方式与使用任何其他源集main调用时创建的要素的初始化方式不同。usingSourceSet以前,在使用main源集时,会创建 new implementationcompileOnlyruntimeOnlyapicompileOnlyApi配置,并配置源集的编译和运行时类路径main来扩展这些配置。

从 Gradle 9.0 开始,main源集将像任何其他源集一样对待。java-library应用插件(或应用该插件的任何其他插件java)后,usingSourceSet使用main源集调用将引发异常。这是因为该java插件已经配置了一个主要功能。仅当java未应用插件时main,调用时才会允许源集usingSourceSet

当前向主源集注册功能的代码,如下所示:

build.gradle.kts
plugins {
    id("java-library")
}

java {
    registerFeature("feature") {
        usingSourceSet(sourceSets["main"])
    }
}
build.gradle
plugins {
    id("java-library")
}

java {
    registerFeature("feature") {
        usingSourceSet(sourceSets.main)
    }
}

相反,应该为该功能创建一个单独的源集,并将该功能注册到该源集:

build.gradle.kts
plugins {
    id("java-library")
}

sourceSets {
    create("feature")
}

java {
    registerFeature("feature") {
        usingSourceSet(sourceSets["feature"])
    }
}
build.gradle
plugins {
    id("java-library")
}

sourceSets {
    feature
}

java {
    registerFeature("feature") {
        usingSourceSet(sourceSets.feature)
    }
}

已弃用将具有显式名称的工件依赖项发布到 Maven 存储库

artifactId不推荐使用名称与 Maven 存储库的依赖项不同的显式工件来发布依赖项。发布到 Ivy 存储库时仍然允许这种行为。在 Gradle 9.0 中会导致错误。

目前,当发布到 Maven 存储库时,Gradle 将解释下面的依赖项,就好像它是用坐标声明的一样org:notfoo:1.0

build.gradle.kts
dependencies {
    implementation("org:foo:1.0") {
        artifact {
            name = "notfoo"
        }
    }
}
build.gradle
dependencies {
    implementation("org:foo:1.0") {
        artifact {
            name = "notfoo"
        }
    }
}

相反,这种依赖关系应该声明为:

build.gradle.kts
dependencies {
    implementation("org:notfoo:1.0")
}
build.gradle
dependencies {
    implementation("org:notfoo:1.0")
}

已弃用ArtifactIdentifier

该类ArtifactIdentifier已在 Gradle 9.0 中被弃用并删除。

DependencyCollector观察后弃用变异依赖项

从 Gradle 9.0 开始,在观察到来自DependencyCollector的依赖项后更改这些依赖项将导致错误。该DependencyCollector接口用于声明测试套件 DSL 内的依赖关系。

考虑以下示例,其中测试套件的依赖关系在观察到后发生了变化:

build.gradle.kts
plugins {
    id("java-library")
}

testing.suites {
    named<JvmTestSuite>("test") {
        dependencies {
            // Dependency is declared on a `DependencyCollector`
            implementation("com:foo")
        }
    }
}

configurations.testImplementation {
    // Calling `all` here realizes/observes all lazy sources, including the `DependencyCollector`
    // from the test suite block. Operations like resolving a configuration similarly realize lazy sources.
    dependencies.all {
        if (this is ExternalDependency && group == "com" && name == "foo" && version == null) {
            // Dependency is mutated after observation
            version {
                require("2.0")
            }
        }
    }
}

在上面的示例中,构建逻辑使用迭代和突变来尝试为特定依赖项设置默认版本(如果尚未设置版本)。像上面的示例这样的构建逻辑在解决声明的依赖关系方面带来了挑战,因为报告工具将显示此依赖关系,就好像用户将版本声明为“2.0”一样,即使他们从未这样做过。相反,构建逻辑可以通过声明preferred依赖项坐标的版本约束来避免迭代和突变。如果没有声明其他版本,这允许依赖项管理引擎使用在约束上声明的版本。

build.gradle.kts
dependencies {
    constraints {
        testImplementation("com:foo") {
            version {
                prefer("2.0")
            }
        }
    }
}

从 8.4 及更早版本升级

潜在的重大变化

升级到 Kotlin 1.9.20

嵌入式 Kotlin 已更新至Kotlin 1.9.20

Groovy 任务约定的更改

groovy-base插件现在负责配置所有GroovyCompile任务的源和目标兼容性版本约定。

如果您在未应用的情况下grooy-base使用此任务,则必须手动设置这些任务的兼容性版本。一般来说,groovy-base只要处理 Groovy 语言任务,就应该应用该插件。

提供者过滤器

传递给的参数类型Provider.filter从 更改为PredicateSpec获得更一致的 API。此更改不应影响使用Provider.filterlambda 表达式的任何人。但是,如果插件作者不使用 SAM 转换来创建 lambda,这可能会影响他们。

弃用

包中已弃用的成员org.gradle.util现在报告其弃用情况

这些成员将在 Gradle 9.0 中删除:

  • VersionNumber.parse(String)

  • VersionNumber.compareTo(VersionNumber)

根据已解决的配置已弃用

解析 时Configuration,有时可以选择相同的配置作为变体。配置应该用于一个目的(解析、消耗或依赖声明),因此只有当配置被标记为可消耗和可解析时才会发生这种情况。

这可能会导致令人困惑的循环依赖图,因为正在解析的配置用于两个不同的目的。

为了避免这个问题,插件应该将所有可解析的配置标记为或在创建用于解析的配置时canBeConsumed=false使用配置工厂方法。resolvable(String)

在 Gradle 9.0 中,将不再允许以这种方式使用配置,并且会导致错误。

包括没有现有目录的项目

如果将项目添加到构建中,但关联的项目projectDir不存在或不可写, Gradle 会发出警告。从版本 9.0 开始,如果项目目录丢失或只读,Gradle 将不会运行构建。如果您打算动态综合项目,请确保也为它们创建目录:

settings.gradle.kts
include("project-without-directory")
project(":project-without-directory").projectDir.mkdirs()
settings.gradle
include 'project-without-directory'
project(":project-without-directory").projectDir.mkdirs()

从 8.3 及更早版本升级

潜在的重大变化

升级到 Kotlin 1.9.10

嵌入式 Kotlin 已更新至Kotlin 1.9.10

XML 解析现在需要最新的解析器

Gradle 8.4 现在配置 XML 解析器并启用安全功能。如果您的构建逻辑依赖于不支持安全解析的旧 XML 解析器,那么您的构建现在可能会失败。如果遇到故障,请检查并更新或删除对旧版 XML 解析器的任何依赖项。

如果您无法升级来自构建逻辑依赖项的 XML 解析器,则可以强制使用 JVM 中内置的 XML 解析器。例如,在 OpenJDK 中,可以通过添加以下内容来完成gradle.properties

systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
systemProp.javax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
systemProp.javax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

请参阅CVE-2023-42445通报,了解更多详细信息以及在以前的 Gradle 版本上启用安全 XML 处理的方法。

带有自定义 JEE 1.3 描述符的 EAR 插件

Gradle 8.4 在解析 XML 文档时禁止外部 XML 实体。如果您使用 EAR 插件并application.xml通过 EAR 插件的 DSL 配置描述符,并在自定义块中使用withXml {}和使用自定义描述符asElement{},那么构建现在将因安全原因而失败。

build.gradle.kts
plugins {
    id("ear")
}
ear {
    deploymentDescriptor {
        version = "1.3"
        withXml {
            asElement()
        }
    }
}
build.gradle
plugins {
    id("ear")
}
ear {
    deploymentDescriptor {
        version = "1.3"
        withXml {
            asElement()
        }
    }
}

如果您碰巧使用asNode()而不是asElement()那么给出的任何更改asNode()都会忽略外部 DTD。

javax.xml.accessExternalDTD您可以通过将系统属性设置为 来运行构建来解决此问题http

在命令行上,将其添加到您的 Gradle 调用中:

-Djavax.xml.accessExternalDTD=http

要使此解决方法持久存在,请将以下行添加到您的gradle.properties

systemProp.javax.xml.accessExternalDTD=http

请注意,这将为整个构建 JVM 启用对外部 DTD 的 HTTP 访问。有关更多详细信息,请参阅JAXP 文档。

弃用

已弃用的GenerateMavenPom方法

以下方法GenerateMavenPom已弃用,并将在 Gradle 9.0 中删除。它们从来没有打算成为公共 API。

  • getVersionRangeMapper

  • withCompileScopeAttributes

  • withRuntimeScopeAttributes

从 8.2 及更早版本升级

潜在的重大变化

不推荐使用Project.buildDir会导致脚本编译失败

随着 的弃用Project.buildDir,如果使用已弃用的字段,则编译时带有警告和错误的构建脚本可能会失败。

有关详细信息,请参阅弃用条目

TestLauncherAPI 不再忽略构建失败

TestLauncher接口是 Tooling API 的一部分,专门用于运行测试。它是BuildLauncher只能启动任务的逻辑扩展。据报告,它们的行为存在差异:如果执行相同的失败测试,BuildLauncher​​将报告构建失败,但TestLauncher不会报告。最初,这是一个设计决策,以便在所有测试任务中继续执行并运行测试,而不是在第一次失败时停止。同时,这种行为可能会让用户感到困惑,因为他们可能会在成功的构建中经历失败的测试。为了使两个 API 更加统一,我们TestLauncher还使构建失败,这是一个潜在的重大更改。即使测试任务失败,为了继续执行测试,Tooling API 客户端应显式传递--continue给构建。

ArtifactView修复了使用和进行变体选择行为ArtifactCollection

用于选择不同工件或文件的依赖关系解析 API (Configuration.getIncoming().artifactView { }Configuration.getIncoming().getArtifacts()) 捕获了底层“配置”属性的不可变副本,以用于变体选择。如果在调用这些方法后更改了“配置”的属性,则这些方法选择的工件可能会出现意外。

考虑在创建Configurationan 之后更改a 上的属性集的情况。ArtifactView

build.gradle.kts
tasks {
    myTask {
        inputFiles.from(configurations.classpath.incoming.artifactView {
            attributes {
                // Add attributes to select a different type of artifact
            }
        }.files)
    }
}

configurations {
    classpath {
        attributes {
            // Add more attributes to the configuration
        }
    }
}

inputFiles的属性使用myTask工件视图从配置中选择不同类型的工件classpath。由于工件视图是在将属性添加到配置之前创建的,因此 Gradle 无法选择正确的工件。

某些构建可能通过将附加属性放入工件视图来解决此问题。这不再是必要的了。

升级到 Kotlin 1.9.0

嵌入式 Kotlin 已从 1.8.20 更新到Kotlin 1.9.0。为了向后兼容,Kotlin 语言和 Kotlin DSL 的 API 级别仍设置为 1.8。请参阅Kotlin 1.8.22Kotlin 1.8.21的发行说明。

Kotlin 1.9 放弃了对 Kotlin 语言和 API 级别 1.3 的支持。如果您使用此版本的 Gradle 构建用 Kotlin 编写的 Gradle 插件,并且需要支持 Gradle <7.0,则需要坚持使用 Kotlin Gradle 插件 <1.9.0 并将 Kotlin 语言和 API 级别配置为 1.3。有关其他版本的详细信息,请参阅兼容性表。

Configuration对属性的热切评价

Gradle 8.3 更新了JVM 配置的org.gradle.libraryelementsorg.gradle.jvm.version属性,使其在创建时就存在,而不像以前,它们仅在配置被解析或使用后才存在。特别是, 的值org.gradle.jvm.version依赖于项目配置的工具链,这意味着查询此属性的值将最终确定项目的 Java 工具链的值。

急切地查询 JVM 配置属性的插件或构建逻辑现在可能会导致项目的 Java 工具链比以前更早完成。尝试在工具链最终确定后对其进行修改将导致类似于以下内容的错误消息:

The value for property 'implementation' is final and cannot be changed any further.
The value for property 'languageVersion' is final and cannot be changed any further.
The value for property 'vendor' is final and cannot be changed any further.

当插件或构建逻辑急切地查询现有 JVM 配置的属性以创建具有相同属性的新配置时,可能会出现这种情况。以前,此逻辑会完全省略上述两个属性,而现在相同的逻辑将复制属性并最终确定项目的 Java 工具链。为了避免工具链过早完成,应更新属性复制逻辑以延迟查询源配置的属性:

build.gradle.kts
fun <T> copyAttribute(attribute: Attribute<T>, from: AttributeContainer, to: AttributeContainer) =
    to.attributeProvider<T>(attribute, provider { from.getAttribute(attribute)!! })

val source = configurations["runtimeClasspath"].attributes
configurations {
    create("customRuntimeClasspath") {
        source.keySet().forEach { key ->
            copyAttribute(key, source, attributes)
        }
    }
}
build.gradle
def source = configurations.runtimeClasspath.attributes
configurations {
    customRuntimeClasspath {
        source.keySet().each { key ->
            attributes.attributeProvider(key, provider { source.getAttribute(key) })
        }
    }
}

弃用

已弃用Project.buildDir将被替换为Project.layout.buildDirectory

Project.buildDir属性已弃用。它使用急切的 API,并且如果在构建逻辑中读取值然后进行修改,则会出现排序问题。它可能会导致输出最终出现在不同的位置。

它被替换为DirectoryProperty在 处找到的Project.layout.buildDirectoryProjectLayout详情请参见接口。

请注意,在此阶段,如果您仍然使用 .Gradle 将不会打印弃用警告Project.buildDir。我们知道这是一个很大的变化,并希望给主要插件的作者一些时间来首先放弃它的使用。

File从 a到 a 的切换DirectoryProperty需要对构建逻辑进行调整。主要影响是您无法使用 a 内的属性String来扩展它。相反,您应该利用dirfile方法来计算所需的位置。

这是创建文件的示例,其中以下内容:

build.gradle.kts
// Returns a java.io.File
file("$buildDir/myOutput.txt")
build.gradle
// Returns a java.io.File
file("$buildDir/myOutput.txt")

应替换为:

build.gradle.kts
// Compatible with a number of Gradle lazy APIs that accept also java.io.File
val output: Provider<RegularFile> = layout.buildDirectory.file("myOutput.txt")

// If you really need the java.io.File for a non lazy API
output.get().asFile

// Or a path for a lazy String based API
output.map { it.asFile.path }
build.gradle
// Compatible with a number of Gradle lazy APIs that accept also java.io.File
Provider<RegularFile> output = layout.buildDirectory.file("myOutput.txt")

// If you really need the java.io.File for a non lazy API
output.get().asFile

// Or a path for a lazy String based API
output.map { it.asFile.path }

这是创建目录的另一个示例,其中以下内容:

build.gradle.kts
// Returns a java.io.File
file("$buildDir/outputLocation")
build.gradle
// Returns a java.io.File
file("$buildDir/outputLocation")

应替换为:

build.gradle.kts
// Compatible with a number of Gradle APIs that accept a java.io.File
val output: Provider<Directory> = layout.buildDirectory.dir("outputLocation")

// If you really need the java.io.File for a non lazy API
output.get().asFile

// Or a path for a lazy String based API
output.map { it.asFile.path }
build.gradle
// Compatible with a number of Gradle APIs that accept a java.io.File
Provider<Directory> output = layout.buildDirectory.dir("outputLocation")

// If you really need the java.io.File for a non lazy API
output.get().asFile

// Or a path for a lazy String based API
output.map { it.asFile.path }

已弃用的ClientModule依赖项

ClientModule依赖项已弃用,并将在 Gradle 9.0 中删除。

客户端模块依赖项最初的目的是允许构建通过在本地定义元数据来覆盖外部依赖项的不正确或丢失的组件元数据。此功能已被组件元数据规则取代。

考虑以下客户端模块依赖关系示例:

build.gradle.kts
dependencies {
    implementation(module("org:foo:1.0") {
        dependency("org:bar:1.0")
        module("org:baz:1.0") {
            dependency("com:example:1.0")
        }
    })
}
build.gradle
dependencies {
    implementation module("org:foo:1.0") {
        dependency "org:bar:1.0"
        module("org:baz:1.0") {
            dependency "com:example:1.0"
        }
    }
}

这可以替换为以下组件元数据规则:

build-logic/src/main/kotlin/my-plugin.gradle.kts
@CacheableRule
abstract class AddDependenciesRule @Inject constructor(val dependencies: List<String>) : ComponentMetadataRule {
    override fun execute(context: ComponentMetadataContext) {
        listOf("compile", "runtime").forEach { base ->
            context.details.withVariant(base) {
                withDependencies {
                    dependencies.forEach {
                        add(it)
                    }
                }
            }
        }
    }
}
build.gradle.kts
dependencies {
    components {
        withModule<AddDependenciesRule>("org:foo") {
            params(listOf(
                "org:bar:1.0",
                "org:baz:1.0"
            ))
        }
        withModule<AddDependenciesRule>("org:baz") {
            params(listOf("com:example:1.0"))
        }
    }

    implementation("org:foo:1.0")
}
build-logic/src/main/groovy/my-plugin.gradle
@CacheableRule
abstract class AddDependenciesRule implements ComponentMetadataRule {

    List<String> dependencies

    @Inject
    AddDependenciesRule(List<String> dependencies) {
        this.dependencies = dependencies
    }

    @Override
    void execute(ComponentMetadataContext context) {
        ["compile", "runtime"].each { base ->
            context.details.withVariant(base) {
                withDependencies {
                    dependencies.each {
                        add(it)
                    }
                }
            }
        }
    }
}
build.gradle
dependencies {
    components {
        withModule("org:foo", AddDependenciesRule) {
            params([
                "org:bar:1.0",
                "org:baz:1.0"
            ])
        }
        withModule("org:baz", AddDependenciesRule) {
            params(["com:example:1.0"])
        }
    }

    implementation "org:foo:1.0"
}

最早支持的 Develocity 插件版本是 3.13.1

从 Gradle 9.0 开始,最早支持的 Develocity 插件版本是 3.13.1。应用时,3.0 至 3.13 的插件版本将被忽略。

升级到 Develocity 插件版本 3.13.1 或更高版本。您可以在 Gradle 插件门户 上找到最新的可用版本。有关兼容性的更多信息可以在此处找到。

从 8.1 及更早版本升级

潜在的重大变化

升级到 Kotlin 1.8.20

嵌入式 Kotlin 已更新至Kotlin 1.8.20。有关更多信息,请参阅Kotlin 1.8.20 中的新增功能

请注意,Kotlin 编译避免存在一个已知问题,如果编译类路径包含非常大的 JAR 文件,则可能会导致任务OutOfMemory异常。compileKotlin这适用于应用 Kotlin 插件 v1.8.20 或kotlin-dsl插件的构建。

您可以通过在文件中禁用 Kotlin 编译避免来解决此问题gradle.properties

kotlin.incremental.useClasspathSnapshot=false

请参阅KT-57757了解更多信息。

升级到 Groovy 3.0.17

Groovy 已更新至Groovy 3.0.17

由于之前的版本是 3.0.15,因此还包括3.0.16 的更改。

升级到 Ant 1.10.13

Ant 已更新至Ant 1.10.13

由于之前的版本是 1.10.11,因此还包括1.10.12 的更改。

升级到 CodeNarc 3.2.0

CodeNarc 的默认版本已更新为CodeNarc 3.2.0

升级到PMD 6.55.0

PMD 已更新至PMD 6.55.0

由于之前的版本是 6.48.0,因此包含此后的所有更改。

升级到JaCoCo 0.8.9

JaCoCo 已更新至0.8.9

插件兼容性更改

使用 Gradle >= 8.2 编译的插件,使用 Kotlin DSL 函数Project.the<T>()Project.the(KClass)或者Project.configure<T> {}无法在 Gradle ⇐ 6.1 上运行。

推迟或避免配置某些任务

当执行依赖解析时,Gradle 创建可用Configuration的内部表示。这需要检查所有配置和工件。处理由任务创建的工件会导致这些任务被实现和配置。

现在,这种内部表示的创建方式更加懒惰,这可以更改任务配置的顺序。有些任务可能永远不会被配置。

此更改可能会导致依赖于特定顺序的代码路径不再起作用,例如根据某些属性的存在有条件地将属性添加到配置中。

我们建议不要从可能未配置的其他域对象的配置块中修改域对象(配置、源集、任务等)。

例如,避免这样做:

    configurations {
        val myConfig = create("myConfig")
    }

    tasks.register("myTask") {
            // This is not safe, as the execution of this block may not occur, or may not occur in the order expected
          configurations["myConfig"].attributes {
              attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, Usage.JAVA_RUNTIME))
          }
    }

弃用

CompileOptions方法弃用

以下方法CompileOptions已被弃用:

  • getAnnotationProcessorGeneratedSourcesDirectory()

  • setAnnotationProcessorGeneratedSourcesDirectory(File)

  • setAnnotationProcessorGeneratedSourcesDirectory(Provider<File>)

这些方法的当前用法应该迁移到DirectoryProperty getGeneratedSourceOutputDirectory()

错误使用配置

当配置方法的调用与配置的预期用途不一致时,Gradle 现在将在运行时发出警告。

此更改是一项更大的持续努力的一部分,旨在使配置的预期行为更加一致和可预测,并进一步提高速度和内存。

目前,只能使用列出的这些允许的用法来调用以下方法:

  • resolve()- 仅可解析配置

  • files(Closure), files(Spec), files(Dependency…), fileCollection(Spec), fileCollection(Closure), fileCollection(Dependency…)- 仅限可解析配置

  • getResolvedConfigurations()- 仅可解析配置

  • defaultDependencies(Action)- 仅可声明配置

  • shouldResolveConsistentlyWith(Configuration)- 仅可解析配置

  • disableConsistentResolution()- 仅可解析配置

  • getDependencyConstraints()- 仅可声明配置

  • copy(), copy(Spec), copy(Closure), copyRecursive(), copyRecursive(Spec), copyRecursive(Closure)- 仅限可解析配置

Configuration接口的 Javadoc中注明了预期用途。该列表在未来的版本中可能会增加。

从 Gradle 9.0 开始,将禁止使用与其预期用途不一致的配置。

另请注意,尽管当前不受限制,但该getDependencies()方法实际上仅适用于 DECLARABLE 配置。该getAllDependencies()方法检索配置和任何超级配置的所有声明依赖项,不会限制于任何特定用途。

已弃用对插件约定的访问

约定的概念已经过时,并被提供自定义 DSL 的扩展所取代。

为了在 Gradle API 中反映这一点,不推荐使用以下元素:

Gradle Core 插件除了扩展之外仍然注册它们的约定以实现向后兼容性。

不推荐访问任何这些约定及其属性。这样做现在会发出弃用警告。这将成为 Gradle 9.0 中的错误。您应该更喜欢访问扩展及其属性。

有关具体示例,请参阅下一节。

著名的社区插件已经迁移到使用扩展来提供自定义 DSL。其中一些仍然注册了向后兼容性的约定。注册约定不会发出弃用警告,也不会提供迁移窗口。未来的 Gradle 版本就可以了。

另请注意,使用 Gradle ⇐ 8.1 编译的插件会使用 Kotlin DSL 函数Project.the<T>()Project.the(KClass)否则Project.configure<T> {}在 Gradle >= 8.2 上运行时会发出弃用警告。要解决此问题,应使用 Gradle >= 8.2 重新编译这些插件,或更改为直接使用访问扩展extensions.getByType<T>()

已弃用的base插件约定

该插件提供的约定属性base已被弃用,并计划在 Gradle 9.0 中删除。有关更广泛的上下文,请参阅有关插件约定弃用的部分

这些约定被BasePluginExtensionbase { }支持的配置块所取代。旧的约定对象使用简单的 getter 和 setter 方法定义、和属性。这些方法在扩展中可用只是为了保持向后兼容性。构建脚本应仅使用 type 的属性:distsDirNamelibsDirNamearchivesBaseNameProperty

build.gradle.kts
plugins {
    base
}

base {
    archivesName.set("gradle")
    distsDirectory.set(layout.buildDirectory.dir("custom-dist"))
    libsDirectory.set(layout.buildDirectory.dir("custom-libs"))
}
build.gradle
plugins {
    id 'base'
}

base {
    archivesName = "gradle"
    distsDirectory = layout.buildDirectory.dir('custom-dist')
    libsDirectory = layout.buildDirectory.dir('custom-libs')
}

已弃用的application插件约定

该插件提供的约定属性application已被弃用,并计划在 Gradle 9.0 中删除。有关更广泛的上下文,请参阅有关插件约定弃用的部分

以下代码现在将发出弃用警告:

build.gradle.kts
plugins {
    application
}

applicationDefaultJvmArgs = listOf("-Dgreeting.language=en") // Accessing a convention
build.gradle
plugins {
    id 'application'
}

applicationDefaultJvmArgs = ['-Dgreeting.language=en'] // Accessing a convention

这应该更改为使用由JavaApplicationapplication { }支持的配置块,而不是:

build.gradle.kts
plugins {
    application
}

application {
    applicationDefaultJvmArgs = listOf("-Dgreeting.language=en")
}
build.gradle
plugins {
    id 'application'
}

application {
    applicationDefaultJvmArgs = ['-Dgreeting.language=en']
}

已弃用的java插件约定

该插件提供的约定属性java已被弃用,并计划在 Gradle 9.0 中删除。有关更广泛的上下文,请参阅有关插件约定弃用的部分

以下代码现在将发出弃用警告:

build.gradle.kts
plugins {
    id("java")
}

configure<JavaPluginConvention> { // Accessing a convention
    sourceCompatibility = JavaVersion.VERSION_18
}
build.gradle
plugins {
    id 'java'
}

sourceCompatibility = 18 // Accessing a convention

这应该更改为使用由JavaPluginExtensionjava { }支持的配置块,而不是:

build.gradle.kts
plugins {
    id("java")
}

java {
    sourceCompatibility = JavaVersion.VERSION_18
}
build.gradle
plugins {
    id 'java'
}

java {
    sourceCompatibility = JavaVersion.VERSION_18
}

已弃用的war插件约定

该插件提供的约定属性war已被弃用,并计划在 Gradle 9.0 中删除。有关更广泛的上下文,请参阅有关插件约定弃用的部分

以下代码现在将发出弃用警告:

build.gradle.kts
plugins {
    id("war")
}

configure<WarPluginConvention> { // Accessing a convention
    webAppDirName = "src/main/webapp"
}
build.gradle
plugins {
    id 'war'
}

webAppDirName = 'src/main/webapp' // Accessing a convention

客户端应直接配置war任务。此外,tasks.withType(War.class).configureEach(…​)可用于配置类型 的每个任务War

build.gradle.kts
plugins {
    id("war")
}

tasks.war {
    webAppDirectory.set(file("src/main/webapp"))
}
build.gradle
plugins {
    id 'war'
}

war {
    webAppDirectory = file('src/main/webapp')
}

已弃用的ear插件约定

该插件提供的约定属性ear已被弃用,并计划在 Gradle 9.0 中删除。有关更广泛的上下文,请参阅有关插件约定弃用的部分

以下代码现在将发出弃用警告:

build.gradle.kts
plugins {
    id("ear")
}

configure<EarPluginConvention> { // Accessing a convention
    appDirName = "src/main/app"
}
build.gradle
plugins {
    id 'ear'
}

appDirName = 'src/main/app' // Accessing a convention

客户端应直接配置ear任务。此外,tasks.withType(Ear.class).configureEach(…​)可用于配置类型 的每个任务Ear

build.gradle.kts
plugins {
    id("ear")
}

tasks.ear {
    appDirectory.set(file("src/main/app"))
}
build.gradle
plugins {
    id 'ear'
}

ear {
    appDirectory = file('src/main/app')  // use application metadata found in this folder
}

已弃用的project-report插件约定

该插件提供的约定属性project-reports已被弃用,并计划在 Gradle 9.0 中删除。有关更广泛的上下文,请参阅有关插件约定弃用的部分

以下代码现在将发出弃用警告:

build.gradle.kts
plugins {
    `project-report`
}

configure<ProjectReportsPluginConvention> {
    projectReportDirName = "custom" // Accessing a convention
}
build.gradle
plugins {
    id 'project-report'
}

projectReportDirName = "custom" // Accessing a convention

配置您的报告任务:

build.gradle.kts
plugins {
    `project-report`
}

tasks.withType<HtmlDependencyReportTask>() {
    projectReportDirectory.set(project.layout.buildDirectory.dir("reports/custom"))
}
build.gradle
plugins {
    id 'project-report'
}

tasks.withType(HtmlDependencyReportTask) {
    projectReportDirectory = project.layout.buildDirectory.dir("reports/custom")
}

冗余配置使用激活

不推荐在已允许使用的配置上调用setCanBeConsumed(boolean)或。setCanBeResolved(boolean)

此弃用旨在帮助用户识别不必要的配置使用修改。

Configuration方法弃用

不推荐使用以下方法Configuration来删除:

  • getAll()

configurations相反,从项目的容器中获取所有配置的集合。

依赖自动测试框架实现依赖

在某些情况下,Gradle 将从 Gradle 发行版加载 JVM 测试框架依赖项以执行测试。这种现有行为可能会导致测试类路径上的测试框架依赖项版本冲突。为了避免这些冲突,此行为已被弃用,并将在 Gradle 9.0 中删除。使用 TestNG 的测试不受影响。

为了为这种行为变化做好准备,要么显式声明所需的依赖项,要么迁移到测试套件,在测试套件中自动管理这些依赖项。

测试套件

使用测试套件的构建不会受到此更改的影响。测试套件自动管理测试框架依赖项,不需要显式声明依赖项。有关迁移到测试套件的更多信息,请参阅用户手册。

手动声明依赖关系

在没有测试套件的情况下,必须在测试运行时类路径上手动声明依赖项:

  • 如果使用 JUnit 5,除了对测试引擎的现有依赖之外,还需要显式runtimeOnly依赖。junit-platform-launcherimplementation

  • 如果使用 JUnit 4,则仅需要implementation对 4 的现有依赖项。junit

  • 如果使用 JUnit 3,除了 对 3 的依赖之外,还需要runtimeOnly对4 的测试依赖。junitcompileOnlyjunit

build.gradle.kts
dependencies {
    // If using JUnit Jupiter
    testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")

    // If using JUnit Vintage
    testCompileOnly("junit:junit:4.13.2")
    testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.9.2")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")

    // If using JUnit 4
    testImplementation("junit:junit:4.13.2")

    // If using JUnit 3
    testCompileOnly("junit:junit:3.8.2")
    testRuntimeOnly("junit:junit:4.13.2")
}
build.gradle
dependencies {
    // If using JUnit Jupiter
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    // If using JUnit Vintage
    testCompileOnly 'junit:junit:4.13.2'
    testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.9.2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    // If using JUnit 4
    testImplementation 'junit:junit:4.13.2'

    // If using JUnit 3
    testCompileOnly 'junit:junit:3.8.2'
    testRuntimeOnly 'junit:junit:4.13.2'
}

BuildIdentifierProjectComponentSelector方法弃用

以下方法BuildIdentifier已被弃用:

  • getName()

  • isCurrentBuild()

您可以使用这些方法来区分具有相同名称但来自不同构建的不同项目组件。然而,对于某些复合构建设置,这些方法无法提供足够的信息来保证唯一性。

这些方法的当前用法应迁移到BuildIdentifier.getBuildPath().

同样,该方法ProjectComponentSelector.getBuildName()已被弃用。代替使用ProjectComponentSelector.getBuildPath()

从 8.0 及更早版本升级

CACHEDIR.TAG 文件在全局缓存目录中创建

Gradle 现在会CACHEDIR.TAG在某些全局缓存目录中发出一个文件,如directory_layout.html中指定的。

这可能会导致某些工具不再搜索或备份这些目录。要禁用它,请在 Gradle 用户主页的init 脚本中使用以下代码:

init.gradle.kts
beforeSettings {
    caches {
        // Disable cache marking for all caches
        markingStrategy.set(MarkingStrategy.NONE)
    }
}
init.gradle
beforeSettings { settings ->
    settings.caches {
        // Disable cache marking for all caches
        markingStrategy = MarkingStrategy.NONE
    }
}

重命名配置缓存选项

在此版本中,配置缓存功能从孵化状态提升为稳定状态,因此,在功能文档中最初提到的所有属性(unsafe其名称中有一部分,例如org.gradle.unsafe.configuration-cache)都被重命名,在某些情况下,只需删除该unsafe位即可。

孵化财产 最终财产

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

请注意,在此版本中继续保留原始org.gradle.unsafe.configuration-cache…​属性,如果使用它们,则不会产生警告,但它们将在未来版本中被弃用并删除。

潜在的重大变化

Kotlin DSL 脚本发出编译警告

来自 Kotlin DSL 脚本的编译警告将打印到控制台输出。例如,在 Kotlin DSL 中使用已弃用的 API 将在每次编译脚本时发出警告。

如果您正在使用 Gradle 构建的控制台输出,这可能是一个重大更改。

kotlin-dsl使用应用的插件配置 Kotlin 编译器选项

如果您在应用了kotlin-dsl插件的项目上配置自定义 Kotlin 编译器选项,您可能会遇到重大更改。

在以前的 Gradle 版本中,该插件在afterEvaluate {}kotlin-dsl上添加了所需的编译器参数。现在 Kotlin Gradle 插件提供了惰性配置属性,我们的插件转而直接向惰性属性添加所需的编译器参数。因此,如果您设置了插件,那么现在构建会失败,因为其所需的编译器参数已被您的配置覆盖。kotlin-dslfreeCompilerArgskotlin-dsl

build.gradle.kts
plugins {
    `kotlin-dsl`
}

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

使用上面的配置,您将遇到以下构建失败:

* 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.

您必须将其更改为将自定义编译器参数添加到 Kotlin Gradle 插件的惰性配置属性中,以便将它们附加到插件所需的参数中kotlin-dsl

build.gradle.kts
plugins {
    `kotlin-dsl`
}

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

如果您已经添加freeCompilerArgs而不是设置其值,那么您不应该遇到构建失败。

引入的新 API 可能与现有 Gradle DSL 代码发生冲突

当将新属性或方法添加到 Gradle DSL 中的现有类型时,它可能会与用户代码中已使用的名称发生冲突。

当发生名称冲突时,一种解决方案是在用户代码中重命名该元素。

这是 8.1 中添加的 API 的非详尽列表,可能会导致与现有用户代码发生名称冲突。

启用配置缓存后,不再允许在配置时使用不受支持的 API 启动外部进程

自 Gradle 7.5 起,仅当启用了功能预览时Project.exec,使用、Project.javaexec和 标准 Java 和 Groovy API 在配置时运行外部进程才会被视为错误。随着 Gradle 8.1 中配置缓存升级为稳定功能,无论功能预览状态如何,都会检测到此错误。配置缓存章节提供了更多详细信息,可帮助迁移到新的基于提供程序的 API,以便在配置时执行外部进程。STABLE_CONFIGURATION_CACHE

不使用配置缓存或仅在执行时启动外部进程的构建不受此更改的影响。

弃用

改变核心插件配置使用

配置的允许使用在创建后应该是不可变的。不推荐更改 Gradle 核心插件创建的配置上允许的用法。这包括调用以下任何Configuration方法:

  • setCanBeConsumed(boolean)

  • setCanBeResolved(boolean)

这些方法现在会对这些配置发出弃用警告,但某些特殊情况除外,这些特殊情况考虑到流行插件的现有行为。此规则尚不适用于分离的配置或在构建脚本和第三方插件中创建的配置。调用或尚未弃用setCanBeConsumed(false), 以避免在使用选定的流行第三方插件时发出警告。apiElementsruntimeElements

此更改是一项更大的持续努力的一部分,旨在使配置的预期行为更加一致和可预测,并在 Gradle 的这一领域进一步提高速度和内存。

Gradle 9.0 中将删除创建后更改配置允许使用的功能。

保留的配置名称

配置名称“detachedConfiguration”和“detachedConfigurationX”(其中 X 是任意整数)保留供创建分离配置时内部使用。

使用这些名称创建非分离配置的功能将在 Gradle 9.0 中删除。

JavaPluginExtension在不存在组件java的情况下调用 select 方法

从 Gradle 8.1 开始,不推荐在JavaPluginExtension不存在默认组件的情况下调用以下任何方法:java

  • withJavadocJar()

  • withSourcesJar()

  • consistentResolution(Action)

java组件由 添加JavaPlugin,它由任何 Gradle JVM 插件应用,包括:

  • java-library

  • application

  • groovy

  • scala

从 Gradle 9.0 开始,在不存在默认组件的情况下调用上述任何方法java都会出错。

WarPlugin#configureConfiguration(ConfigurationContainer)

从 Gradle 8.1 开始,WarPlugin#configureConfiguration(ConfigurationContainer)不推荐使用调用。此方法旨在供内部使用,从未打算用作公共接口的一部分。

从 Gradle 9.0 开始,该方法将被删除而不进行替换。

依赖自定义测试任务的约定

默认情况下,应用java插件时,testClassesDirs`and `classpath所有Test任务具有相同的约定。除非另有更改,否则默认行为是通过使用套件test TestSuite配置任务来执行默认测试。此行为将在 Gradle 9.0 中删除。classpathtestClassesDirstest

虽然此现有默认行为对于在不同环境下执行默认单元测试套件的用例是正确的,但它不支持执行完全独立的测试集的用例。

如果您希望继续包含这些测试,请使用以下代码来避免 8.1 中的弃用警告,并为 9.0 中的行为更改做好准备。或者,考虑迁移到测试套件。

build.gradle.kts
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 })
}
build.gradle
tasks.myTestTask {
    testClassesDirs = testing.suites.test.sources.output.classesDirs
    classpath = testing.suites.test.sources.runtimeClasspath
}

填充发布后修改 Gradle 模块元数据

现在不推荐在从其组件填充 Maven 或 Ivy 发布更改GMM(例如,更改组件配置变体) 。该功能将在 Gradle 9.0 中删除。

如果调用以下方法,则可能会出现出版物的急切人口:

以前,以下代码不会生成警告,但会在已发布的工件之间造成不一致:

build.gradle.kts
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() }
build.gradle
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() }

在此示例中,Maven 和 Ivy 出版物将包含项目的主要 JAR 工件,而 GMM模块文件将省略它们。

在 JVM 版本 6 和 7 上运行测试

不推荐在 8 之前的 JVM 版本上运行 JVM 测试。在这些版本上进行测试将在 Gradle 9.0 中成为错误

应用使用 Gradle < 6.0 发布的 Kotlin DSL 预编译脚本

不推荐使用使用 Gradle < 6.0 发布的 Kotlin DSL 预编译脚本。请使用 Gradle >= 6.0 发布的插件版本。

kotlin-dsl与 Kotlin Gradle 插件 < 1.8.0 一起应用

kotlin-dsl不推荐将 与 Kotlin Gradle 插件 < 1.8.0 一起应用。请让 Gradle 通过从构建逻辑中kotlin-dsl删除任何显式版本约束来控制版本。kotlin-dsl这将使kotlin-dsl插件决定使用哪个版本的 Kotlin Gradle 插件。如果您明确声明构建逻辑使用哪个版本的 Kotlin Gradle 插件,请将其更新到 >= 1.8.0。

访问Kotlin 脚本块中的依赖版本目录librariesbundles从依赖版本目录访问plugins {}

不推荐在 Kotlin 脚本块中访问依赖版本目录librariesbundles从依赖版本目录访问。plugins {}请仅使用块中依赖版本目录中的versions或。pluginsplugins {}

ValidatePlugins在没有 Java 工具链的情况下使用任务

不推荐使用ValidatePlugins类型的任务而不应用Java Toolchains插件,这将在 Gradle 9.0 中成为错误。

为了避免出现此警告,请将插件应用到您的项目中:

build.gradle.kts
plugins {
    id("jvm-toolchains")
}
build.gradle
plugins {
    id 'jvm-toolchains'
}

Java 工具链插件由Java 库插件或其他 JVM 插件自动应用。因此,您可以将其中任何一个应用到您的项目中,它将修复警告。

包中已弃用的成员org.gradle.util现在报告其弃用情况

这些成员将在 Gradle 9.0 中删除。

  • WrapUtil.toDomainObjectSet(…​)

  • GUtil.toCamelCase(…​)

  • GUtil.toLowerCase(…​)

  • ConfigureUtil

已弃用的 JVM 供应商 IBM Semeru

枚举常量JvmVendorSpec.IBM_SEMERU现已弃用,并将在 Gradle 9.0 中删除。

请将其替换为等效项,JvmVendorSpec.IBM以避免在下一个主要版本发布中出现警告和潜在错误。

设置自定义构建布局StartParameterGradleBuild

之前在 Gradle 7.1 中弃用相关行为之后,现在也弃用了相关StartParameterGradleBuild属性。这些属性将在 Gradle 9.0 中删除。

已弃用在GradleBuild任务中使用buildFile属性设置自定义构建文件。

请使用dir属性来指定嵌套构建的根目录。或者,考虑使用GradleBuild任务的推荐替代方案之一,如避免使用 GradleBuild 任务类型部分中的建议。

使用StartParameter方法setBuildFile(File)setSettingsFile(File)设置自定义构建布局以及对应的 getter getBuildFile()getSettingsFile()已被弃用。

请使用设置和构建文件的标准位置:

  • 设置文件位于构建的根目录中

  • 每个子项目根目录下的构建文件

已弃用 org.gradle.cache.cleanup 属性

org.gradle.cache.cleanupGradle User Home 下的属性已gradle.properties被弃用。请使用缓存清理 DSL来禁用或修改清理配置。

由于旧版本的 Gradle 可能仍然需要该org.gradle.cache.cleanup属性,因此该属性可能仍然存在,并且只要它也是通过 DSL 配置的,就不会打印弃用警告。 DSL 值始终优先于org.gradle.cache.cleanup属性。如果所需的配置是禁用旧版本 Gradle 的清理(使用org.gradle.cache.cleanup),但要使用 Gradle 8 或更高版本的 Gradle 版本的默认值启用清理,则清理应配置为使用Cleanup.DEFAULT

cache-settings.gradle
if (GradleVersion.current() >= GradleVersion.version('8.0')) {
    apply from: "gradle8/cache-settings.gradle"
}
cache-settings.gradle.kts
if (GradleVersion.current() >= GradleVersion.version("8.0")) {
    apply(from = "gradle8/cache-settings.gradle")
}
gradle8/cache-settings.gradle
beforeSettings { settings ->
    settings.caches {
        cleanup = Cleanup.DEFAULT
    }
}
gradle8/cache-settings.gradle.kts
beforeSettings {
    caches {
        cleanup.set(Cleanup.DEFAULT)
    }
}

不推荐使用相对路径来指定 Java 可执行文件

使用相对文件路径指向 Java 可执行文件现已被弃用,并且在 Gradle 9 中将成为错误。这样做是为了减少对此类相对路径应解析的内容的混淆。

Task.getConvention()Task.getExtensions()任务操作调用

现在已弃用在执行时从任务操作调用Task.getConvention()Task.getExtensions(),并且在 Gradle 9.0 中将出现错误。

有关如何将这些用法迁移到配置缓存支持的 API 的详细信息,请参阅配置缓存章节。

不推荐在未执行测试时成功运行测试任务

在没有执行测试时成功运行Test任务现在已被弃用,并且在 Gradle 9 中将成为错误。请注意,当不存在测试源时这不是错误,在这种情况下,任务test将被简单地跳过。仅当存在测试源但未选择执行测试时才会出现错误。对此进行更改是为了避免由于错误配置而导致测试运行意外成功。

IDE 集成的变化

plugins {}不再需要使用版本目录来解决Kotlin DSL 块中显示的误报错误

块中插件别名的版本目录访问器plugins {}不再在 IntelliJ IDEA 和 Android Studio Kotlin 脚本编辑器中显示为错误。

如果您使用@Suppress("DSL_SCOPE_VIOLATION")注释作为解决方法,现在可以将其删除。

如果您曾经使用Gradle Libs Error Suppressor IntelliJ IDEA 插件,现在可以将其卸载。

将 Gradle 升级到 8.1 后,您需要清除 IDE 缓存并重新启动。

另请参阅上面 Kotlin DSL中版本目录的已弃用用法plugins {}