本章提供将 Gradle 7.x 构建迁移到 Gradle 8.0 所需的信息。要从 Gradle 6.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.1.1 将项目更新到 8.1.1。

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

从 7.6 及更早版本升级

现在是错误的警告

Referencing tasks in an included build with finalizedBy, mustRunAfter or shouldRunAfter

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

  • 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 {
   }
}

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

以下代码现在会导致 test 任务包含“foo”和“bar”标签:

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 已被删除。有关详细信息,请参阅 Registering artifact transforms extending ArtifactTransform

遗留增量任务输入 API

遗留的 IncrementalTaskInputs API 已被删除。有关详细信息,请参阅 IncrementalTaskInputs 类型已弃用。此更改还会影响 Kotlin Gradle 插件和 Android Gradle 插件。对于 Gradle 8.0,您应该使用 Kotlin Gradle Plugin 1.6.10 或更高版本以及具有 android.experimental.legacyTransform.forceNonIncremental=true 属性或更高版本的 Android Gradle Plugin 7.3.0。

遗留 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 属性。

报告和 TestReport API 清理

已弃用的 destinationReport 类型的 enabled 属性已被删除。请改用 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 清理

已弃用的 findDependency(String) 方法和 VersionCatalog 类型的 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) 方法。

依赖替换 API 清理

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

AbstractArchiveTask API 清理

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

IdeaModule API 清理

IdeaModule 类型的已弃用的 testSourceDirstestResourceDirs 属性已被删除。这会影响 org.gradle.plugins.ide.idea.model.IdeaModule 类型,而不是 org.gradle.tooling.model.idea.IdeaModule 类型。请改用 testSourcestestResources 属性。

AbstractCompile API 弃用

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

ResolvedComponentResult API 清理

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

代码质量插件 API 清理

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

使用 API 清理

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

外部依赖 API 清理

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

从 Kotlin DSL 中删除构建扫描方法

已弃用的 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<配置>.all

  • NamedDomainObjectProvider<Configuration>.allArtifacts

  • NamedDomainObjectProvider<配置>.allDependencies

  • NamedDomainObjectProvider<Configuration>.allDependencyConstraints

  • NamedDomainObjectProvider<Configuration>.artifacts

  • NamedDomainObjectProvider<Configuration>.asFileTree

  • NamedDomainObjectProvider<配置>.asPath

  • NamedDomainObjectProvider<配置>.attributes

  • NamedDomainObjectProvider<配置>.buildDependencies

  • NamedDomainObjectProvider<Configuration>.contains

  • NamedDomainObjectProvider<配置>.copy

  • NamedDomainObjectProvider<配置>.copyRecursive

  • NamedDomainObjectProvider<Configuration>.defaultDependencies

  • NamedDomainObjectProvider<配置>.dependencies

  • NamedDomainObjectProvider<Configuration>.dependencyConstraints

  • NamedDomainObjectProvider<Configuration>.description

  • NamedDomainObjectProvider<配置>.exclude

  • NamedDomainObjectProvider<配置>.excludeRules

  • NamedDomainObjectProvider<Configuration>.extendsFrom

  • NamedDomainObjectProvider<Configuration>.fileCollection

  • NamedDomainObjectProvider<配置>.files

  • NamedDomainObjectProvider<Configuration>.filter

  • NamedDomainObjectProvider<配置>.getTaskDependencyFromProjectDependency

  • NamedDomainObjectProvider<Configuration>.hierarchy

  • NamedDomainObjectProvider<Configuration>.incoming

  • NamedDomainObjectProvider<配置>.isCanBeConsumed

  • NamedDomainObjectProvider<配置>.isCanBeResolved

  • NamedDomainObjectProvider<Configuration>.isEmpty

  • NamedDomainObjectProvider<Configuration>.isTransitive

  • NamedDomainObjectProvider<Configuration>.isVisible

  • NamedDomainObjectProvider<配置>.minus

  • NamedDomainObjectProvider<Configuration>.outgoing

  • NamedDomainObjectProvider<配置>.plus

  • NamedDomainObjectProvider<配置>.resolutionStrategy

  • NamedDomainObjectProvider<Configuration>.resolve

  • NamedDomainObjectProvider<Configuration>.resolvedConfiguration

  • NamedDomainObjectProvider<Configuration>.setDescription

  • NamedDomainObjectProvider<Configuration>.setExtendsFrom

  • NamedDomainObjectProvider<配置>.setTransitive

  • NamedDomainObjectProvider<配置>.singleFile

  • NamedDomainObjectProvider<Configuration>.state

  • NamedDomainObjectProvider<配置>.withDependencies

