本章提供了将 Gradle 7.x 构建迁移到 Gradle 8.0 所需的信息。要从 Gradle 6.x 迁移,请先参阅旧版迁移指南

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

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

    Deprecations View in a Build Scan

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

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

  2. 更新您的插件。

    某些插件将在此新版 Gradle 中失效,例如因为它们使用了已删除或更改的内部 API。上一步将通过在插件尝试使用已弃用的 API 部分时发出弃用警告来帮助您识别潜在问题。

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

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

从 7.6 及更早版本升级

现在成为错误的警告

在包含的构建中引用带有 finalizedBymustRunAftershouldRunAfter 的任务

使用以下任何方法引用包含在包含构建中的任务现在会导致执行时错误

  • finalizedBy

  • mustRunAfter

  • shouldRunAfter

从没有支持文件的资源创建 TAR 树

不再支持从没有支持文件的资源创建 TAR 树。相反,将资源转换为文件,并在文件上使用 project.tarTree()。有关更多信息,请参阅从没有支持文件的资源创建 TAR 树

使用无效的 Java 工具链规范

不再支持使用无效的 Java 工具链规范。通过确保在所有工具链规范上设置语言版本,可以避免相关的构建错误。有关更多信息,请参阅用户手册

在未配置仓库的情况下使用自动工具链下载

不再支持在未明确提供要使用的仓库的情况下自动工具链下载。有关更多信息,请参阅用户手册

设置测试框架选项后更改测试框架现在会出错

配置 Java、Groovy 和 Scala 项目的内置测试任务时,Gradle 不再允许您在配置选项后更改 Test 任务使用的测试框架。这已弃用,因为它在某些情况下会静默丢弃配置。

以下代码示例现在会产生错误

test {
   options {
   }

   useJUnitPlatform()
}

相反,您可以

test {
   // select test framework before configuring options
   useJUnitPlatform()
   options {
   }
}

此外,多次将测试框架设置为相同框架现在会累积可能在框架上设置的任何选项。以前,每次设置框架时,都会导致框架选项被覆盖。

以下代码现在会导致 "foo" 和 "bar" 标签都包含在 test 任务中

test {
   useJUnitPlatform {
        includeTags("foo")
   }
}
tasks.withType(Test).configureEach {
   // previously, this would overwrite the included tags to only include "bar"
   useJUnitPlatform {
        includeTags("bar")
   }
}

已删除的 API

旧版 ArtifactTransform API

旧版 ArtifactTransform API 已被删除。有关更多信息,请参阅注册扩展 ArtifactTransform 的构件转换

旧版 IncrementalTaskInputs API

旧版 IncrementalTaskInputs API 已被删除。有关更多信息,请参阅IncrementalTaskInputs 类型已弃用。此更改也影响 Kotlin Gradle 插件和 Android Gradle 插件。使用 Gradle 8.0,您应该使用 Kotlin Gradle 插件 1.6.10 或更高版本,以及 Android Gradle 插件 7.3.0 并设置 android.experimental.legacyTransform.forceNonIncremental=true 属性或更高版本。

旧版 AntlrSourceVirtualDirectory API

旧版 AntlrSourceVirtualDirectory API 已被删除。此更改会影响 antlr 插件。在 Gradle 8.0 及更高版本中,请改用 AntlrSourceDirectorySet 源集扩展。

JvmPluginsHelper

JvmPluginsHelper 类中已弃用的 configureDocumentationVariantWithArtifact 方法已删除,该方法不需要 FileResolver。这是一个内部 API,但可能已被插件访问。请改向此方法的重载版本提供 FileResolver

Groovydoc API 清理

Groovydoc 任务类型中已弃用的 isIncludePrivate 属性已删除。请改用 access 属性以及 GroovydocAccess#PRIVATE 常量。

JavaApplication API 清理

JavaApplication 接口中已弃用的 mainClassName 属性已删除。请改用 mainClass 属性。

DefaultDomainObjectSet API 清理

已弃用的 DefaultDomainObjectSet(Class) 构造函数已删除。这是一个内部 API,但可能已被插件使用。

JacocoPluginExtension API 清理

JacocoPluginExtension 中已弃用的 reportsDir 属性已删除。请改用 reportsDirectory 属性。

DependencyInsightReportTask API 清理

DependencyInsightReportTask 任务类型中已弃用的 legacyShowSinglePathToDependnecy 属性已删除。请改用 showSinglePathToDependency 属性。

Report 和 TestReport API 清理

Report 类型中已弃用的 destinationenabled 属性已删除。请改用 outputLocationrequired 属性。

TestReport 任务类型中已弃用的 testResultDirs 属性已删除。请改用 testResults 属性。

JacocoMerge 任务已删除

已弃用的 JacocoMerge 任务类型已删除。相同的功能在 JacocoReport 任务上也可用。

JavaExec API 清理

JavaExec 任务类型中已弃用的 main 属性已删除。请改用 mainClass 属性。

AbstractExecTask API 清理

AbstractExecTask 任务类型中已弃用的 execResult getter 属性已删除。请改用 executionResult getter 属性。

AbstractTestTask API 清理

AbstractTestTask 任务类型中已弃用的 binResultsDir 属性已删除。请改用 binaryResultsDirectory 属性。

SourceDirectorySet API 清理

SourceDirectorySet 类型中已弃用的 outputDir 属性已删除。请改用 destinationDirectory 属性。

VersionCatalog API 清理

VersionCatalog 类型中已弃用的 findDependency(String) 方法和 dependencyAliases 属性已删除。请改用 findLibrary(String) 方法和 libraryAliases 属性。

VersionCatalogBuilder 类型中已弃用的 alias(String) 方法已删除。请改用 library(String, String, String)plugin(String, String) 方法。

WorkerExecutor API 清理

WorkerExecutor 接口中已弃用的 submit(Class, Action) 方法已删除。请改用 noIsolation()classLoaderIsolation()processIsolation() 方法获取 WorkQueue,并在 WorkQueue 上使用 submit(Class, Action) 方法。

DependencySubstitution API 清理

DependencySubstitution 类型的内部 Substitution 类型中已弃用的 with(ComponentSelector) 方法已删除。请改用 using(ComponentSelector) 方法。

AbstractArchiveTask API 清理

AbstractArchiveTask 任务类型中已弃用的 appendixarchiveNamearchivePathbaseNameclassifierdestinationDirextensionversion 属性已删除。请改用 archiveAppendixarchiveFileNamearchiveFilearchiveBaseNamearchiveClassifierdestinationDirectoryarchiveExtensionarchiveVersion 属性。

AbstractCompile API 弃用

AbstractCompile 中先前已弃用的 destinationDir 属性仍然弃用,现在使用时将发出弃用警告。它现在计划在 Gradle 9.0 中删除。请改用 destinationDirectory 属性。

ResolvedComponentResult API 清理

ResolvedComponentResult 接口中已弃用的 getVariant 方法已删除。请改用 getVariants 方法。

代码质量插件 API 清理

CheckstyleCodeNarcPmd 任务类型中已弃用的 antBuilder 属性已删除。请改用 Project 类型的 ant 属性。

Usage API 清理

Usage 类型中已弃用的公共字段 JAVA_API_CLASSESJAVA_API_JARSJAVA_RUNTIME_CLASSESJAVA_RUNTIME_JARSJAVA_RUNTIME_RESOURCES 已删除。这些值在内部 JavaEcosystemSupport 类中可用,以兼容以前发布的模块,但不应用于任何新发布。

ExternalDependency API 清理

ExternalDependency 接口中已弃用的 setForce(boolean) 方法已删除。请改用 version(Action) 方法配置严格版本。

Kotlin DSL 中已删除的 build-scan 方法

