將您的建構從 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
參考包含建構中的 tasks
現在,使用以下任何方法參考包含建構中的 tasks 會導致執行時期錯誤
-
finalizedBy
-
mustRunAfter
-
shouldRunAfter
從沒有後端檔案的資源建立 TAR 樹狀結構
不再支援從沒有後端檔案的資源建立 TAR 樹狀結構。請改為將資源轉換為檔案,並對該檔案使用 project.tarTree()
。如需更多資訊,請參閱從沒有後端檔案的資源建立 TAR 樹狀結構。
使用無效的 Java 工具鏈規格
不再支援使用無效的 Java 工具鏈規格。可以透過確保在所有工具鏈規格上設定語言版本來避免相關的建構錯誤。如需更多資訊,請參閱使用者手冊。
在沒有配置 Repository 的情況下使用自動工具鏈下載
不再支援在沒有明確提供要使用的 repositories 的情況下自動下載工具鏈。如需更多資訊,請參閱使用者手冊。
在設定測試框架選項後變更測試框架現在會產生錯誤
在為 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
的 artifact transforms。
舊版 IncrementalTaskInputs API
舊版 IncrementalTaskInputs
API 已被移除。如需更多資訊,請參閱IncrementalTaskInputs 類型已棄用。此變更也影響 Kotlin Gradle Plugin 和 Android Gradle Plugin。使用 Gradle 8.0,您應該使用 Kotlin Gradle Plugin 1.6.10 或更新版本以及 Android Gradle Plugin 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 中移除 Configuration 擴充方法
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 引數清單現在是不可變的。
先前,對傳回清單的修改會被靜默忽略。
可為 Null 的註解能更佳地反映 API 的實際可為 Null 性
在某些 API 中,可為 Null 性未正確註解,並且允許 Null 或傳回 Null 的 API 被標記為不可為 Null。在 Java 或 Groovy 中,這種不符在編譯時期不會造成問題。在 Kotlin 中,這種不符使得編寫有效的程式碼變得困難,因為該語言不允許您傳遞 Null。
一個特別的例子是從 Provider#map
或 Provider#flatMap
傳回 null
。在這兩個 API 中,Gradle 允許您傳回 Null,但在 Kotlin DSL 中,這被認為是非法的。
此修正可能會在預期不可為 Null 的程式碼中造成編譯錯誤。
Plugins、tasks 和擴充類別是抽象的
大多數用於 plugins、tasks 和擴充功能的公開類別都已設為抽象類別。這樣做是為了更輕鬆地從 Gradle 的實作中移除樣板程式碼。
受此變更影響的 plugins 也應將其類別設為抽象類別。Gradle 使用執行時期類別裝飾來實作抽象方法,只要物件是透過 ObjectFactory
或其他自動機制 (例如受管屬性) 實例化。這些方法絕不應直接實作。
Wrapper task 配置
如果 gradle-wrapper.properties
包含 distributionSha256Sum
屬性,您必須指定總和。您可以在 wrapped task 配置中或使用 --gradle-distribution-sha256-sum
task 選項指定總和。
AbstractCodeQualityPlugin 類別中的變更
已在 Gradle 8.0 中移除已棄用的 AbstractCodeQualityPlugin.getJavaPluginConvention()
方法。您應該改用 JavaPluginExtension
。
移除 Gradle workers 的隱含 --add-opens
在 Gradle 8.0 之前,JDK9+ 上的 Gradle workers 會透過傳遞 --add-opens
CLI 引數自動開啟 JDK 模組 java.base/java.util
和 java.base/java.lang
。這使得在 Gradle worker 中執行的程式碼能夠對 JDK 內部組件執行深度反射,而不會出現警告或失敗。 Workers 不再使用這些隱含引數。
這會影響所有內部 Gradle workers,這些 workers 用於各種 tasks
-
程式碼品質外掛程式 (Checkstyle、CodeNarc、Pmd)
-
ScalaDoc
-
AntlrTask
-
JVM 編譯器 daemons
-
透過Worker API使用程序隔離執行的 tasks
使用 worker API 對 JDK 內部組件執行深度反射的任何工具、擴充功能或外掛程式中都可能出現新的警告和錯誤。
可以透過更新違規程式碼或相依性來解決這些錯誤。更新可能包括
-
程式碼品質工具
-
註解處理器
-
任何使用 worker API 的 Gradle 外掛程式
如需可能因這項變更而產生的錯誤或警告輸出的範例,請參閱移除測試 workers 的隱含 --add-opens
。
SourceSet classesDirs 不再將整個 SourceSet 作為 task 相依性
在 Gradle 8.0 之前,SourceSetOutput.classesDirs
的 task 相依性包含不產生類別檔案的 tasks。這表示相依於 classesDirs
的 task 也會相依於 classes
、processResources
以及新增至 SourceSetOutput
的任何其他 task 相依性。此行為可能是一個錯誤,因為 classesDirs
屬性不包含 processResources
的輸出。自 8.0 起,已移除此隱含相依性。現在,相依於 classesDirs
只會執行直接在類別目錄中產生檔案的 tasks。
考慮以下建構腳本
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
作為輸入,其中包含所有類別和資源。
如果這不可行,您可以透過將更多 task 相依性新增至 classesDirs
來還原先前的行為
java {
sourceSets {
main {
output.classesDirs.builtBy(output)
}
}
}
已變更最低支援的 Kotlin Gradle Plugin 版本
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 編譯 tasks 中的語言版本和 api 版本設定來使用較低的 Kotlin 語言版本。
已變更最低支援的 Android Gradle Plugin 版本
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
變更為 AntBuilder
父類別
先前,org.gradle.api.AntBuilder
擴充了已棄用的 groovy.util.AntBuilder
類別。它現在擴充 groovy.ant.AntBuilder
。
PluginDeclaration
不可序列化
org.gradle.plugin.devel.PluginDeclaration
不再可序列化。如果您需要序列化它,您可以將其轉換為您自己的可序列化類別。
Gradle 不會在最新檢查中使用 equals 來比較序列化值
Gradle 現在不會嘗試在使用 equals 比較最新檢查中的序列化值時使用 equals。如需更多資訊,請參閱依賴 equals 進行最新檢查已棄用。
在 Gradle 7.x 中引入的 Task 和轉換驗證警告現在會產生錯誤
Gradle 在 Gradle 7.x 系列中引入了額外的 task 和 artifact 轉換驗證警告。這些警告現在在 Gradle 8.0 中會產生錯誤,並且會導致建構失敗。
變成錯誤的警告
-
無法解析的輸入檔案集合。
-
無法讀取的輸入或輸出檔案或目錄。請參閱宣告包含無法讀取內容的輸入或輸出目錄。
-
將
java.io.File
用作 artifact 轉換的@InputArtifact
。 -
使用實作未知的輸入。請參閱無法使用實作未知的輸入。
-
Tasks 之間缺少相依性。請參閱Tasks 之間的隱含相依性。
-
將檔案轉換為路徑包含檔案分隔符號的類別路徑。
Gradle 不會忽略具有 @SkipWhenEmpty
的檔案樹狀結構的空目錄
先前,Gradle 用於偵測以 @SkipWhenEmpty
註解的輸入檔案集合是否僅由檔案樹狀結構組成,然後自動忽略目錄。若要在 Gradle 8.0 及更高版本中忽略目錄,需要使用 @IgnoreEmptyDirectories
明確註解輸入屬性。如需更多資訊,請參閱檔案樹狀結構和空目錄處理。
Java 9 和 Java 10 的 JavaVersion
格式已變更
JavaVersion
的字串格式已變更為符合官方 Java 版本控制。從 Java 9 開始,語言版本不得包含 1.
前綴。這會影響 JavaCompile
task 和 JavaExtension
上 sourceCompatiblity
和 targetCompatibility
屬性的格式。從字串解析 JavaVersion
時,仍然支援舊格式。
Gradle 7.6 |
Gradle 8.0 |
|
|
|
|
|
|
|
|
預編譯 script plugins 預設使用嚴格的 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 toolchain。建議您配置 toolchain,而不是在 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 Toolchain。
如果您已配置 Java Toolchain 且 kotlinDslPluginOptions.jvmTarget
未設定,則 Gradle 8.0 現在將使用 Java Toolchain 作為 JVM 目標,而不是先前的預設目標 (1.8)。
Java Base Plugin 現在設定 Jar、War 和 Ear 目的地目錄預設值
先前,base
外掛程式將 destinationDirectory of Jar、War 和 Ear 任務配置為 BasePluginExtension#getLibsDirectory 指定的目錄。在 Gradle 8.0 中,java-base
處理此配置。對於已直接或間接透過 java-base
外掛程式或透過 java
、application
、java-library
或其他 JVM 生態系統外掛程式套用專案,不需要進行任何變更。
不應使用 Upload Task
Upload
任務仍然已棄用,現在計劃在 Gradle 9.0 中移除。雖然此類型仍然存在,但它不再起作用,並且在執行時會擲回例外。保留它僅僅是為了避免破壞外掛程式。請改為使用 maven-publish
或 ivy-publish
外掛程式中的任務。
不再允許將 Configuration 作為 Dependencies
不再允許在 dependencies
DSL 區塊中新增 Configuration 作為相依性,或以程式設計方式使用 DependencyHandler
類別的 doAdd(Configuration, Object, Closure)
方法,並且會因例外而失敗。若要複製此行為的許多方面,請改為在 Configuration
上使用 extendsFrom(Configuration)
方法來擴充配置。
已棄用供取用的配置現在不可取用
以下配置從未打算被取用
-
AntlrPlugin
建立的antlr
配置 -
ScalaBasePlugin
建立的zinc
配置 -
WarPlugin
建立的providedCompile
和providedRuntime
配置
這些配置已棄用供取用,現在已不可取用。嘗試取用它們將導致錯誤。
相同的可取用配置現在會導致錯誤
如果專案有多個可取用配置,這些配置共用相同的屬性和功能宣告,則在發布或解析作為該專案的相依性時,建置將會失敗。這先前已棄用。
outgoingVariants
報告將針對受影響的配置發出警告。
適用於 JVM 專案的基於 Toolchain 的任務
從 Gradle 8.0 開始,所有具有 toolchain 支援的核心 Java 任務現在都無條件地使用 toolchain。如果套用了 JavaBasePlugin
,則任務上 tool 屬性的慣例值由在 java
擴充功能上配置的 toolchain 定義。如果沒有明確配置 toolchain,則會使用對應於執行 Gradle 的 JVM 的 toolchain。
同樣地,來自 Groovy 和 Scala 外掛程式的任務也依賴 toolchain 來判斷它們在哪個 JVM 上執行。
Scala 編譯目標
透過上述 toolchain 變更,現在始終為 Scala 編譯任務提供 target
或 release
參數。確切的參數和值取決於 toolchain 的使用情況(或不使用)和 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 現在會發出錯誤。過去,任務將使用預設 toolchain 或執行建置的 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 的相依性宣告。 -
您不能直接使用 bundle 作為相依性宣告 (
implementation(libs.bundles.testing)
)。請改為使用implementation.bundle(libs.bundles.testing)
。
如需更多資訊,請參閱使用者指南的 JVM 測試套件外掛程式章節中更新的宣告其他測試套件範例,以及 DSL 參考中的 DependencyAdder
頁面。
棄用
無效 Java toolchain 規格的使用現在已棄用
除了 Java 語言版本之外,Java toolchain DSL 還允許配置其他準則,例如特定供應商或 VM 實作。從 Gradle 7.6 開始,未指定語言版本而配置其他屬性的 toolchain 規格被視為無效。無效規格已棄用,並將在 Gradle 8.0 中成為建置錯誤。
請參閱使用者手冊中關於 toolchain 配置的更多詳細資訊。
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 測試套件外掛程式定義的所有來源集和相依性也會預設標記為測試程式碼。您現在可以透過 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 程式碼。
移除測試 workers 的隱含 --add-opens
在 Gradle 7.5 之前,JDK 模組 java.base/java.util
和 java.base/java.lang
在 JDK9+ 上的測試 workers 中透過傳遞 --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 有路徑分隔符號的概念,用於分隔路徑列表中的個別路徑,例如類別路徑字串中。個別路徑不得包含路徑分隔符號。因此,對於路徑包含路徑分隔符號的檔案,使用 @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-based APIs 或 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 一起使用,且未來將會需要 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 的詳細資訊。
建置完成事件
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 依賴項更新
-
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 中的工具鏈支援
當在 Scala 中使用工具鏈 時,Scala 編譯器的 -target
選項現在會自動設定。這表示使用 Scala 版本無法以其為目標的 Java 版本,將會導致錯誤。在編譯器選項中提供此標記將停用此行為,並允許使用較高的 Java 版本來編譯為較低的位元組碼目標。
宣告包含無法讀取內容的輸入或輸出目錄
為了進行最新檢查,Gradle 依賴於追蹤任務的輸入和輸出狀態。Gradle 過去會忽略輸入或輸出中無法讀取的檔案,以支援某些用例,儘管它無法追蹤其狀態。在任務上宣告包含無法讀取內容的輸入或輸出目錄已被棄用,這些用例現在透過宣告任務為未追蹤來支援。使用 @UntrackedTask 注釋或 Task.doNotTrackState() 方法來宣告任務為未追蹤。
當您使用 Copy
任務將單個檔案複製到包含無法讀取檔案的目錄中時,請使用方法 Task.doNotTrackState()。
從 7.1 及更早版本升級
潛在的重大變更
應用程式啟動腳本和 Gradle Wrapper 腳本的安全性變更
由於 CVE-2021-32751,gradle
、gradlew
和 Gradle 的 application plugin 產生的啟動腳本已更新,以避免在攻擊者能夠變更環境變數時,這些腳本可能被用於任意程式碼執行的情況。
您可以使用最新版本的 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 作為任務動作
當使用 Java Lambda 實作任務動作時,Gradle 無法追蹤實作,且任務永遠不會是最新的或從建置快取中提供。由於新增此類任務動作很容易,因此現在已棄用使用 Java Lambda 實作的任務動作。請參閱 驗證問題,以取得關於如何修正此問題的更多詳細資訊。
依賴 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 設定檔)的用例,請考慮將 系統屬性 與條件邏輯一起使用。例如,給定設定或建置檔案中的一段程式碼
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")
。
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 中變成錯誤。
以下外掛程式組態已棄用取用
外掛程式 | 已棄用取用的組態 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
如果您的用例需要在另一個專案中取用上述任何組態,請建立一個單獨的可取用組態,該組態從內部組態擴充。例如
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
的資訊。