将您的构建从 Gradle 7.x 升级到 8.0
本章提供将您的 Gradle 7.x 构建迁移到 Gradle 8.0 所需的信息。要从 Gradle 6.x 或更早版本迁移,请先完成旧版本的迁移指南。
我们为所有用户推荐以下步骤
-
尝试运行
gradle help --scan
并查看生成的构建扫描的弃用视图。这样您就可以看到任何适用于您的构建的弃用警告。
或者,您可以运行
gradle help --warning-mode=all
在控制台中查看弃用信息,但这可能不会报告那么多详细信息。 -
更新您的插件。
某些插件会在此新版本的 Gradle 中崩溃,例如,因为它们使用了已删除或更改的内部 API。上一步将通过在插件尝试使用已弃用的 API 部分时发出弃用警告来帮助您识别潜在的问题。
-
运行
gradle wrapper --gradle-version 8.13
以将项目更新到 8.13。 -
尝试运行项目并使用故障排除指南调试任何错误。
从 7.6 及更早版本升级
现在成为错误的警告
使用 finalizedBy
、mustRunAfter
或 shouldRunAfter
引用包含构建中的 Task
现在,使用以下任何方法引用包含构建中的 Task 都会导致执行时错误
-
finalizedBy
-
mustRunAfter
-
shouldRunAfter
从没有后备文件的资源创建 TAR 树
不再支持从没有后备文件的资源创建 TAR 树。相反,将资源转换为文件,并在该文件上使用 project.tarTree()
。有关更多信息,请参阅从没有后备文件的资源创建 TAR 树。
使用无效的 Java 工具链规范
不再支持使用无效的 Java 工具链规范。可以通过确保在所有工具链规范上都设置了语言版本来避免相关的构建错误。有关更多信息,请参阅用户手册。
在没有配置仓库的情况下使用自动工具链下载
不再支持在没有显式提供要使用的仓库的情况下自动下载工具链。有关更多信息,请参阅用户手册。
在设置测试框架选项后更改测试框架现在是一个错误
当为 Java、Groovy 和 Scala 项目配置内置测试 task 时,Gradle 不再允许您在配置选项后更改 Test
task 使用的测试框架。这已被弃用,因为它在某些情况下会静默丢弃配置。
以下代码示例现在会产生错误
test {
options {
}
useJUnitPlatform()
}
相反,您可以
-
在配置选项之前设置测试框架
test {
// select test framework before configuring options
useJUnitPlatform()
options {
}
}
此外,多次将测试框架设置为相同的框架现在会累积可能在框架上设置的任何选项。以前,每次设置框架时,都会导致框架选项被覆盖。
以下代码现在将导致 test
task 同时包含 "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。有关更多信息,请参阅注册扩展 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
task 类型的已弃用 isIncludePrivate
属性。请改用 access
属性以及 GroovydocAccess#PRIVATE
常量。
JavaApplication API 清理
已删除 JavaApplication
接口的已弃用 mainClassName
属性。请改用 mainClass
属性。
DefaultDomainObjectSet API 清理
已删除已弃用的 DefaultDomainObjectSet(Class)
构造函数。这是一个内部 API,但可能已被插件使用。
JacocoPluginExtension API 清理
已删除 JacocoPluginExtension
的已弃用 reportsDir
属性。请改用 reportsDirectory
属性。
DependencyInsightReportTask API 清理
已删除 DependencyInsightReportTask
task 类型的已弃用 legacyShowSinglePathToDependnecy
属性。请改用 showSinglePathToDependency
属性。
Report 和 TestReport API 清理
已删除 Report
类型的已弃用 destination
和 enabled
属性。请改用 outputLocation
和 required
属性。
已删除 TestReport
task 类型的已弃用 testResultDirs
属性。请改用 testResults
属性。
JacocoMerge Task 已删除
已删除已弃用的 JacocoMerge
task 类型。JacocoReport
task 也提供了相同的功能。
JavaExec API 清理
已删除 JavaExec
task 类型的已弃用 main
属性。请改用 mainClass
属性。
AbstractExecTask API 清理
已删除 AbstractExecTask
task 类型的已弃用 execResult
getter 属性。请改用 executionResult
getter 属性。
AbstractTestTask API 清理
已删除 AbstractTestTask
task 类型的已弃用 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
task 类型的已弃用 appendix
、archiveName
、archivePath
、baseName
、classifier
、destinationDir
、extension
和 version
属性。请改用 archiveAppendix
、archiveFileName
、archiveFile
、archiveBaseName
、archiveClassifier
、destinationDirectory
、archiveExtension
和 archiveVersion
属性。
IdeaModule API 清理
已删除 IdeaModule
类型的已弃用 testSourceDirs
和 testResourceDirs
属性。这会影响 org.gradle.plugins.ide.idea.model.IdeaModule
类型,而不是 org.gradle.tooling.model.idea.IdeaModule
类型。请改用 testSources
和 testResources
属性。
AbstractCompile API 弃用
先前已弃用的 AbstractCompile
的 destinationDir
属性仍然被弃用,并且现在在使用时会发出弃用警告。它现在计划在 Gradle 9.0 中删除。请改用 destinationDirectory
属性。
ResolvedComponentResult API 清理
已删除 ResolvedComponentResult
接口的已弃用 getVariant
方法。请改用 getVariants
方法。
代码质量插件 API 清理
已删除 Checkstyle
、CodeNarc
和 Pmd
task 类型的已弃用 antBuilder
属性。请改用 Project
类型的 ant
属性。
Usage API 清理
已删除 Usage
类型的已弃用公共字段 JAVA_API_CLASSES
、JAVA_API_JARS
、JAVA_RUNTIME_CLASSES
、JAVA_RUNTIME_JARS
和 JAVA_RUNTIME_RESOURCES
。这些值在内部 JavaEcosystemSupport
类中可用,以与以前发布的模块兼容,但不应用于任何新的发布。
ExternalDependency API 清理
已删除 ExternalDependency
接口的已弃用 setForce(boolean)
方法。请改用 version(Action)
方法来配置严格版本。
从 Kotlin DSL 中删除构建扫描方法
已从 Kotlin DSL 中删除已弃用的 build-scan
插件应用方法。请改用 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 参数列表现在是不可变的。
以前,对返回列表的修改会被静默忽略。
Nullable 注解更好地反映了 API 的实际可空性
在某些 API 中,可空性未正确注解,并且允许 null 或返回 null 的 API 被标记为非 null。在 Java 或 Groovy 中,这种不匹配在编译时不会引起问题。在 Kotlin 中,这种不匹配使得编写有效代码变得困难,因为该语言不允许您传递 null。
一个特殊的例子是从 Provider#map
或 Provider#flatMap
返回 null
。在这两个 API 中,Gradle 允许您返回 null,但在 Kotlin DSL 中,这被认为是非法的。
此更正可能会在期望非 null 的代码中导致编译错误。
插件、Task 和扩展类是抽象类
大多数插件、Task 和扩展的公共类都已设为抽象类。这样做是为了更容易从 Gradle 的实现中删除样板代码。
受此更改影响的插件也应将其类设为抽象类。只要对象是通过 ObjectFactory
或其他自动机制(如托管属性)实例化的,Gradle 就会使用运行时类装饰来实现抽象方法。这些方法永远不应直接实现。
Wrapper task 配置
如果 gradle-wrapper.properties
包含 distributionSha256Sum
属性,则必须指定校验和。您可以在 wrapper task 配置中或使用 --gradle-distribution-sha256-sum
task 选项指定校验和。
AbstractCodeQualityPlugin 类中的更改
已在 Gradle 8.0 中删除已弃用的 AbstractCodeQualityPlugin.getJavaPluginConvention()
方法。您应该改用 JavaPluginExtension
。
为 Gradle worker 删除隐式 --add-opens
在 Gradle 8.0 之前,JDK9+ 上的 Gradle worker 通过传递 --add-opens
CLI 参数自动打开 JDK 模块 java.base/java.util
和 java.base/java.lang
。这使在 Gradle worker 中执行的代码能够对 JDK 内部结构执行深度反射,而不会发出警告或失败。Worker 不再使用这些隐式参数。
这会影响所有内部 Gradle worker,这些 worker 用于各种 task
-
代码质量插件(Checkstyle、CodeNarc、Pmd)
-
ScalaDoc
-
AntlrTask
-
JVM 编译器守护程序
-
使用进程隔离通过Worker API执行的 task
新的警告和错误可能会出现在任何工具、扩展或插件中,这些工具、扩展或插件使用 worker API 对 JDK 内部结构执行深度反射。
这些错误可以通过更新违规代码或依赖项来解决。更新可能包括
-
代码质量工具
-
注解处理器
-
任何使用 worker API 的 Gradle 插件
有关可能因这一更改而产生的错误或警告输出的一些示例,请参阅为测试 worker 删除隐式 --add-opens
。
SourceSet classesDirs 不再依赖于整个 SourceSet 作为 task 依赖项
在 Gradle 8.0 之前,SourceSetOutput.classesDirs
的 task 依赖项包括不生成类文件的 task。这意味着依赖于 classesDirs
的 task 也将依赖于 classes
、processResources
以及添加到 SourceSetOutput
的任何其他 task 依赖项。此行为可能是一个错误,因为 classesDirs
属性不包含 processResources
的输出。自 8.0 起,此隐式依赖项已删除。现在,依赖于 classesDirs
仅执行直接在 classes 目录中生成文件的 task。
考虑以下构建脚本
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
task 依赖于 compileJava
、processResources
和 classes
。现在,只有 compileJava
是 listClassFiles
的 task 依赖项。
如果您的构建中的某个 task 依赖于以前的行为,您可以改为使用整个 SourceSetOutput
作为输入,其中包含所有类和资源。
如果这不可行,您可以通过向 classesDirs
添加更多 task 依赖项来恢复以前的行为
java {
sourceSets {
main {
output.classesDirs.builtBy(output)
}
}
}
最低支持的 Kotlin Gradle 插件版本已更改
Gradle 7.x 支持 Kotlin Gradle 插件 1.3.72 及更高版本。Gradle 7.x 未测试高于 1.6.21 的 Kotlin Gradle 插件版本。Gradle 8.x 支持 Kotlin Gradle 插件 1.6.10 及更高版本。您可以通过修改 Kotlin 编译任务中的 language version 和 api version 设置来使用较低的 Kotlin 语言版本。
最低支持的 Android Gradle 插件版本已更改
Gradle 7.x 支持 Android Gradle Plugin (AGP) 4.1 及更高版本。Gradle 7.x 未测试高于 7.3 的 AGP 版本。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 在最新检查中不再对序列化值使用 equals
Gradle 现在在最新检查中比较序列化值时,不再尝试使用 equals。有关更多信息,请参阅 依赖 equals 进行最新检查已弃用。
Gradle 7.x 中引入的任务和转换验证警告现在是错误
Gradle 在 Gradle 7.x 系列中引入了额外的任务和工件转换验证警告。这些警告现在在 Gradle 8.0 中是错误,并将导致构建失败。
已变为错误的警告
-
无法解析的输入文件集合。
-
无法读取的输入或输出文件或目录。请参阅 声明包含不可读内容的输入或输出目录。
-
使用
java.io.File
作为工件转换的@InputArtifact
。 -
使用具有未知实现的输入。请参阅 无法使用具有未知实现的输入。
-
任务之间缺少依赖关系。请参阅 任务之间的隐式依赖关系。
-
将文件转换为路径包含文件分隔符的类路径。
Gradle 不再为具有 @SkipWhenEmpty
的文件树忽略空目录
之前,Gradle 过去会检测使用 @SkipWhenEmpty
注释的输入文件集合是否仅由文件树组成,然后自动忽略目录。要在 Gradle 8.0 及更高版本中忽略目录,输入属性需要使用 @IgnoreEmptyDirectories
显式注释。有关更多信息,请参阅 文件树和空目录处理。
Java 9 和 Java 10 的 JavaVersion
格式已更改
JavaVersion
的字符串格式已更改为与官方 Java 版本控制匹配。从 Java 9 开始,语言版本不得包含 1.
前缀。这会影响 JavaCompile
任务和 JavaExtension
上的 sourceCompatiblity
和 targetCompatibility
属性的格式。从字符串解析 JavaVersion
时,旧格式仍然受支持。
Gradle 7.6 |
Gradle 8.0 |
|
|
|
|
|
|
|
|
预编译脚本插件默认使用严格的 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 { }
hook for buildSrc
在所有任务执行完毕后运行
现在,buildFinished {}
hook for buildSrc
在所有任务完成后运行。在之前的版本中,此 hook 会在 buildSrc
的任务完成后立即运行,并在任何请求的任务开始之前运行。
此行为现在对于 buildSrc
和包含的构建是一致的。
包含构建的路径更改
为了更好地处理嵌套包含构建名称之间的冲突,Gradle 现在使用包含构建的目录层次结构来分配构建路径。如果您从命令行在嵌套包含构建中运行任务,则可能需要调整您的调用。
例如,如果您有以下层次结构
.
├── settings.gradle.kts
└── nested
├── settings.gradle.kts
└── nestedNested
└── settings.gradle.kts
includeBuild("nested")
includeBuild("nestedNested")
.
├── settings.gradle
└── nested
├── settings.gradle
└── nestedNested
└── settings.gradle
includeBuild("nested")
includeBuild("nestedNested")
在 Gradle 8.0 之前,您运行 gradle :nestedNested:compileJava
。在 Gradle 8.0 中,调用更改为 gradle :nested:nestedNested:compileJava
。
使用 eclipse wtp
插件添加 jst.ejb
现在会删除 jst.utility
facet
eclipse wtp
插件将 jst.utility
facet 添加到 java 项目。现在,添加 jst.ejb
facet 隐式删除 jst.utility
facet
eclipse {
wtp {
facet {
facet name: 'jst.ejb', version: '3.2'
}
}
}
简化 PMD 自定义规则配置
以前,您必须显式配置 PMD 以使用 ruleSets = []
忽略默认规则。在 Gradle 8.0 中,将 ruleSetConfig
或 ruleSetFiles
设置为非空值会隐式忽略默认规则。
Report 的 getOutputLocation
返回类型从 Provider 更改为 Property
现在,Report 的 outputLocation
属性返回 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-plugin
的 validatePlugins
任务来验证正在开发的插件。
可重现的归档文件可能与过去版本相比发生更改
Gradle 更改了用于创建归档文件的压缩库,从基于 Ant 的库更改为 Apache Commons Compress™。因此,由相同内容创建的归档文件,不太可能与其使用旧库创建的旧版本字节对字节完全相同。
升级到 Kotlin 1.8.10
嵌入式 Kotlin 已更新到 Kotlin 1.8.10。另请参阅 Kotlin 1.8.0 发行说明。有关更多信息,请参阅 Kotlin 的发行说明
将 Kotlin DSL 更新到 Kotlin API Level 1.8
以前,Kotlin DSL 使用 Kotlin API level 1.4。从 Gradle 8.0 开始,Kotlin DSL 使用 Kotlin API level 1.8。此更改带来了自 Kotlin 1.4.0 以来对 Kotlin 语言和标准库所做的所有改进。
有关此升级中的破坏性和非破坏性更改的信息,请参阅以下 Kotlin 文档链接
请注意,Kotlin Gradle Plugin 1.8.0 开始使用 Java 工具链。建议您配置工具链,而不是在 Kotlin 项目中定义 Java sourceCompatibility
/targetCompatibility
。
另请注意,Kotlin Gradle Plugin 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
插件将 destinationDirectory of Jar、War 和 Ear 任务配置为由 BasePluginExtension#getLibsDirectory 指定的目录。在 Gradle 8.0 中,java-base
处理此配置。对于已直接或间接通过 java
、application
、java-library
或其他 JVM 生态系统插件应用 java-base
插件的项目,无需进行任何更改。
不应使用 Upload Task
Upload
任务仍然已弃用,现在计划在 Gradle 9.0 中删除。尽管此类型仍然存在,但它不再起作用,并且在运行时将抛出异常。保留它仅是为了避免破坏插件。请改用 maven-publish
或 ivy-publish
插件中的任务。
不再允许将 Configuration 用作依赖项
不再允许在 dependencies
DSL 块中将 Configuration 添加为依赖项,或以编程方式使用 DependencyHandler
类的 doAdd(Configuration, Object, Closure)
方法,这将失败并抛出异常。要复制此行为的许多方面,请使用 Configuration
上的 extendsFrom(Configuration)
方法扩展配置。
已弃用以供使用的 Configuration 现在不可使用
以下 Configuration 从未打算被使用
-
由
AntlrPlugin
创建的antlr
Configuration -
由
ScalaBasePlugin
创建的zinc
Configuration -
由
WarPlugin
创建的providedCompile
和providedRuntime
Configuration
这些 Configuration 已弃用以供使用,现在已不可使用。尝试使用它们将导致错误。
相同的可使用 Configuration 现在是错误
如果项目有多个共享相同属性和功能声明的可使用 Configuration,则在发布或解析为依赖项时,构建将失败。这在 之前已弃用。
outgoingVariants
报告 将警告受影响的 Configuration。
JVM 项目的基于工具链的任务
从 Gradle 8.0 开始,所有具有工具链支持的核心 Java 任务现在都无条件地使用工具链。如果应用了 JavaBasePlugin
,则任务上工具属性的约定值由在 java
扩展上配置的工具链定义。如果未显式配置工具链,则使用与运行 Gradle 的 JVM 对应的工具链。
同样,Groovy 和 Scala 插件中的任务也依赖于工具链来确定它们在哪个 JVM 上执行。
Scala 编译目标
通过上述工具链更改,Scala 编译任务现在始终提供 target
或 release
参数。确切的参数和值取决于工具链的使用与否以及 Scala 版本。
有关详细信息,请参阅 Scala 插件文档。
从 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 {
// ...
}
升级到 CodeNarc 3.1.0
CodeNarc 的默认版本已更新到 3.1.0。
升级到 PMD 6.48.0
PMD 已更新到 PMD 6.48.0。
配置不存在的可执行文件现在会失败
当为 JavaCompile
或 Test
任务显式配置可执行文件时,如果此可执行文件不存在,Gradle 现在将发出错误。过去,该任务将使用默认工具链或运行构建的 JVM 执行。
Test Suites 中依赖项声明的更改
作为不断发展 Test Suites 的一部分,Test Suites dependencies
块中的依赖项声明现在是 强类型 的。这将有助于使此孵化 API 更易于发现,并在 IDE 中更易于使用。
在某些情况下,这需要语法更改。例如,以前使用以下语法添加 Test Suite 依赖项的构建脚本
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 的依赖项声明。 -
您不能直接使用 bundle 作为依赖项声明 (
implementation(libs.bundles.testing)
)。请改用implementation.bundle(libs.bundles.testing)
。
有关更多信息,请参阅用户指南的 JVM Test Suite Plugin 部分中更新的 声明额外的测试套件 示例和 DSL 参考中的 DependencyAdder
页面。
弃用
无效 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
中的替换集合
testResourcesDirs
和 testSourcesDirs
字段及其 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` 的命名容器配置方法中访问根项目配置方法。考虑以下代码片段以了解此行为的示例
当提供的闭包在其他方面是 Configuration 的无效配置闭包时,Gradle 允许从 configurations
块内访问顶级 repositories
块。在这种情况下,repositories
闭包的执行方式就像在脚本级别调用一样,并创建一个未配置的 repositories
Configuration
configurations {
repositories {
mavenCentral()
}
someConf {
canBeConsumed = false
canBeResolved = false
}
}
此行为也适用于不立即执行的闭包。在这种情况下,afterResolve
仅在 resolve
任务运行时执行。distributions
闭包是有效的顶级脚本闭包。但它是 Configuration 的无效配置闭包。此示例立即创建 conf
Configuration。在 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…) 方法)将导致构建失败。
更新默认工具集成版本
-
Checkstyle 已更新至 Checkstyle 8.45.1。
-
JaCoCo 已更新至 0.8.8。
由 eclipse
插件生成的 Classpath 文件已更改
在测试配置中定义的项目依赖项会获得 test=true
classpath 属性。由 JVM Test Suite 插件定义的所有源集和依赖项在默认情况下也会标记为测试代码。现在,您可以通过 eclipse
插件 DSL 自定义测试源集和依赖项
eclipse {
classpath {
testSourceSets = [sourcesSets.test, sourceSets.myTestSourceSet]
testConfigurations = [configuration.myTestConfiguration]
}
}
或者,您可以在 eclipse.classpath.file.whenMerged { }
代码块中调整或删除 classpath 属性。
当使用 GPG 命令时,签名插件默认使用 gpg
而不是 gpg2
签名插件的默认可执行文件当使用 GPG 命令时已从 gpg2
更改为 gpg
。此更改的动机是 GPG 2.x 变得稳定,并且发行版开始迁移,不再链接 gpg2
可执行文件。
为了设置旧的默认值,可以在 gradle.properties
中手动定义可执行文件
signing.gnupg.executable=gpg2
mustRunAfter
约束不再被 finalizedBy
依赖项违反
在之前的 Gradle 版本中,常规任务和 finalizer 任务依赖项之间的 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") {
}
}
相关的约束是
-
dockerStop
是dockerTest
的 finalizer,因此它必须在dockerTest
之后运行; -
removeContainer
是dockerStop
的依赖项,因此它必须在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
更新捆绑的 Gradle 依赖项
-
Groovy 已更新至 Groovy 3.0.11。
Scala Zinc 版本已更新至 1.6.1
Zinc 是 Scala 增量编译器,它允许 Gradle 始终编译当前文件更改所需的最少文件集。它会考虑正在使用哪些方法以及哪些方法已更改,这意味着它比仅文件间依赖关系更精细。
Zinc 版本已更新到最新的可用版本,以便从所有最新的错误修复中获益。因此,如果您使用 zincVersion
设置,建议将其删除,仅使用默认版本,因为 Gradle 将只能使用设置为 1.6.x 或更高版本的 Zinc 版本编译 Scala 代码。
为测试 worker 移除隐式的 --add-opens
在 Gradle 7.5 之前,JDK 模块 java.base/java.util
和 java.base/java.lang
在 JDK9+ 上的测试 worker 中通过传递 --add-opens
CLI 参数自动打开。这意味着任何测试都能够在 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.lang
和 java.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 任务默认使用 toolchain 并并行执行
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
。
弃用
将路径包含文件分隔符的文件转换为 classpath
Java 具有路径分隔符的概念,该分隔符用于分隔路径列表中的各个路径,例如在 classpath 字符串中。各个路径不得包含路径分隔符。因此,对于路径包含路径分隔符的文件,使用 @FileCollection.getAsPath()
已被弃用,并且在 Gradle 8.0 及更高版本中将是一个错误。使用路径包含路径分隔符的文件集合可能会导致不正确的构建,因为 Gradle 找不到作为输入的文件,或者甚至在操作系统上路径包含路径分隔符是非法的情况下导致构建失败。
dependencyInsight
--singlepath
选项已弃用
为了保持一致性,这已更改为 --single-path
。API 方法保持不变,这仅影响 CLI。
Groovydoc includePrivate
属性已弃用
有一个新的 access
属性,可以更精细地控制 Groovydoc 中包含的内容。
必须使用基于 Provider 的 API 在配置时运行外部进程
当启用配置缓存时,在配置时使用 Project.exec
、Project.javaexec
以及标准 Java 和 Groovy API 运行外部进程现在已被弃用。在 Gradle 8.0 及更高版本中,这将是一个错误。Gradle 7.5 引入了配置缓存兼容的方式,可以使用基于 provider 的 API 或 ValueSource
接口的自定义实现来执行外部进程并获取其输出。配置缓存章节提供了更多详细信息,以帮助迁移到新的 API。
从 7.3 及更早版本升级
潜在的破坏性更改
更新默认工具集成版本
-
PMD 已更新至 PMD 6.39.0。
弃用
AdoptOpenJDK 工具链下载
在 AdoptOpenJDK 迁移到 Eclipse 基金会下的 Adoptium 之后,现在无法再从其端点下载 AdoptOpenJDK 构建。而是返回 Eclipse Temurin 或 IBM Semeru 构建。
当在工具链规范中指定 AdoptOpenJDK 供应商,并且它被自动配置使用时,Gradle 7.4+ 现在将发出弃用警告。如果您必须使用 AdoptOpenJDK,则应关闭自动下载。如果 Eclipse Temurin 或 IBM Semeru 构建对您有效,请指定 JvmVendorSpec.ADOPTIUM
或 JvmVendorSpec.IBM
作为供应商,或不指定供应商。
文件树和空目录处理
当在输入文件集合上使用 @SkipWhenEmpty
时,Gradle 会在确定输入为空时跳过任务。如果输入文件集合仅包含文件树,则 Gradle 会忽略目录以进行空性检查。但是,当检查输入文件集合的更改时,仅当存在 @IgnoreEmptyDirectories
注解时,Gradle 才会忽略目录。
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 能够应用诸如最新检查之类的优化,而不是每次都重新运行创建资源的逻辑。
唯一的属性集
与项目中可消费配置关联的 Attribute 集合,必须在该项目中共享同一组 Capability 的所有其他配置中是唯一的。
这将在配置变体配置结束时进行检查,因为它们被锁定以防止进一步的突变。
如果属性集在配置之间共享,请考虑为变体之一添加一个额外的属性,仅用于消除歧义。
Provider#forUseAtConfigurationTime()
已被弃用
Provider#forUseAtConfigurationTime 现已弃用,并计划在 Gradle 9.0 中移除。客户端应直接删除调用。
从版本 7.4 开始,Gradle 将隐式地将配置时使用的外部值视为配置缓存输入。
客户端也可以自由使用标准的 Java API,例如 System#getenv
读取环境变量,System#getProperty
读取系统属性,以及 Gradle API,例如 Project#property(String)
和 Project#findProperty(String)
在配置时读取 Gradle 属性。基于 Provider
的 API 仍然是将外部值连接到任务输入以实现最大配置缓存重用的推荐方法。
ConfigurableReport#setDestination(org.gradle.api.provider.Provider<java.io.File>)
已被弃用
ConfigurableReport#setDestination(org.gradle.api.provider.Provider<java.io.File>)
现已弃用,并计划在 Gradle 8.0 中移除。
任务执行监听器和事件
Gradle 配置缓存不支持直接访问 Task
和 Project
实例的监听器和事件,这允许 Gradle 并行执行任务并在配置缓存中存储最少量的数据。为了转向与配置缓存是否启用都一致的 API,以下 API 已被弃用,并将在 Gradle 8.0 中移除或变为错误
-
通过 Gradle.addListener() 注册 TaskExecutionListener、TaskActionListener、TestListener、TestOutputListener
请参阅配置缓存章节,了解如何将这些用法迁移到配置缓存支持的 API。
从任务 action 中调用 Task.getProject()
现在,从执行时的任务 action 中调用 Task.getProject() 已被弃用,并将在 Gradle 8.0 中变为错误。此方法可以在配置时使用,但建议避免这样做。
请参阅配置缓存章节,了解如何将这些用法迁移到配置缓存支持的 API。
从任务 action 中调用 Task.getTaskDependencies()
现在,从执行时的任务 action 中调用 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 依赖项
-
Kotlin 已更新至 Kotlin 1.5.31。
-
Groovy 已更新至 Groovy 3.0.9。
-
Ant 已更新至 Ant 1.10.11,以修复 CVE-2021-36373 和 CVE-2021-36374。
-
Commons compress 已更新至 Commons-compress 1.21,以修复 CVE-2021-35515、CVE-2021-35516、CVE-2021-35517 和 CVE-2021-36090。
plugins
代码块中插件的应用顺序
plugins
代码块中插件的实际应用顺序是不一致的,并且取决于插件添加到类路径的方式。
现在,插件始终按照它们在 plugins
代码块中声明的相同顺序应用,这在极少数情况下可能会更改现有构建的行为。
依赖项解析中排除对替换依赖项的影响
在此版本之前,依赖项替换目标无法从依赖项图中排除。这是由于在执行替换之前检查排除项引起的。现在,Gradle 还将检查替换结果的排除项。
Scala 中的 Toolchain 支持
当在 Scala 中使用 toolchain 时,Scala 编译器的 -target
选项现在将自动设置。这意味着使用 Scala 版本无法定位的 Java 版本将导致错误。在编译器选项中提供此标志将禁用此行为,并允许使用更高的 Java 版本来编译为较低的字节码目标。
声明包含不可读内容的输入或输出目录
对于最新检查,Gradle 依赖于跟踪任务的输入和输出的状态。Gradle 过去常常忽略输入或输出中不可读的文件以支持某些用例,尽管它无法跟踪其状态。在包含不可读内容的任务上声明输入或输出目录已被弃用,并且现在通过声明任务为 untracked 来支持这些用例。使用 @UntrackedTask 注解或 Task.doNotTrackState() 方法将任务声明为 untracked。
当您使用 Copy
任务将单个文件复制到包含不可读文件的目录时,请使用 Task.doNotTrackState() 方法。
从 7.1 及更早版本升级
潜在的破坏性更改
应用程序启动脚本和 Gradle Wrapper 脚本的安全更改
由于 CVE-2021-32751,gradle
、gradlew
和 Gradle 的 application 插件生成的启动脚本已更新,以避免在攻击者能够更改环境变量时,这些脚本可能被用于任意代码执行的情况。
您可以使用最新版本的 Gradle 生成 gradlew
脚本,并使用它来执行旧版本的 Gradle。
对于大多数用户来说,这应该是透明的;但是,对于依赖于环境变量 JAVA_OPTS
或 GRADLE_OPTS
传递具有复杂引号转义的参数的 Gradle 构建,可能会发生更改。如果您怀疑某些东西破坏了您的构建并且您找不到解决方案,请联系我们。
更新捆绑的 Gradle 依赖项
-
Groovy 已更新至 Groovy 3.0.8。
-
Kotlin 已更新至 Kotlin 1.5.21。
更新默认工具集成版本
-
PMD 已更新至 PMD 6.36.0。
弃用
使用 Java lambda 作为任务 action
当使用 Java lambda 实现任务 action 时,Gradle 无法跟踪实现,并且任务永远不会是最新的或从构建缓存中提供。由于添加这样的任务 action 很容易,因此现在不建议使用由 Java lambda 实现的任务 action。有关如何解决此问题的更多详细信息,请参阅验证问题。
依赖 equals 进行最新检查已被弃用
当任务输入使用 @Input
注解并且不是 Gradle 直接理解的类型(如 String
)时,Gradle 会使用输入的序列化形式进行最新检查和构建缓存键。从历史上看,Gradle 还会从上次执行中加载序列化值,然后使用 equals()
将其与当前值进行比较以进行最新检查。这样做容易出错,不适用于构建缓存,并且会影响性能,因此已被弃用。与其在 Gradle 不直接理解的类型上使用 @Input
,不如使用 @Nested
并相应地注解类型的属性。
从 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
源集扩展的返回类型已更改
以下源集通过具有自定义类型的扩展来贡献
-
groovy
: GroovySourceDirectorySet -
antlr
: AntlrSourceDirectorySet -
scala
: ScalaSourceDirectorySet
“惯用”的 DSL 声明是向后兼容的
sourceSets {
main {
groovy {
// ...
}
}
}
但是,groovy 代码块的返回类型已更改为扩展类型。这意味着以下代码段在 Gradle 7.1 中不再有效
sourceSets {
main {
GroovySourceSet sourceSet = groovy {
// ...
}
}
}
启动脚本需要 bash shell
用于启动 Gradle、Gradle wrapper 以及 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 profiles)的用例,请考虑使用带有条件逻辑的 系统属性。例如,假设在设置文件或构建文件中有一段代码
if (System.getProperty("profile") == "custom") {
println("custom profile")
} else {
println("default profile")
}
您可以将 profile
系统属性传递给 Gradle,使用 gradle -Dprofile=custom
来执行 custom
profile 分支中的代码。
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")
。
compile
任务中已弃用的属性
-
JavaCompile.destinationDir
属性已被弃用。请改用 JavaCompile.destinationDirectory 属性。 -
GroovyCompile.destinationDir
属性已被弃用。请改用 GroovyCompile.destinationDirectory 属性。 -
ScalaCompile.destinationDir
属性已被弃用。请改用 ScalaCompile.destinationDirectory 属性。
非分层项目布局
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 中反映这一点,以下元素现在已被弃用
-
org.gradle.api.internal.HasConvention
(已弃用)
约定的内部用法也已清理(请参阅下面已弃用的项目)。
如果插件作者复制了我们在内部所做的更改,则应迁移到扩展。以下是一些示例
-
迁移插件配置: gradle/gradle#16900。
-
迁移自定义源集: gradle/gradle#17149。
已弃用内部插件配置的消费
一些核心 Gradle 插件声明了插件本身使用的配置,这些配置不应被发布或直接被另一个子项目消费。Gradle 之前没有明确禁止这一点。Gradle 7.1 弃用了这些配置的消费,这将在 Gradle 8.0 中变为错误。
以下插件配置已被弃用,禁止消费
plugin | 已弃用消费的配置 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
如果您的用例需要在另一个项目中消费上述任何配置,请创建一个单独的可消费配置,该配置从内部配置扩展而来。例如
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.plugins.antlr.AntlrSourceVirtualDirectory
(已移除)
客户端应使用其插件特定的配置来配置源
-
groovy
: GroovySourceDirectorySet -
antlr
: AntlrSourceDirectorySet -
scala
: ScalaSourceDirectorySet
例如,以下是如何从插件配置 groovy 源
GroovySourceDirectorySet groovySources = sourceSet.getExtensions().getByType(GroovySourceDirectorySet.class);
groovySources.setSrcDirs(Arrays.asList("sources/groovy"));
注册扩展 ArtifactTransform
的构件转换
当 Gradle 首次引入构件转换时,它使用了基类 ArtifactTransform
来实现它们。Gradle 5.3 引入了接口 TransformAction
来实现构件转换,取代了之前的类 ArtifactTransform
并解决了各种缺点。使用注册方法 DependencyHandler.registerTransform(Action) 注册 ArtifactTransform
已被弃用。请迁移您的构件转换以使用 TransformAction
,并改用 DependencyHandler.registerTransform(Class, Action)。请参阅用户手册,了解有关实现 TransformAction
的更多信息。