已弃用的 build-scan 插件应用方法已从 Kotlin DSL 中删除。请改用 gradle-enterprise 方法。

Kotlin DSL 中已删除的配置扩展方法

Kotlin DSL 为 NamedDomainObjectProvider<Configuration> 添加了专门的扩展方法,当按名称查找配置时可用。这些扩展允许构建在使用 NamedDomainObjectProvider<Configuration> 实例时直接访问 Configuration 的某些属性

configurations.compileClasspath.files // equivalent to configurations.compileClasspath.get().files
configurations.compileClasspath.singleFile // equivalent to configurations.compileClasspath.get().singleFile

所有这些扩展都已从 API 中删除,但这些方法对于针对旧版 Gradle 编译的插件仍然可用。

  • NamedDomainObjectProvider<Configuration>.addToAntBuilder

  • NamedDomainObjectProvider<Configuration>.all

  • NamedDomainObjectProvider<Configuration>.allArtifacts

  • NamedDomainObjectProvider<Configuration>.allDependencies

  • NamedDomainObjectProvider<Configuration>.allDependencyConstraints

  • NamedDomainObjectProvider<Configuration>.artifacts

  • NamedDomainObjectProvider<Configuration>.asFileTree

  • NamedDomainObjectProvider<Configuration>.asPath

  • NamedDomainObjectProvider<Configuration>.attributes

  • NamedDomainObjectProvider<Configuration>.buildDependencies

  • NamedDomainObjectProvider<Configuration>.contains

  • NamedDomainObjectProvider<Configuration>.copy

  • NamedDomainObjectProvider<Configuration>.copyRecursive

  • NamedDomainObjectProvider<Configuration>.defaultDependencies

  • NamedDomainObjectProvider<Configuration>.dependencies

  • NamedDomainObjectProvider<Configuration>.dependencyConstraints

  • NamedDomainObjectProvider<Configuration>.description

  • NamedDomainObjectProvider<Configuration>.exclude

  • NamedDomainObjectProvider<Configuration>.excludeRules

  • NamedDomainObjectProvider<Configuration>.extendsFrom

  • NamedDomainObjectProvider<Configuration>.fileCollection

  • NamedDomainObjectProvider<Configuration>.files

  • NamedDomainObjectProvider<Configuration>.filter

  • NamedDomainObjectProvider<Configuration>.getTaskDependencyFromProjectDependency

  • NamedDomainObjectProvider<Configuration>.hierarchy

  • NamedDomainObjectProvider<Configuration>.incoming

  • NamedDomainObjectProvider<Configuration>.isCanBeConsumed

  • NamedDomainObjectProvider<Configuration>.isCanBeResolved

  • NamedDomainObjectProvider<Configuration>.isEmpty

  • NamedDomainObjectProvider<Configuration>.isTransitive

  • NamedDomainObjectProvider<Configuration>.isVisible

  • NamedDomainObjectProvider<Configuration>.minus

  • NamedDomainObjectProvider<Configuration>.outgoing

  • NamedDomainObjectProvider<Configuration>.plus

  • NamedDomainObjectProvider<Configuration>.resolutionStrategy

  • NamedDomainObjectProvider<Configuration>.resolve

  • NamedDomainObjectProvider<Configuration>.resolvedConfiguration

  • NamedDomainObjectProvider<Configuration>.setDescription

  • NamedDomainObjectProvider<Configuration>.setExtendsFrom

  • NamedDomainObjectProvider<Configuration>.setTransitive

  • NamedDomainObjectProvider<Configuration>.singleFile

  • NamedDomainObjectProvider<Configuration>.state

  • NamedDomainObjectProvider<Configuration>.withDependencies

您应该优先直接引用 Configuration 中的方法。

潜在的重大更改

JavaForkOptions getJvmArgs()getAllJvmArgs() 返回不可变列表

JavaForkOptions 接口检索的 JVM 参数列表现在是不可变的。

以前,对返回列表的修改会被静默忽略。

可空注解更好地反映了 API 的实际可空性

在某些 API 中,可空性未正确注解,允许 null 或返回 null 的 API 被标记为非 null。在 Java 或 Groovy 中,这种不匹配在编译时不会导致问题。在 Kotlin 中,这种不匹配使得编写有效代码变得困难,因为该语言不允许您传递 null。

一个特别的例子是从 Provider#mapProvider#flatMap 返回 null。在这两个 API 中,Gradle 都允许您返回 null,但在 Kotlin DSL 中,这被认为是非法的。

此更正可能会导致期望非 null 的代码出现编译错误。

插件、任务和扩展类是抽象的

大多数用于插件、任务和扩展的公共类已抽象化。这样做是为了更容易地从 Gradle 的实现中删除样板代码。

受此更改影响的插件也应将其类抽象化。只要通过 ObjectFactory 或其他自动机制(如受管属性)实例化对象,Gradle 就会使用运行时类修饰来实现抽象方法。这些方法永远不应直接实现。

包装器任务配置

如果 gradle-wrapper.properties 包含 distributionSha256Sum 属性,则必须指定一个和。您可以在包装任务配置中或使用 --gradle-distribution-sha256-sum 任务选项指定一个和。

AbstractCodeQualityPlugin 类中的更改

已弃用的 AbstractCodeQualityPlugin.getJavaPluginConvention() 方法在 Gradle 8.0 中已删除。您应该改用 JavaPluginExtension

删除 Gradle worker 的隐式 --add-opens

在 Gradle 8.0 之前,JDK9+ 上的 Gradle worker 通过传递 --add-opens CLI 参数自动打开 JDK 模块 java.base/java.utiljava.base/java.lang。这使得在 Gradle worker 中执行的代码可以对 JDK 内部进行深度反射而不会发出警告或失败。worker 不再使用这些隐式参数。

这会影响所有内部 Gradle worker,它们用于各种任务

  • 代码质量插件(Checkstyle、CodeNarc、Pmd)

  • ScalaDoc

  • AntlrTask

  • JVM 编译器守护进程

  • 通过 Worker API 使用进程隔离执行的任务

任何通过 worker API 对 JDK 内部进行深度反射的工具、扩展或插件中可能会出现新的警告和错误。

这些错误可以通过更新违规代码或依赖项来解决。更新可能包括

  • 代码质量工具

  • 注解处理器

  • 任何使用 worker API 的 Gradle 插件

有关由于此更改可能出现的错误或警告输出的一些示例,请参阅删除测试 worker 的隐式 --add-opens

SourceSet classesDirs 不再依赖整个 SourceSet 作为任务依赖项

在 Gradle 8.0 之前,SourceSetOutput.classesDirs 的任务依赖项包括不生成类文件的任务。这意味着依赖 classesDirs 的任务也将依赖 classesprocessResources 以及添加到 SourceSetOutput 的任何其他任务依赖项。此行为可能是一个错误,因为 classesDirs 属性不包含 processResources 的输出。从 8.0 开始,此隐式依赖项已删除。现在,依赖 classesDirs 只执行直接在类目录中生成文件的任务。

考虑以下构建脚本

plugins {
    id 'java-library'
}
// Task lists all files in the given classFiles FileCollection
tasks.register("listClassFiles", ListClassFiles) {
    classFiles.from(java.sourceSets.main.output.classesDirs)
}

以前,listClassFiles 任务依赖 compileJavaprocessResourcesclasses。现在,只有 compileJavalistClassFiles 的任务依赖项。

如果构建中的任务依赖于以前的行为,则可以改用整个 SourceSetOutput 作为输入,它包含所有类和资源。

如果不可行,可以通过向 classesDirs 添加更多任务依赖项来恢复以前的行为

java {
    sourceSets {
        main {
            output.classesDirs.builtBy(output)
        }
    }
}