您应该更喜欢直接引用 Configuration 中的方法。

潜在的重大变化

JavaForkOptions getJvmArgs() and getAllJvmArgs() return immutable lists

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

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

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

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

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

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

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

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

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

包装器任务配置

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

AbstractCodeQualityPlugin 类中的更改

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

Remove implicit --add-opens for Gradle workers

在 Gradle 8.0 之前,JDK9+ 上的 Gradle 工作人员通过传递 --add-opens CLI 参数自动打开 JDK 模块 java.base/java.utiljava.base/java.lang。这使得在 Gradle worker 中执行的代码能够在没有警告或失败的情况下对 JDK 内部执行深度反射。工人不再使用这些隐含的论点。

这会影响所有用于各种任务的内部 Gradle worker:

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

  • ScalaDoc

  • AntlrTask

  • JVM 编译器守护进程

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

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

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

  • 代码质量工具

  • 注释处理器

  • 任何使用 worker API 的 Gradle 插件

有关可能由于此更改而产生的可能错误或警告输出的一些示例,请参阅 Removes implicit --add-opens for test workers

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 Plugin 1.3.72 及以上版本。 1.6.21 以上的 Kotlin Gradle Plugin 版本未使用 Gradle 7.x 进行测试。 Gradle 8.x 支持 Kotlin Gradle Plugin 1.6.10 及以上版本。您可以通过修改Kotlin 编译任务中的语言版本和 api 版本设置来使用较低的 Kotlin 语言版本。

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

Gradle 7.x 支持 Android Gradle Plugin (AGP) 4.1 及更高版本。 7.3 以上的 AGP 版本未使用 Gradle 7.x 进行测试。 Gradle 8.x 支持 AGP 8 及更高版本。如果配置以下属性,Gradle 8.x 支持 AGP 7.3 及更高版本:

android.experimental.legacyTransform.forceNonIncremental=true

Change to AntBuilder parent class

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

PluginDeclaration is not serializable

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

Gradle 在最新检查中不对序列化值使用 equals

Gradle 现在在比较最新检查中的序列化值时不会尝试使用 equals。有关详细信息,请参阅 不推荐使用 equals 进行最新检查

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

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

变成错误的警告:

Gradle does not ignore empty directories for file-trees with @SkipWhenEmpty

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

Format of JavaVersion has changed for Java 9 and Java 10

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 系统属性启用此行为。此行为现在是默认行为。该属性已被弃用,应删除其用法。您可以找到有关此属性的更多信息 以下

Init scripts are applied to buildSrc builds

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

此行为现在对于 buildSrc 和包含的构建是一致的。

Gradle no longer runs the build task for buildSrc builds

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

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

此行为现在对于 buildSrc 和包含的构建是一致的。

您可以以与包含的构建中的项目相同的方式运行 buildSrc 的测试,例如运行 gradle buildSrc:build

buildFinished { } hook for buildSrc runs after all tasks have executed

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

此行为现在对于 buildSrc 和包含的构建是一致的。

包含构建的路径更改

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

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

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

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

Adding jst.ejb with the eclipse wtp plugin now removes the jst.utility facet

eclipse wtp 插件将 jst.utility 方面添加到 java 项目。现在,添加 jst.ejb facet 会隐式删除 jst.utility facet:

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

简化 PMD 自定义规则配置

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

Report getOutputLocation return type changed from Provider to Property

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

此更改使 Report API 在内部更加一致,并允许对报告任务进行更惯用的配置。

前者,现在@Deprecated用法:

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 Plugin 1.8.0 开始使用 Java 工具链。建议您配置工具链,而不是在 Kotlin 项目中定义 Java sourceCompatibility /targetCompatibility

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

kotlinDslPluginOptions.jvmTarget is deprecated

以前,您可以使用 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 插件将 JarWarEar 任务的 destinationDirectory 配置到 BasePluginExtension#getLibsDirectory 指定的目录。在 Gradle 8.0 中,java-base 处理此配置。对于已经直接或通过 javaapplicationjava-library 或其他 JVM 生态系统插件直接或间接应用 java-base 插件的项目,无需进行任何更改。

不应使用上传任务

Upload 任务仍然被弃用,现在计划在 Gradle 9.0 中删除。虽然这个类型仍然存在,但它不再起作用,并且会在运行时抛出异常。保留它只是为了避免破坏插件。请改用 maven-publishivy-publish 插件中的任务。

配置不再允许作为依赖项

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

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