支持的 Kotlin Gradle 插件最低版本已更改

Gradle 7.x 支持 Kotlin Gradle 插件 1.3.72 及更高版本。Kotlin Gradle 插件 1.6.21 以上版本未在 Gradle 7.x 中测试。Gradle 8.x 支持 Kotlin Gradle 插件 1.6.10 及更高版本。您可以通过修改 Kotlin 编译任务中的语言版本和 API 版本设置来使用更低的 Kotlin 语言版本。

支持的 Android Gradle 插件最低版本已更改

Gradle 7.x 支持 Android Gradle 插件 (AGP) 4.1 及更高版本。AGP 7.3 以上版本未在 Gradle 7.x 中测试。Gradle 8.x 支持 AGP 8 及更高版本。如果您配置以下属性,Gradle 8.x 支持 AGP 7.3 及更高版本

android.experimental.legacyTransform.forceNonIncremental=true

AntBuilder 父类更改

以前,org.gradle.api.AntBuilder 扩展了已弃用的 groovy.util.AntBuilder 类。它现在扩展 groovy.ant.AntBuilder

PluginDeclaration 不可序列化

org.gradle.plugin.devel.PluginDeclaration 不再可序列化。如果需要序列化,可以将其转换为自己的可序列化类。

Gradle 在最新检查中不使用等于来比较序列化值

Gradle 现在在最新检查中不尝试使用等于来比较序列化值。有关更多信息,请参阅在最新检查中依赖等于已弃用

Gradle 7.x 中引入的任务和转换验证警告现在已成为错误

Gradle 在 Gradle 7.x 系列中引入了额外的任务和构件转换验证警告。这些警告现在在 Gradle 8.0 中已成为错误,并将导致构建失败。

变成错误的警告

Gradle 不再忽略带有 @SkipWhenEmpty 的文件树的空目录

以前,Gradle 会检测用 @SkipWhenEmpty 注解的输入文件集合是否仅由文件树组成,然后自动忽略目录。要在 Gradle 8.0 及更高版本中忽略目录,输入属性需要明确使用 @IgnoreEmptyDirectories 注解。有关更多信息,请参阅文件树和空目录处理

Java 9 和 Java 10 的 JavaVersion 格式已更改

JavaVersion 的字符串格式已更改,以匹配官方 Java 版本控制。从 Java 9 开始,语言版本不得包含 1. 前缀。这会影响 JavaCompile 任务和 JavaExtension 上的 sourceCompatiblitytargetCompatibility 属性的格式。从字符串解析 JavaVersion 时仍支持旧格式。

Gradle 7.6

Gradle 8.0

1.8

1.8

1.9

9

1.10

10

11

11

预编译脚本插件默认使用严格的 Kotlin DSL 访问器生成

在预编译脚本插件中,如果插件应用失败,类型安全的 Kotlin DSL 访问器生成现在会使构建失败。

从 Gradle 7.6 开始,构建可以使用 org.gradle.kotlin.dsl.precompiled.accessors.strict 系统属性启用此行为。此行为现在是默认行为。该属性已弃用,应删除其用法。您可以在下方找到有关此属性的更多信息。

初始化脚本应用于 buildSrc 构建

现在,使用 --init-script 指定的初始化脚本应用于 buildSrc 构建。在以前的版本中,这些脚本应用于包含的构建,但不应用于 `buildSrc 构建。

现在 buildSrc 和包含的构建的行为一致。

Gradle 不再为 buildSrc 构建运行 build 任务

当 Gradle 构建 buildSrc 的输出时,它只运行生成该输出的任务,通常是 jar 任务。在以前的版本中,Gradle 会运行 build 任务。

这意味着 buildSrc 及其子项目的测试不会自动构建和执行,现在必须明确请求。

现在 buildSrc 和包含的构建的行为一致。

您可以像在包含的构建中的项目一样运行 buildSrc 的测试,例如通过运行 gradle buildSrc:build

buildFinished { } buildSrc 钩子在所有任务执行后运行

buildSrcbuildFinished {} 钩子现在在所有任务完成后运行。在以前的版本中,此钩子会在 buildSrc 的任务完成后立即运行,并在任何请求的任务开始之前运行。

现在 buildSrc 和包含的构建的行为一致。

包含的构建路径更改

为了更好地处理嵌套包含构建名称之间的冲突,Gradle 现在使用包含构建的目录层次结构来分配构建路径。如果您在嵌套包含构建中从命令行运行任务,则可能需要调整调用。

例如,如果您有以下层次结构

.
├── settings.gradle.kts
└── nested
    ├── settings.gradle.kts
    └── nestedNested
        └── settings.gradle.kts
settings.gradle.kts
includeBuild("nested")
nested/settings.gradle.kts
includeBuild("nestedNested")
.
├── settings.gradle
└── nested
    ├── settings.gradle
    └── nestedNested
        └── settings.gradle
settings.gradle
includeBuild("nested")
nested/settings.gradle
includeBuild("nestedNested")

在 Gradle 8.0 之前,您运行 gradle :nestedNested:compileJava。在 Gradle 8.0 中,调用更改为 gradle :nested:nestedNested:compileJava

使用 eclipse wtp 插件添加 jst.ejb 现在会移除 jst.utility 方面

eclipse wtp 插件向 Java 项目添加 jst.utility 方面。现在,添加 jst.ejb 方面会隐式移除 jst.utility 方面

eclipse {
    wtp {
        facet {
            facet name: 'jst.ejb', version: '3.2'
        }
    }
}

简化 PMD 自定义规则配置

以前,您必须明确配置 PMD 以忽略默认规则 ruleSets = []。在 Gradle 8.0 中,将 ruleSetConfigruleSetFiles 设置为非空值会隐式忽略默认规则。

Report getOutputLocation 返回类型从 Provider 更改为 Property

Report 的 outputLocation 属性现在返回 Property<? extends FileSystemLocation> 类型的值。以前,outputLocation 返回 Provider<? extends FileSystemLocation> 类型的值。

此更改使 Report API 在内部更具一致性,并允许更规范地配置报告任务。

以前已弃用的用法

tasks.named('test') {
    reports.junitXml.setDestination(layout.buildDirectory.file('reports/my-report-old').get().asFile) // DEPRECATED
}

可以替换为

tasks.named('test') {
    reports.junitXml.outputLocation = layout.buildDirectory.dir('reports/my-report')
}

许多内置和自定义报告,例如 JUnit 使用的报告,都实现了此接口。针对早期版本 Gradle 编译的包含旧方法签名的插件可能需要重新编译才能与包含新签名的较新版本 Gradle 一起使用。

外部插件验证插件已移除

孵化中的插件 ExternalPluginValidationPlugin 已被删除。请使用 java-gradle-pluginvalidatePlugins 任务来验证开发中的插件。

可重现档案可能与过去版本不同

Gradle 将用于创建档案的压缩库从基于 Ant 的库更改为 Apache Commons Compress™。因此,由相同内容创建的档案与使用旧库创建的旧版本档案相比,字节级可能不再相同。

升级到 Kotlin 1.8.10

嵌入式 Kotlin 已更新至 Kotlin 1.8.10。另请参阅 Kotlin 1.8.0 发布说明。有关更多信息,请参阅 Kotlin 的发布说明

将 Kotlin DSL 更新到 Kotlin API 级别 1.8

以前,Kotlin DSL 使用 Kotlin API 级别 1.4。从 Gradle 8.0 开始,Kotlin DSL 使用 Kotlin API 级别 1.8。此更改带来了自 Kotlin 1.4.0 以来对 Kotlin 语言和标准库所做的所有改进。

有关此升级中的破坏性更改和非破坏性更改的信息,请参阅以下 Kotlin 文档链接

请注意,Kotlin Gradle 插件 1.8.0 开始使用 Java 工具链。建议您配置工具链,而不是在 Kotlin 项目中定义 Java sourceCompatibility/targetCompatibility

另请注意,Kotlin Gradle 插件 1.8.0 引入了具有惰性配置属性的 compilerOptions,以替代不支持惰性配置的 kotlinOptions。建议您使用 compilerOptions 而不是 kotlinOptions 配置 Kotlin 编译。

kotlinDslPluginOptions.jvmTarget 已弃用

以前,您可以使用 kotlinDslPluginOptions.jvmTarget 来配置在使用 kotlin-dsl 插件时应使用哪个 JVM 目标进行编译。

从 Gradle 8.0 开始,kotlinDslPluginOptions.jvmTarget 已弃用。您应该改为配置 Java 工具链

如果您已经配置了 Java 工具链并且 kotlinDslPluginOptions.jvmTarget 未设置,那么 Gradle 8.0 现在将使用 Java 工具链作为 JVM 目标,而不是以前的默认目标 (1.8)。

Java Base Plugin 现在设置 Jar、War 和 Ear 目标目录默认值

以前,base 插件将 Jar、War 和 Ear 任务的 destinationDirectory 配置为 BasePluginExtension#getLibsDirectory 指定的目录。在 Gradle 8.0 中,java-base 处理此配置。对于已直接或间接通过 javaapplicationjava-library 或其他 JVM 生态系统插件应用 java-base 插件的项目,无需进行任何更改。

不应使用 Upload 任务

Upload 任务仍然弃用,现在计划在 Gradle 9.0 中删除。虽然此类型仍然存在,但它不再具有功能,运行后将抛出异常。它仅保留以避免破坏插件。请改用 maven-publishivy-publish 插件中的任务。

不再允许将配置作为依赖项

dependencies DSL 块中添加配置作为依赖项,或以编程方式使用 DependencyHandler 类的 doAdd(Configuration, Object, Closure) 方法,不再允许,并且将抛出异常。要复制此行为的许多方面,请改用 Configuration 上的 extendsFrom(Configuration) 方法扩展配置。

已弃用的消费配置现在不可消费

以下配置从未打算用于消费

  • AntlrPlugin 创建的 antlr 配置

  • ScalaBasePlugin 创建的 zinc 配置

  • WarPlugin 创建的 providedCompileprovidedRuntime 配置

这些配置已弃用以供消费,现在不再可消费。尝试消费它们将导致错误。

相同的可消费配置现在会出错

如果一个项目有多个具有相同属性和功能声明的可消费配置,则在发布或解析该项目作为依赖项时,构建将失败。这以前已弃用

outgoingVariants 报告将针对受影响的配置发出警告。

基于工具链的 JVM 项目任务

从 Gradle 8.0 开始,所有具有工具链支持的核心 Java 任务现在都无条件地使用工具链。如果应用了 JavaBasePlugin,则任务上工具属性的约定值由 java 扩展上配置的工具链定义。如果没有明确配置工具链,则使用与运行 Gradle 的 JVM 对应的工具链。

类似地,Groovy 和 Scala 插件中的任务也依赖于工具链来确定它们在哪个 JVM 上执行。

Scala 编译目标

根据上述工具链更改,Scala 编译任务现在始终提供 targetrelease 参数。具体参数和值取决于工具链使用情况(或不使用)和 Scala 版本。

有关详细信息,请参阅Scala 插件文档

插件发布插件中的 pluginBundle 已删除

Gradle 8 不再支持 pluginBundle 扩展。其功能已合并到 gradlePlugin 块中。这些更改需要最新版本的插件发布插件(1.0.+)。有关配置插件发布的文档可以在门户用户手册中找到。

从 7.5 及更早版本升级

AttributeSchema.setAttributeDisambiguationPrecedence(List)AttributeSchema.getAttributeDisambiguationPrecedence() 方法现在接受并返回 List 而不是 Collection,以更好地表明这些集合中元素的顺序很重要。

严格的 Kotlin DSL 预编译脚本插件访问器生成

预编译脚本插件的类型安全 Kotlin DSL 访问器生成在默认情况下不会在预编译脚本中请求的插件应用失败时使构建失败。由于原因可能是环境问题和向后兼容性,此行为尚未更改。

早在 Gradle 7.1 中,负责访问器生成的 :generatePrecompiledScriptPluginAccessors 任务默认已被标记为不可缓存。引入了 org.gradle.kotlin.dsl.precompiled.accessors.strict 系统属性,以提供一种选择更严格操作模式的选项,该模式在插件应用失败时使构建失败,并为该任务启用构建缓存。

从 Gradle 7.6 开始,Kotlin DSL 预编译脚本插件的非严格访问器生成已弃用。这将在 Gradle 8.0 中更改。严格访问器生成将成为默认行为。要选择严格行为,请将 'org.gradle.kotlin.dsl.precompiled.accessors.strict' 系统属性设置为 true

这可以在构建根目录中的 gradle.properties 文件中持久地实现

systemProp.org.gradle.kotlin.dsl.precompiled.accessors.strict=true

潜在的重大更改

升级到 Kotlin 1.7.10

嵌入式 Kotlin 已更新至 Kotlin 1.7.10

Gradle 不附带 kotlin-gradle-plugin,但升级到 1.7.10 可以带来新版本。例如,当您使用 kotlin-dsl 插件时。

kotlin-gradle-plugin 版本 1.7.10 更改了 KotlinCompile 任务类型的类型层次结构。它不再继承自 AbstractCompile。如果您过去通过 AbstractCompile 选择 Kotlin 编译任务,则需要将其更改为 KotlinCompile

例如,这个

tasks.named<AbstractCompile>("compileKotlin")

需要更改为

tasks.named<KotlinCompile>("compileKotlin")

同样,如果您过去通过 AbstractCompile 过滤任务,您将不再获得 Kotlin 编译任务

tasks.withType<AbstractCompile>().configureEach {
    // ...
}

需要更改为

tasks.withType<AbstractCompile>().configureEach {
    // ...
}
tasks.withType<KotlinCompile>().configureEach {
    // ...
}

升级到 Groovy 3.0.13

Groovy 已更新至 Groovy 3.0.13

由于上一个版本是 3.0.10,因此也包含了 3.0.113.0.12 的更改。

升级到 CodeNarc 3.1.0

CodeNarc 的默认版本已更新至 3.1.0

升级到 PMD 6.48.0

PMD 已更新至 PMD 6.48.0

配置不存在的可执行文件现在会失败

当为 JavaCompileTest 任务明确配置可执行文件时,如果此可执行文件不存在,Gradle 现在将发出错误。过去,任务将使用默认工具链或运行构建的 JVM 执行。

测试套件中依赖项声明的更改

作为演进测试套件的持续努力的一部分,测试套件 dependencies 块中的依赖项声明现在是强类型。这将有助于使这个孵化中的 API 更具可发现性,并且更容易在 IDE 中使用。

在某些情况下,这需要语法更改。例如,以前使用以下语法添加测试套件依赖项的构建脚本

testing {
  suites {
    register<JvmTestSuite>("integrationTest") {
      dependencies {
        implementation(project)
      }
    }
  }
}

现在将无法编译,并显示类似以下消息

None of the following functions can be called with the arguments supplied:
public operator fun DependencyAdder.invoke(dependencyNotation: CharSequence): Unit defined in org.gradle.kotlin.dsl
public operator fun DependencyAdder.invoke(dependency: Dependency): Unit defined in org.gradle.kotlin.dsl
public operator fun DependencyAdder.invoke(files: FileCollection): Unit defined in org.gradle.kotlin.dsl
public operator fun DependencyAdder.invoke(dependency: Provider<out Dependency>): Unit defined in org.gradle.kotlin.dsl
public operator fun DependencyAdder.invoke(externalModule: ProviderConvertible<out MinimalExternalModuleDependency>): Unit defined in org.gradle.kotlin.dsl

要解决此问题,请将对 project 的引用替换为对 project() 的调用

testing {
  suites {
    register<JvmTestSuite>("integrationTest") {
      dependencies {
        implementation(project())
      }
    }
  }
}

受此更改影响的其他语法包括

  • 不能使用 Provider<String> 作为依赖项声明。

  • 不能使用 Map 作为 Kotlin 或 Java 的依赖项声明。

  • 不能直接使用捆绑包作为依赖项声明(implementation(libs.bundles.testing))。请改用 implementation.bundle(libs.bundles.testing)

有关更多信息,请参阅用户指南中 JVM 测试套件插件部分的更新后的声明其他测试套件示例。

弃用

使用无效的 Java 工具链规范现在已弃用

除了 Java 语言版本之外,Java 工具链 DSL 允许配置其他条件,例如特定的供应商或 VM 实现。从 Gradle 7.6 开始,配置其他属性而不指定语言版本的工具链规范被视为无效。无效规范已弃用,并将在 Gradle 8.0 中成为构建错误。

有关工具链配置的更多详细信息,请参阅用户手册

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

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

  • ClosureBackedAction

  • CollectionUtils

  • ConfigureUtil

  • DistributionLocator

  • GFileUtils

  • GradleVersion.getBuildTime()

  • GradleVersion.getNextMajor()

  • GradleVersion.getRevision()

  • GradleVersion.isValid()

  • GUtil

  • NameMatcher

  • NameValidator

  • RelativePathUtil

  • TextUtil

  • SingleMessageLogger

  • VersionNumber

  • WrapUtil

内部 DependencyFactory 已重命名

内部 org.gradle.api.internal.artifacts.dsl.dependencies.DependencyFactory 类型已重命名为 org.gradle.api.internal.artifacts.dsl.dependencies.DependencyFactoryInternal。作为内部类型,它不应被使用,但出于兼容性原因,内部 ClassPathNotation 类型仍然可用。此类型名称已弃用,并将在 Gradle 8.0 中删除。此类型的公共 API 在 DependencyHandler 上,其中包含 localGroovy() 等方法,提供相同的功能。

org.gradle.plugins.ide.idea.model.IdeaModule 中的替换集合

testResourcesDirstestSourcesDirs 字段及其 getter 和 setter 已弃用。请使用现在稳定的 getTestSources()getTestResources() 方法及其各自的 setter。这些新方法返回并由 ConfigurableFileCollection 实例支持,以提高使用灵活性。Gradle 现在在使用这些已弃用方法时发出警告。它们将在 Gradle 的未来版本中删除。

org.gradle.api.tasks.testing.TestReport 中的替换方法

getDestinationDir()setDestinationDir(File) 以及 getTestResultDirs()setTestResultDirs(Iterable) 方法已弃用。请使用现在稳定的 getDestinationDirectory()getTestResults() 方法及其相关的 setter。这些已弃用的元素将在 Gradle 的未来版本中删除。

某些配置块中对外部作用域方法的已弃用隐式引用

在 Gradle 7.6 之前,Groovy 脚本允许在命名容器配置方法中访问根项目配置方法,这些方法会抛出 MissingMethodException。考虑以下代码片段作为此行为的示例

当提供的闭包是配置的无效配置闭包时,Gradle 允许从 configurations 块内访问顶级 repositories 块。在这种情况下,repositories 闭包执行,就像它是在脚本级别调用一样,并创建一个未配置的 repositories 配置

configurations {
    repositories {
        mavenCentral()
    }
    someConf {
        canBeConsumed = false
        canBeResolved = false
    }
}

该行为也适用于不立即执行的闭包。在这种情况下,afterResolve 仅在 resolve 任务运行时执行。distributions 闭包是有效的顶级脚本闭包。但它是配置的无效配置闭包。此示例会立即创建 conf 配置。在 resolve 任务执行期间,distributions 块的执行方式就像它是在脚本级别声明一样

configurations {
    conf.incoming.afterResolve {
        distributions {
            myDist {
                contents {}
            }
        }
    }
}

task resolve {
    dependsOn configurations.conf
    doFirst {
        configurations.conf.files() // Trigger `afterResolve`
    }
}

从 Gradle 7.6 开始,此行为已弃用。从 Gradle 8.0 开始,此行为将被移除。相反,Gradle 将抛出底层 MissingMethodException。为了缓解此更改,请考虑以下解决方案

configurations {
    conf.incoming.afterResolve {
        // Fully qualify the reference.
        project.distributions {
            myDist {
                contents {}
            }
        }
    }
}
configurations {
    conf
}

// Extract the script-level closure to the script root scope.
configurations.conf.incoming.afterResolve {
    distributions {
        myDist {
            contents {}
        }
    }
}

从 7.4 及更早版本升级

IncrementalTaskInputs 类型已弃用

IncrementalTaskInputs 类型用于实现增量任务,即可以优化为对更改输入的子集而不是整个输入运行的任务。此类型存在许多缺点。特别是使用此类型无法确定更改与哪个输入相关联。

您现在应该改用 InputChanges 类型。请参阅用户指南中关于实现增量任务的部分以获取更多详细信息

潜在的重大更改

版本目录只接受一个 TOML 导入文件

使用 from 导入方法时,只接受单个文件。这意味着,解析为多个文件的表示法(例如,当传递多个文件时,Project.files(java.lang.Object…​) 方法)将导致构建失败。

默认工具集成版本更新

eclipse 插件生成的类路径文件已更改

在测试配置中定义的项目依赖项将获得 test=true 类路径属性。JVM 测试套件插件定义的所有源集和依赖项默认也标记为测试代码。您现在可以通过 eclipse 插件 DSL 自定义测试源集和依赖项

eclipse {
    classpath {
        testSourceSets = [sourcesSets.test, sourceSets.myTestSourceSet]
        testConfigurations = [configuration.myTestConfiguration]
    }
}

或者,您可以在 eclipse.classpath.file.whenMerged { } 块中调整或删除类路径属性。

签名插件在使用 GPG 命令时默认使用 gpg 而不是 gpg2

签名插件的默认可执行文件在使用 GPG 命令时gpg2 更改为 gpg。此更改的动机是 GPG 2.x 变得稳定,并且发行版开始迁移,不再链接 gpg2 可执行文件。

为了设置旧默认值,可以在 gradle.properties 中手动定义可执行文件

signing.gnupg.executable=gpg2

mustRunAfter 约束不再被 finalizedBy 依赖项违反

在以前的 Gradle 版本中,常规任务和终结器任务依赖项之间的 mustRunAfter 约束将不会得到遵守。

举一个具体的例子,考虑以下任务图定义

tasks {
    register("dockerTest") {
        dependsOn("dockerUp")     // dependsOn createContainer mustRunAfter removeContainer
        finalizedBy("dockerStop") // dependsOn removeContainer
    }

    register("dockerUp") {
        dependsOn("createContainer")
    }

    register("dockerStop") {
        dependsOn("removeContainer")
    }

    register("createContainer") {
        mustRunAfter("removeContainer")
    }

    register("removeContainer") {
    }
}

相关约束是

  • dockerStopdockerTest 的终结器,因此它必须在 dockerTest 之后运行;

  • removeContainerdockerStop 的依赖项,因此它必须在 dockerStop 之前运行;

  • createContainer 必须在 removeContainer 之后运行;

在 Gradle 7.5 之前,gradle dockerTest 会产生以下执行顺序,违反了 :createContainer:removeContainer 之间的 mustRunAfter 约束

> Task :createContainer UP-TO-DATE
> Task :dockerUp UP-TO-DATE
> Task :dockerTest UP-TO-DATE
> Task :removeContainer UP-TO-DATE
> Task :dockerStop UP-TO-DATE

从 Gradle 7.5 开始,mustRunAfter 约束得到充分遵守,产生以下执行顺序

> Task :removeContainer UP-TO-DATE
> Task :createContainer UP-TO-DATE
> Task :dockerUp UP-TO-DATE
> Task :dockerTest UP-TO-DATE
> Task :dockerStop UP-TO-DATE

Scala Zinc 版本更新至 1.6.1

Zinc 是 Scala 增量编译器,允许 Gradle 始终编译当前文件更改所需的最少文件集。它考虑了正在使用的方法和已更改的方法,这意味着它比仅文件间依赖关系更细粒度。

Zinc 版本已更新至最新可用版本,以受益于所有最新的错误修复。因此,如果您使用 zincVersion 设置,建议将其删除并仅使用默认版本,因为 Gradle 将只能使用设置为 1.6.x 或更高版本的 Zinc 版本编译 Scala 代码。

移除测试 workers 的隐式 --add-opens

在 Gradle 7.5 之前,JDK9+ 上的测试 workers 会自动通过传递 --add-opens CLI 参数打开 JDK 模块 java.base/java.utiljava.base/java.lang。这意味着任何测试都能够对 JDK 内部进行深度反射而不会发出警告或失败。这导致测试不可靠,因为允许代码在生产环境中本应失败时通过。

这些隐式参数已移除,默认不再添加。如果您的代码或任何依赖项在测试执行期间对 JDK 内部进行深度反射,您可能会看到以下行为更改

在 Java 16 之前,会显示新的构建警告。这些新警告会打印到 stderr,但不会导致构建失败

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.ReflectUtils$2 (file:/.../testng-5.12.1.jar) to <method>
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

使用 Java 16 或更高版本,会抛出异常并导致构建失败

// Thrown by TestNG
java.lang.reflect.InaccessibleObjectException: Unable to make <method> accessible: module java.base does not "opens java.lang" to unnamed module @1e92bd61
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
	at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
	at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
    ...

// Thrown by ProjectBuilder
org.gradle.api.GradleException: Could not inject synthetic classes.
	at org.gradle.initialization.DefaultLegacyTypesSupport.injectEmptyInterfacesIntoClassLoader(DefaultLegacyTypesSupport.java:91)
	at org.gradle.testfixtures.internal.ProjectBuilderImpl.getGlobalServices(ProjectBuilderImpl.java:182)
	at org.gradle.testfixtures.internal.ProjectBuilderImpl.createProject(ProjectBuilderImpl.java:111)
	at org.gradle.testfixtures.ProjectBuilder.build(ProjectBuilder.java:120)
	...
Caused by: java.lang.RuntimeException: java.lang.IllegalAccessException: module java.base does not open java.lang to unnamed module @1e92bd61

在大多数情况下,这些错误可以通过更新执行非法访问的代码或依赖项来解决。如果测试中的代码或相关依赖项的最新版本故意执行非法访问,则可以通过手动使用 --add-opens 打开 java.base/java.langjava.base/java.util 模块来恢复旧行为

tasks.withType(Test).configureEach {
    jvmArgs(["--add-opens=java.base/java.lang=ALL-UNNAMED",
             "--add-opens=java.base/java.util=ALL-UNNAMED"]
}

如果您正在开发 Gradle 插件,ProjectBuilder 依赖于 java.base/java.lang 模块中的反射。当应用 java-gradle-plugin 插件时,Gradle 将自动为测试添加适当的 --add-opens 标志。

如果您正在使用 TestNG,版本早于 5.14.6 会执行非法反射。更新到至少 5.14.6 应该可以解决不兼容性。

Checkstyle 任务默认使用工具链并并行执行

Checkstyle 插件现在使用 Gradle worker API 将 Checkstyle 作为外部 worker 进程运行。现在,同一个项目中的多个 Checkstyle 任务可以并行运行。

某些项目需要增加 Checkstyle 可用的内存量,以避免内存不足错误。您可以通过为 Checkstyle 任务设置 maxHeapSize增加 Checkstyle 进程的最大堆大小。默认情况下,该进程将以 512MB 的最大堆大小启动。

我们还建议将 Checkstyle 更新到 9.3 或更高版本。

运行 Checkstyle 时使用相对路径指定的文件丢失

Gradle 7.5 将 Checkstyle 任务的当前工作目录一致地设置为 $GRADLE_USER_HOME/workers。这可能会导致自定义 Checkstyle 任务或 Checkstyle 配置文件的问题,因为它们假定相对路径的目录不同。

以前,Gradle 根据您运行 Gradle 的目录选择当前工作目录。如果您在以下目录中运行 Gradle

  • 项目的根目录:Gradle 将根目录用作当前工作目录。

  • 项目的嵌套目录:Gradle 将子项目的根目录用作当前工作目录。

在 7.5 及更高版本中,Gradle 将 Checkstyle 任务的当前工作目录一致地设置为 $GRADLE_USER_HOME/workers

弃用

将文件转换为路径中包含文件分隔符的类路径

Java 有一个路径分隔符的概念,用于分隔路径列表中的单个路径,例如在类路径字符串中。单个路径不得包含路径分隔符。因此,对于路径包含路径分隔符的文件,使用 @FileCollection.getAsPath() 已被弃用,并且在 Gradle 8.0 及更高版本中这将是一个错误。使用路径中包含路径分隔符的文件集合可能会导致构建不正确,因为 Gradle 不会将文件作为输入找到,甚至当包含路径分隔符的路径在操作系统上非法时,也可能导致构建失败。

dependencyInsight --singlepath 选项已弃用

为了保持一致性,这已更改为 --single-path。API 方法保持不变,这仅影响 CLI。

Groovydoc includePrivate 属性已弃用

有一个新的 access 属性,允许更精细地控制 Groovydoc 中包含的内容。

配置时运行外部进程必须使用基于 Provider 的 API

当配置缓存启用时,在配置时使用 Project.execProject.javaexec 以及标准 Java 和 Groovy API 运行外部进程现在已弃用。在 Gradle 8.0 及更高版本中,这将是一个错误。Gradle 7.5 引入了与配置缓存兼容的方法,可以使用基于 Provider 的 APIValueSource 接口的自定义实现来执行和获取外部进程的输出。配置缓存章节包含更多详细信息,以帮助迁移到新的 API。

从 7.3 及更早版本升级

弃用

AdoptOpenJDK 工具链下载

随着从 AdoptOpenJDK 转移到 Eclipse 基金会旗下的 Adoptium,不再可能从其终端下载 AdoptOpenJDK 构建。相反,返回 Eclipse Temurin 或 IBM Semeru 构建。

当在工具链规范中指定 AdoptOpenJDK 供应商并且它由自动配置使用时,Gradle 7.4+ 现在将发出弃用警告。如果您必须使用 AdoptOpenJDK,则应关闭自动下载。如果 Eclipse Temurin 或 IBM Semeru 构建对您有效,请将 JvmVendorSpec.ADOPTIUMJvmVendorSpec.IBM 指定为供应商,或不指定供应商。

文件树和空目录处理

当在输入文件集合上使用 @SkipWhenEmpty 时,Gradle 在确定输入为空时跳过任务。如果输入文件集合仅由文件树组成,Gradle 会忽略目录进行空检查。但是,当检查输入文件集合的更改时,Gradle 仅在存在 @IgnoreEmptyDirectories 注解时才忽略目录。

Gradle 现在将一致地忽略 @SkipWhenEmpty 检查和确定更改时的目录。在 Gradle 8.0 之前,Gradle 将检测用 @SkipWhenEmpty 注解的输入文件集合是否仅由文件树组成,然后自动忽略目录。此外,Gradle 将发出弃用警告,以告知用户该行为将在 Gradle 8.0 中更改,并且输入属性应使用 @IgnoreEmptyDirectories 注解。要在 Gradle 8.0 及更高版本中忽略目录,输入属性需要使用 @IgnoreEmptyDirectories 注解。

最后,使用 @InputDirectory 意味着 @IgnoreEmptyDirectories,因此在使用此注解时无需进行任何更改。通过运行时 API 注册输入目录时,inputs.dir() 也是如此。

不带 FileResolver 使用 LazyPublishArtifact 已弃用

当不带 FileResolver 使用 LazyPublishArtifact 时,会使用不同的文件解析策略,这会使 FileResolver 中的一些逻辑重复。

为了提高一致性,LazyPublishArtifact 应该与 FileResolver 一起使用,并且将来会强制要求。

这也影响了使用 LazyPublishArtifact 的其他内部 API,这些 API 现在在需要时也会发出弃用警告。

从没有支持文件的资源创建 TAR 树

可以从任意资源创建 TAR 树。如果资源不是通过 project.resources 创建的,则它可能没有支持文件。从没有支持文件的资源创建 TAR 树已弃用。相反,将资源转换为文件并在文件上使用 project.tarTree()。要将资源转换为文件,您可以使用自定义任务或使用依赖管理通过 URL 下载文件。这样,Gradle 能够应用诸如最新检查之类的优化,而不是每次都重新运行创建资源的逻辑。

唯一属性集

与项目中可消费配置关联的属性集必须在该项目中与所有其他共享相同功能集的配置唯一。

这将在配置变体配置结束时进行检查,因为它们被锁定以防止进一步的变异。

如果属性集在配置之间共享,请考虑向其中一个变体添加一个额外的属性,仅用于消歧目的。

Provider#forUseAtConfigurationTime() 已弃用

Provider#forUseAtConfigurationTime 现在已弃用,计划在 Gradle 9.0 中删除。客户端应直接删除调用。

对于外部值的提供者(例如系统属性环境变量Gradle 属性文件内容)在配置时与配置缓存功能一起使用时,此调用是强制性的。

从版本 7.4 开始,Gradle 将隐式地将配置时使用的外部值视为配置缓存输入。

客户端也可以自由使用标准 Java API(如 System#getenv 读取环境变量、System#getProperty 读取系统属性)以及 Gradle API(如 Project#property(String)Project#findProperty(String))在配置时读取 Gradle 属性。基于 Provider 的 API 仍然是将外部值连接到任务输入以实现最大配置缓存重用的推荐方式。

任务执行监听器和事件

Gradle 配置缓存不支持直接访问 TaskProject 实例的监听器和事件,这允许 Gradle 并行执行任务并在配置缓存中存储最少的数据。为了转向一个无论配置缓存是否启用都一致的 API,以下 API 已弃用,并将在 Gradle 8.0 中删除或成为错误

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

构建完成事件

Gradle 配置缓存不支持构建完成监听器。因此,以下 API 已弃用,并将在 Gradle 8.0 中删除

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

从任务动作调用 Task.getProject()

在执行时从任务动作调用 Task.getProject() 现在已弃用,并将在 Gradle 8.0 中成为错误。此方法可以在配置时使用,但不建议这样做。

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

从任务动作调用 Task.getTaskDependencies()

在执行时从任务动作调用 Task.getTaskDependencies() 现在已弃用,并将在 Gradle 8.0 中成为错误。此方法可以在配置时使用,但不建议这样做。

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

从任务中使用未声明的构建服务

Gradle 需要此信息才能正确遵守构建服务生命周期及其使用约束。

这将在未来的 Gradle 版本中成为错误。

这可以通过使用 @ServiceReference 属性(自 8.0 起)或在任务上调用 usesService()(自 6.1 起)来完成。

有关更多信息,请查看共享构建服务文档

VersionCatalog 和 VersionCatalogBuilder 的废弃

VersionCatalog 和 VersionCatalogBuilder 中的某些方法现已废弃,并计划在 Gradle 8.0 中移除。具体替代方法可在受影响方法的 JavaDoc 中找到。

这些方法经过更改,以改善 `libs.versions.toml` 文件与 API 类之间的一致性。

从 7.2 及更早版本升级

潜在的重大更改

捆绑 Gradle 依赖项的更新

plugins 块中插件的应用顺序

plugins 块中插件的实际应用顺序不一致,取决于插件如何添加到类路径。

现在,插件始终按照它们在 plugins 块中声明的顺序应用,这在极少数情况下可能会改变现有构建的行为。

排除对依赖项解析中替换依赖项的影响

在此版本之前,依赖项替换目标无法从依赖项图中排除。这是由于在执行替换之前检查了排除项。现在 Gradle 还会检查替换结果的排除项。

版本目录

生成的访问器不再提供对类型不安全 API 的访问。您必须改为使用版本目录扩展

Scala 中的工具链支持

Scala 中使用工具链时,Scala 编译器的 `-target` 选项现在将自动设置。这意味着使用无法由某个 Scala 版本定位的 Java 版本将导致错误。在编译器选项中提供此标志将禁用此行为,并允许使用更高版本的 Java 编译为较低的字节码目标。

声明包含不可读内容的输入或输出目录

对于最新检查,Gradle 依赖于跟踪任务输入和输出的状态。Gradle 过去会忽略输入或输出中的不可读文件,以支持某些用例,尽管它无法跟踪它们的状态。声明包含不可读内容的任务上的输入或输出目录已被弃用,这些用例现在通过将任务声明为未跟踪来支持。使用 @UntrackedTask 注解或 Task.doNotTrackState() 方法将任务声明为未跟踪。

当您使用 `Copy` 任务将单个文件复制到包含不可读文件的目录中时,请使用 Task.doNotTrackState() 方法。

从 7.1 及更早版本升级

潜在的重大更改

应用程序启动脚本和 Gradle 包装器脚本的安全更改

由于 CVE-2021-32751,Gradle 的 应用程序插件生成的 `gradle`、`gradlew` 和启动脚本已更新,以避免攻击者能够更改环境变量时这些脚本可能被用于任意代码执行的情况。

您可以使用最新版本的 Gradle 生成 `gradlew` 脚本,并使用它来执行旧版本的 Gradle。

这对于大多数用户来说应该是透明的;但是,对于依赖环境变量 `JAVA_OPTS` 或 `GRADLE_OPTS` 传递带有复杂引用转义的参数的 Gradle 构建,可能会发生更改。如果您怀疑某些东西破坏了您的构建并且找不到解决方案,请联系我们。

捆绑 Gradle 依赖项的更新

弃用

使用 Java lambda 作为任务操作

当使用 Java lambda 实现任务操作时,Gradle 无法跟踪实现,任务将永远不会是最新的或从构建缓存中提供。由于添加此类任务操作很容易,因此使用由 Java lambda 实现的任务操作现已废弃。有关如何解决此问题的更多详细信息,请参阅验证问题

依赖 equals 进行最新检查已被废弃

当任务输入用 `@Input` 注解并且不是 Gradle 直接理解的类型(如 `String`)时,Gradle 使用输入的序列化形式进行最新检查和构建缓存键。历史上,Gradle 还会从上次执行中加载序列化值,然后使用 `equals()` 将其与当前值进行比较以进行最新检查。这样做容易出错,不适用于构建缓存,并且会影响性能,因此已被废弃。Instead of using `@Input` on a type Gradle doesn’t understand directly, use `@Nested` and annotate the properties of the type accordingly。

从 7.0 及更早版本升级

潜在的重大更改

默认工具集成版本的更新

  • JaCoCo 已更新至 0.8.7

`org.gradle.util` 包现在是公共 API

官方地,`org.gradle.util` 包不属于公共 API。但是,由于此包名不包含 `internal` 一词,许多 Gradle 插件已将其视为公共 API。Gradle 7.1 解决了这种情况并将该包标记为公共。那些无意中暴露的类要么被废弃,要么被移除,具体取决于它们的外部使用情况。

以下类现在正式被认为是公共 API:
  • GradleVersion

  • Path

  • Configurable

以下类在外部插件中已知有使用,现已废弃并计划在 Gradle 8.0 中移除:
  • VersionNumber

  • TextUtil

  • WrapUtil

  • RelativePathUtil

  • DistributionLocator

  • SingleMessageLogger

  • ConfigureUtil

`ConfigureUtil` 将被移除,没有替代。插件可以避免使用 `ConfigureUtil`。

以下类仅供内部使用,已从 `org.gradle.util` 移动到 `org.gradle.util.internal` 包:
  • Resources

  • RedirectStdOutAndErr

  • Swapper

  • StdInSwapper

  • IncubationLogger

  • RedirectStdIn

  • MultithreadedTestRule

  • DisconnectableInputStream

  • BulkReadInputStream

  • MockExecutor

  • FailsWithMessage

  • FailsWithMessageExtension

  • TreeVisitor

  • AntUtil

  • JarUtil

最后一组类没有外部或内部使用,因此已被删除:
  • DiffUtil

  • NoopChangeListener

  • EnumWithClassBody

  • AlwaysTrue

  • ReflectionEqualsMatcher

  • DynamicDelegate

  • IncubationLogger

  • NoOpChangeListener

  • DeferredUtil

  • ChangeListener

源集扩展的返回类型已更改

以下源集通过自定义类型的扩展贡献

“惯用”DSL 声明向后兼容

sourceSets {
    main {
        groovy {
            // ...
        }
    }
}

但是,groovy 块的返回类型已更改为扩展类型。这意味着以下代码片段在 Gradle 7.1 中不再有效

 sourceSets {
     main {
         GroovySourceSet sourceSet = groovy {
             // ...
         }
     }
 }

启动脚本需要 bash shell

用于启动 Gradle、Gradle 包装器以及 `application` 插件生成的脚本现在需要 `bash` shell。

弃用

在带有 Provider 类型的属性上使用约定映射已被废弃

约定映射是一个内部功能,已被 Provider API 取代。当约定映射与 Provider API 混合使用时,可能会出现意外行为。当任务、扩展或其他领域对象中的属性使用带有 Provider API 的约定映射时,Gradle 会发出废弃警告。

要解决此问题,需要更改为任务、扩展或领域对象配置约定映射的插件,以仅使用 Provider API。

设置自定义构建布局

命令行选项

  • `-c`, `--settings-file` 用于指定自定义设置文件位置

  • `-b`, `--build-file` 用于指定自定义构建文件位置

已被废弃。

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

请改用 dir 属性来指定嵌套构建的根目录。

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

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

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

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

对于使用自定义设置或构建文件来建模不同行为(类似于 Maven 配置文件)的用例,请考虑使用带有条件逻辑的系统属性。例如,给定设置或构建文件中的一段代码

if (System.getProperty("profile") == "custom") {
    println("custom profile")
} else {
    println("default profile")
}

您可以使用 `gradle -Dprofile=custom` 将 `profile` 系统属性传递给 Gradle,以执行 `custom` 配置文件分支中的代码。

Substitution.with 被 Substitution.using 替换

使用 `with` 方法的依赖项替换已被废弃,并被 `using` 方法替换,该方法也允许链式调用。例如,依赖项替换规则 `substitute(project(':a')).with(project(':b'))` 应该替换为 `substitute(project(':a')).using(project(':b'))`。通过链式调用,您可以为替换添加一个原因,例如:`substitute(project(':a')).using(project(':b')).because("a reason")`。

JavaExec 任务中废弃的属性

非分层项目布局

Gradle 7.1 废弃了子项目位于项目根目录之外的项目布局。然而,根据社区反馈,我们决定在 Gradle 7.4 中回滚并移除了废弃。因此,Settings.includeFlat() 方法仅在 Gradle 7.1、7.2 和 7.3 中废弃。

废弃的 `Upload` 任务

Gradle 过去有两种发布工件的方式。现在,情况已经明朗,所有构建都应该使用 `maven-publish` 插件。旧式发布方式的最后一个剩余工件是 `Upload` 任务,该任务已被废弃并计划在 Gradle 8.0 中移除。现有客户端应迁移到`maven-publish` 插件

废弃的约定

约定的概念已过时,并被扩展取代。为了在 Gradle API 中反映这一点,以下元素现已废弃

约定的内部用法也已清理(参见下面的废弃项)。

如果插件作者复制了我们在内部所做的更改,则迁移到扩展。这里有一些例子

废弃的内部插件配置消费

一些核心 Gradle 插件声明的配置是插件本身使用的,不应直接发布或由另一个子项目消费。Gradle 没有明确禁止这一点。Gradle 7.1 废弃了这些配置的消费,这将在 Gradle 8.0 中成为错误。

以下插件配置已废弃消费

插件 废弃的配置

codenarc

codenarc

pmd

pmd

checkstyle

checkstyle

antlr

antlr

jacoco

`jacocoAnt`、`jacocoAgent`

Scala

zinc

war

`providedCompile`、`providedRuntime`

如果您的用例需要在另一个项目中消费上述任何配置,请创建一个单独的可消费配置,该配置从内部配置扩展。例如

plugins {
    id("codenarc")
}
configurations {
    codenarc {
        // because currently this is consumable until Gradle 8.0 and can clash with the configuration below depending on the attributes set
        canBeConsumed = false
    }
    codenarcConsumable {
        extendsFrom(codenarc)
        canBeConsumed = true
        canBeResolved = false
        // the attributes below make this configuration consumable by a `java-library` project using `implementation` configuration
        attributes {
            attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
            attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY))
            attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, LibraryElements.JAR))
            attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL))
            attribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, objects.named(TargetJvmEnvironment, TargetJvmEnvironment.STANDARD_JVM));
        }
    }
}

废弃的自定义源集接口

以下源集接口现已废弃,并计划在 Gradle 8.0 中移除

  • org.gradle.api.tasks.GroovySourceSet

  • `org.gradle.api.plugins.antlr.AntlrSourceVirtualDirectory` (已移除)

  • org.gradle.api.tasks.ScalaSourceSet

客户端应使用其插件特定的配置来配置源

例如,以下是您如何从插件配置 groovy 源的方法

GroovySourceDirectorySet groovySources = sourceSet.getExtensions().getByType(GroovySourceDirectorySet.class);
groovySources.setSrcDirs(Arrays.asList("sources/groovy"));

注册扩展 `ArtifactTransform` 的工件转换

当 Gradle 首次引入工件转换时,它使用基类 `ArtifactTransform` 来实现它们。Gradle 5.3 引入了接口 `TransformAction` 来实现工件转换,取代了之前的类 `ArtifactTransform` 并解决了各种缺点。使用 `ArtifactTransform` 的注册方法 DependencyHandler.registerTransform(Action) 已被废弃。将您的工件转换迁移到使用 `TransformAction` 并改用 DependencyHandler.registerTransform(Class, Action)。有关实现 `TransformAction` 的更多信息,请参阅用户手册