以下配置永远不会被使用:

  • AntlrPlugin 创建的 antlr 配置

  • ScalaBasePlugin 创建的 zinc 配置

  • WarPlugin 创建的 providedCompileprovidedRuntime 配置

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

相同的耗材配置现在是一个错误

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

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

JVM 项目的基于工具链的任务

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

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

Scala 编译目标

通过上述工具链更改,Scala 编译任务现在始终提供 targetrelease 参数。确切的参数和值取决于工具链的使用与否,以及 Scala 版本。

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

pluginBundle dropped in Plugin Publish plugin

Gradle 8 不再支持 pluginBundle 扩展。它的功能已合并到 gradlePlugin 块中。这些更改需要最新版本的 Plugin Publish 插件 (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 测试套件插件部分中更新的 声明一个额外的测试套件 示例和 DSL 参考中的 DependencyAdder 页面。

弃用

现在不推荐使用无效的 Java 工具链规范

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

用户手册 中查看有关工具链配置的更多详细信息。

Deprecated members of the org.gradle.util package now report their deprecation

这些成员将在 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() 之类的方法提供相同的功能。

Replacement collections in org.gradle.plugins.ide.idea.model.IdeaModule

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

Replacement methods in org.gradle.api.tasks.testing.TestReport

getDestinationDir()setDestinationDir(File)getTestResultDirs()setTestResultDirs(Iterable) 方法已被弃用。将用法替换为现在稳定的 getDestinationDirectory()getTestResults() 方法及其关联的设置器。这些已弃用的元素将在 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 类型用于实现 incremental tasks,,即可以优化以在更改输入的子集而不是整个输入上运行的任务。这种类型有许多缺点。特别是使用这种类型时,无法确定更改与哪个输入相关联。

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

潜在的重大变化

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

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

更新默认工具集成版本

Classpath file generated by the eclipse plugin has changed

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

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

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

Signing plugin defaults to gpg instead of gpg2 when using the GPG command

签名插件的默认可执行文件 使用 GPG 命令时gpg2 更改为 gpg 。随着 GPG 2.x 变得稳定,并且发行版开始通过不链接 gpg2 可执行文件来迁移,这一变化是有动机的。

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

signing.gnupg.executable=gpg2

mustRunAfter constraints no longer violated by finalizedBy dependencies

在以前的 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 将只能编译 Zinc 版本设置为 1.6.x 或更高版本的 Scala 代码。

Removes implicit --add-opens for test workers

在 Gradle 7.5 之前,JDK 模块 java.base/java.utiljava.base/java.lang 通过传递 --add-opens CLI 参数在 JDK9+ 的测试工作器中自动打开。这意味着任何测试都能够在没有警告或失败的情况下对 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 作为外部工作进程运行。多个 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 option is deprecated

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

Groovydoc includePrivate property is deprecated

有一个新的 access 属性可以更好地控制 Groovydoc 中包含的内容。

必须使用基于提供者的 API 在配置时运行外部进程

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

从 7.3 及更早版本升级

弃用

AdoptOpenJDK工具链下载

在从 AdoptOpenJDK 转移到 Adoptium 之后,在 Eclipse 基础下,不再可能从其端点下载 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 就能够应用最新检查等优化,而不是每次都重新运行逻辑来创建资源。

独特的属性集

与项目中的 consumable 配置关联的 Attribute 集必须在该项目中共享同一组 Capability 的所有其他配置中是唯一的。

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

如果属性集在配置之间共享,请考虑向其中一个变体添加一个附加属性,其唯一目的是消除歧义。

Provider#forUseAtConfigurationTime() has been deprecated

提供商#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 的详细信息,请参阅 配置缓存章节

Calling Task.getProject() from a task action

在执行时从任务操作调用 Task.getProject() 现在已弃用,并且在 Gradle 8.0 中会出错。此方法可在配置时使用,但建议避免这样做。

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

Calling Task.getTaskDependencies() from a task action

在执行时从任务操作调用 Task.getTaskDependencies() 现在已弃用,并且在 Gradle 8.0 中会出错。此方法可在配置时使用,但建议避免这样做。

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

Using a build service from a task without the corresponding Task.usesService declaration

Gradle 需要这些信息才能正确遵守构建服务生命周期及其使用限制。

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

查看 共享构建服务文档 了解更多信息。

VersionCatalog 和 VersionCatalogBuilder 弃用

VersionCatalogVersionCatalogBuilder 中的一些方法现已弃用,并计划在 Gradle 8.0 中删除。可以在受影响方法的 JavaDoc 中找到特定的替换。

这些方法已更改,以提高 libs.versions.toml 文件和 API 类之间的一致性。

从 7.2 及更早版本升级

潜在的重大变化

更新捆绑的 Gradle 依赖项

Application order of plugins in the plugins block

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

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

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

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

版本目录

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

Scala 中的工具链支持

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

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

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

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

从 7.1 及更早版本升级

潜在的重大变化

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

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

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

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

更新捆绑的 Gradle 依赖项

弃用

使用 Java lambda 作为任务操作

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

不推荐使用 equals 进行最新检查

当任务输入用 @Input 注释并且不是 Gradle 直接理解的类型(如 String )时,Gradle 将使用输入的序列化形式进行最新检查和构建缓存键。从历史上看,Gradle 还会加载上次执行的序列化值,然后使用 equals() 将其与当前值进行比较以进行最新检查。这样做很容易出错,不适用于构建缓存并且会影响性能,因此已被弃用。不要在 Gradle 不能直接理解的类型上使用 @Input,而是使用 @Nested 并相应地注释类型的属性。

从 7.0 及更早版本升级

潜在的重大变化

更新默认工具集成版本

  • JaCoCo 已更新为 0.8.7

The org.gradle.util package is now a public API

正式地,org.gradle.util 包不是公共 API 的一部分。但是,因为这个包名不包含单词 internal ,许多 Gradle 插件已经被认为是一个。 Gradle 7.1 解决了这种情况并将包标记为公开。无意中公开的类将被弃用或删除,具体取决于它们的外部用途。

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

  • Path

  • Configurable

以下类在外部插件中具有已知用法,现在已弃用并设置为在 Gradle 8.0 中删除:
  • VersionNumber

  • TextUtil

  • WrapUtil

  • RelativePathUtil

  • DistributionLocator

  • SingleMessageLogger

  • ConfigureUtil

ConfigureUtil 被删除,没有替换。插件可以通过遵循 我们的例子 来避免使用 ConfigureUtil

The following classes have only internal usages and were moved from org.gradle.util to the org.gradle.util.internal package:
  • 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 类型的属性的约定映射

约定映射是一项内部功能,已被 供应商接口 取代。将约定映射与提供者 API 混合使用时,可能会发生意外行为。当任务、扩展或其他域对象中的属性使用 Provider API 的约定映射时,Gradle 会发出弃用警告。

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

设置自定义构建布局

命令行选项:

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

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

已被弃用。

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

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

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

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

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

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

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

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

您可以使用 gradle -Dprofile=customprofile 系统属性传递给 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 中被弃用。

Deprecated Upload task

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

弃用的约定

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

约定的内部用法也已清理(请参阅下面的弃用项目)。

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

Deprecated base plugin conventions

base 插件提供的约定属性已被弃用,并计划在 Gradle 8.0 中删除。这些约定被 BasePluginExtension 支持的 base { } 配置块所取代。

旧约定对象使用简单的 getter 和 setter 方法定义 distsDirNamelibsDirNamearchivesBaseName 属性。这些方法在扩展中可用只是为了保持向后兼容性。构建脚本应该只使用 Property 类型的属性:

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

Deprecated ApplicationPluginConvention

ApplicationPluginConvention 已在 文档 中列为已弃用。现在,它被正式注释为已弃用,并计划在 Gradle 8.0 中删除。

Deprecated java plugin conventions

java 插件提供的约定属性已被弃用,并计划在 Gradle 8.0 中删除。它们被 JavaPluginExtension 的属性替换,可以在 java {} 块中配置。

不赞成使用内部插件配置

一些核心 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));
        }
    }
}

Deprecated project-report plugin conventions

ProjectReportsPluginConvention 现在已弃用并计划在 Gradle 8.0 中删除。客户应直接配置项目报告任务。此外,tasks.withType(…).configureEach(…) 可用于配置相同类型的每个任务(例如 HtmlDependencyReportTask)。

Deprecated war plugin conventions

WarPluginConvention 现在已弃用并计划在 Gradle 8.0 中删除。客户端应直接配置 war 任务。此外,tasks.withType(War.class).configureEach(…) 可用于配置类型为 War 的每个任务。

Deprecated ear plugin conventions

EarPluginConvention 现在已弃用并计划在 Gradle 8.0 中删除。客户端应直接配置 ear 任务。此外,tasks.withType(Ear.class).configureEach(…) 可用于配置类型为 Ear 的每个任务。

弃用的自定义源集接口

以下源集接口现已弃用并计划在 Gradle 8.0 中删除:

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

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

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

Registering artifact transforms extending ArtifactTransform

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