將您的組建從 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.7
以將專案更新到 8.7。 -
嘗試執行專案並使用疑難排解指南偵錯任何錯誤。
從 7.6 及更早版本升級
現在為錯誤的警告
使用 finalizedBy
、mustRunAfter
或 shouldRunAfter
參照包含建置中的工作
使用下列任何方法參照包含建置中包含的工作現在會導致執行時間錯誤
-
finalizedBy
-
mustRunAfter
-
shouldRunAfter
從沒有備份檔案的資源建立 TAR 樹
從沒有備份檔案的資源建立 TAR 樹不再受支援。請改為將資源轉換為檔案,並對檔案使用 `project.tarTree()`。如需更多資訊,請參閱 從沒有備份檔案的資源建立 TAR 樹。
使用無效的 Java 工具鏈規格
不再支援使用無效的 Java 工具鏈規格。只要確保所有工具鏈規格都設定語言版本,就能避免相關的建置錯誤。如需更多資訊,請參閱 使用者手冊。
在未設定儲存庫的情況下使用自動工具鏈下載
不再支援未明確提供要使用的儲存庫的自動工具鏈下載。如需更多資訊,請參閱 使用者手冊。
設定測試架構選項後變更測試架構現在會產生錯誤
在為 Java、Groovy 和 Scala 專案設定內建測試工作時,Gradle 不再允許你在設定選項後變更 `Test` 工作所使用的測試架構。此功能已標示為不建議使用,因為在某些情況下會靜默捨棄設定。
以下程式碼範例現在會產生錯誤
test {
options {
}
useJUnitPlatform()
}
你可以改為
-
在設定選項之前設定測試架構
-
移轉到 JVM 測試套件外掛程式
test {
// select test framework before configuring options
useJUnitPlatform()
options {
}
}
此外,將測試架構設定為相同架構多次,現在會累積可能設定在架構上的任何選項。之前,每次設定架構時,都會導致架構選項被覆寫。
以下程式碼現在會導致「foo」和「bar」標籤都包含在 test
任務中
test {
useJUnitPlatform {
includeTags("foo")
}
}
tasks.withType(Test).configureEach {
// previously, this would overwrite the included tags to only include "bar"
useJUnitPlatform {
includeTags("bar")
}
}
已移除的 API
舊版 ArtifactTransform API
舊版的 ArtifactTransform
API 已移除。如需更多資訊,請參閱 註冊延伸 ArtifactTransform
的人工產出轉換。
舊版 IncrementalTaskInputs API
舊版的 IncrementalTaskInputs
API 已移除。如需更多資訊,請參閱 IncrementalTaskInputs 類型已棄用。此變更也影響 Kotlin Gradle 外掛和 Android Gradle 外掛。使用 Gradle 8.0 時,您應該使用 Kotlin Gradle 外掛 1.6.10 或更新版本,以及 Android Gradle 外掛 7.3.0 和 android.experimental.legacyTransform.forceNonIncremental=true
屬性或更新版本。
舊版 AntlrSourceVirtualDirectory API
舊版的 AntlrSourceVirtualDirectory
API 已移除。此變更影響 antlr
外掛。在 Gradle 8.0 及更新版本中,請改用 AntlrSourceDirectorySet
來源設定延伸模組。
JvmPluginsHelper
JvmPluginsHelper
類別中已移除一個不需 FileResolver
的已棄用 configureDocumentationVariantWithArtifact
方法。這是一個內部 API,但外掛可能已存取它。請改為提供 FileResolver
給此方法的重載版本。
Groovydoc API 清理
Groovydoc
任務類型的已棄用 isIncludePrivate
屬性已移除。請改用 access
屬性以及 GroovydocAccess#PRIVATE
常數。
JavaApplication API 清理
JavaApplication
介面的已棄用 mainClassName
屬性已移除。請改用 mainClass
屬性。
DefaultDomainObjectSet API 清理
已棄用的 DefaultDomainObjectSet(Class)
建構函式已移除。這是一個內部 API,但外掛可能已使用它。
JacocoPluginExtension API 清理
JacocoPluginExtension
的已棄用 reportsDir
屬性已移除。請改用 reportsDirectory
屬性。
DependencyInsightReportTask API 清理
DependencyInsightReportTask
任務類型的已棄用 legacyShowSinglePathToDependnecy
屬性已移除。請改用 showSinglePathToDependency
屬性。
Report 和 TestReport API 清理
Report
類型的已棄用 destination
和 enabled
屬性已移除。請改用 outputLocation
和 required
屬性。
TestReport
任務類型的已棄用 testResultDirs
屬性已移除。請改用 testResults
屬性。
JacocoMerge 任務已移除
已棄用的 JacocoMerge
任務類型已移除。JacocoReport
任務中也提供相同的功能。
JavaExec API 清理
JavaExec
任務類型的已棄用 main
屬性已移除。請改用 mainClass
屬性。
AbstractExecTask API 清理
AbstractExecTask
任務類型的已棄用 execResult
getter 屬性已移除。請改用 executionResult
getter 屬性。
AbstractTestTask API 清理
AbstractTestTask
任務類型的已棄用 binResultsDir
屬性已移除。請改用 binaryResultsDirectory
屬性。
SourceDirectorySet API 清理
SourceDirectorySet
類型的已棄用 outputDir
屬性已移除。請改用 destinationDirectory
屬性。
VersionCatalog API 清理
已移除 VersionCatalog
類型的已棄用 findDependency(String)
方法和 dependencyAliases
屬性。請改用 findLibrary(String)
方法和 libraryAliases
屬性。
已移除 VersionCatalogBuilder
類型的已棄用 alias(String)
方法。請改用 library(String, String, String)
或 plugin(String, String)
方法。
WorkerExecutor API 清理
已移除 WorkerExecutor
介面的已棄用 submit(Class, Action)
方法。請改用 noIsolation()
、classLoaderIsolation()
和 processIsolation()
方法取得 WorkQueue
,然後改用 WorkQueue
上的 submit(Class, Action)
方法。
DependencySubstitution API 清理
已移除 DependencySubstitution
類型的內部 Substitution
類型的已棄用 with(ComponentSelector)
方法。請改用 using(ComponentSelector)
方法。
AbstractArchiveTask API 清理
已移除 AbstractArchiveTask
任務類型的已棄用 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
屬性。
已解決元件結果 API 清理
ResolvedComponentResult
介面的已棄用 getVariant
方法已移除。請改用 getVariants
方法。
程式碼品質外掛 API 清理
Checkstyle
、CodeNarc
和 Pmd
任務類型的已棄用 antBuilder
屬性已移除。請改用 Project
類型的 ant
屬性。
使用狀況 API 清理
Usage
類型的已棄用公開欄位 JAVA_API_CLASSES
、JAVA_API_JARS
、JAVA_RUNTIME_CLASSES
、JAVA_RUNTIME_JARS
和 JAVA_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<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 的程式碼中發生編譯錯誤。
外掛程式、工作和擴充元件類別為抽象
大多數外掛程式、工作和擴充元件的公開類別已設為抽象。這樣做是為了更容易從 Gradle 的實作中移除樣板程式碼。
受此變更影響的外掛程式也應將其類別設為抽象。Gradle 使用執行時期類別裝飾來實作抽象方法,只要物件是透過 ObjectFactory
或其他自動機制 (例如 管理的屬性) 來實例化。這些方法不應直接實作。
Wrapper 工作設定
如果 gradle-wrapper.properties
包含 distributionSha256Sum
屬性,您必須指定總和。您可以在包裝的工作設定中或使用 --gradle-distribution-sha256-sum
工作選項指定總和。
AbstractCodeQualityPlugin 類別中的變更
已在 Gradle 8.0 中移除已棄用的 AbstractCodeQualityPlugin.getJavaPluginConvention()
方法。您應改用 JavaPluginExtension
。
移除 Gradle 工作的隱式 --add-opens
在 Gradle 8.0 之前,JDK9+ 上的 Gradle 工作會自動開啟 JDK 模組 java.base/java.util
和 java.base/java.lang
,方法是傳遞 --add-opens
CLI 引數。這使在 Gradle 工作中執行的程式碼能夠在沒有警告或失敗的情況下對 JDK 內部執行深入反射。工作不再使用這些隱式引數。
這會影響所有內部 Gradle 工作人員,這些工作人員用於各種任務
-
程式碼品質外掛程式 (Checkstyle、CodeNarc、Pmd)
-
ScalaDoc
-
AntlrTask
-
JVM 編譯器守護程式
-
使用 工作人員 API 透過程序隔離執行的任務
任何使用工作人員 API 深入反映 JDK 內部結構的工具、擴充功能或外掛程式都可能會出現新的警告和錯誤。
這些錯誤可以透過更新違規程式碼或相依性來解決。更新可能包括
-
程式碼品質工具
-
註解處理器
-
任何使用工作人員 API 的 Gradle 外掛程式
有關因這個變更可能產生的錯誤或警告輸出的範例,請參閱 移除測試工作人員的隱式 --add-opens
。
SourceSet classesDirs 不再依賴整個 SourceSet 作為任務相依性
在 Gradle 8.0 之前,SourceSetOutput.classesDirs
的任務相依性包括未產生類別檔案的任務。這表示依賴於 classesDirs
的任務也會依賴於 classes
、processResources
,以及新增至 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
任務依賴於 compileJava
、processResources
和 classes
。現在,只有 compileJava
是 listClassFiles
的任務相依性。
如果建置中的任務依賴於先前的行為,您可以改用整個 SourceSetOutput
作為輸入,其中包含所有類別和資源。
如果這不可行,您可以透過新增更多任務相依性至 classesDirs
來還原先前的行為
java {
sourceSets {
main {
output.classesDirs.builtBy(output)
}
}
}
變更 Kotlin Gradle 外掛的最低支援版本
Gradle 7.x 支援 Kotlin Gradle 外掛 1.3.72 以上版本。Kotlin Gradle 外掛 1.6.21 以上版本未通過 Gradle 7.x 測試。Gradle 8.x 支援 Kotlin Gradle 外掛 1.6.10 以上版本。您可以在 Kotlin 編譯工作中修改語言版本和 API 版本設定,以使用較低版本的 Kotlin 語言。
變更 Android Gradle 外掛的最低支援版本
Gradle 7.x 支援 Android Gradle 外掛 (AGP) 4.1 以上版本。AGP 7.3 以上版本未通過 Gradle 7.x 測試。Gradle 8.x 支援 AGP 8 以上版本。如果您設定下列屬性,Gradle 8.x 支援 AGP 7.3 以上版本
android.experimental.legacyTransform.forceNonIncremental=true
變更為 AntBuilder
父類別
先前,org.gradle.api.AntBuilder
擴充已棄用的 groovy.util.AntBuilder
類別。現在,它擴充 groovy.ant.AntBuilder
。
PluginDeclaration
無法序列化
org.gradle.plugin.devel.PluginDeclaration
無法再序列化。如果您需要序列化,可以將它轉換為您自己的可序列化類別。
Gradle 不會在最新檢查中使用等於運算子來處理序列化值
現在,Gradle 嘗試在最新檢查中比較序列化值時,不會使用等於運算子。如需進一步資訊,請參閱 仰賴等於運算子進行最新檢查已棄用。
Gradle 7.x 中新增的工作和轉換驗證警告現在為錯誤
Gradle 在 Gradle 7.x 系列中引入了其他任務和人工製品轉換驗證警告。這些警告現在在 Gradle 8.0 中為錯誤,並且會導致建置失敗。
成為錯誤的警告
-
無法解析的輸入檔案集合。
-
無法讀取的輸入或輸出檔案或目錄。請參閱 宣告包含無法讀取內容的輸入或輸出目錄。
-
使用 `java.io.File` 作為人工製品轉換的 `@InputArtifact`。
-
使用具有未知實作的輸入。請參閱 無法使用具有未知實作的輸入。
-
任務之間缺少依賴關係。請參閱 任務之間的隱式依賴關係。
-
將檔案轉換為包含檔案分隔符號的路徑的類別路徑。
Gradle 對於具有 `@SkipWhenEmpty` 的檔案樹不會忽略空目錄
以前,Gradle 用於偵測是否註解為 `@SkipWhenEmpty` 的輸入檔案集合僅包含檔案樹,然後自動忽略目錄。若要在 Gradle 8.0 及更新版本中忽略目錄,輸入屬性需要明確註解為 `@IgnoreEmptyDirectories`。如需更多資訊,請參閱 檔案樹和空目錄處理。
`JavaVersion` 的格式已針對 Java 9 和 Java 10 變更
`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`。
`buildSrc` 的 `buildFinished { }` 鉤子在所有工作執行完畢後執行
`buildSrc` 的 `buildFinished {}` 鉤子現在在所有工作完成後執行。在之前的版本中,此鉤子會在 `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` 面向
`eclipse wtp` 外掛程式會將 `jst.utility` 面向新增至 Java 專案。現在,新增 `jst.ejb` 面向會隱式移除 `jst.utility` 面向
eclipse {
wtp {
facet {
facet name: 'jst.ejb', version: '3.2'
}
}
}
簡化 PMD 自訂規則組態
之前,你必須明確組態 PMD 以使用 `ruleSets = []` 忽略預設規則。在 Gradle 8.0 中,將 `ruleSetConfig` 或 `ruleSetFiles` 設定為非空值會隱式忽略預設規則。
報告 `getOutputLocation` 回傳型別已從 Provider 變更為 Property
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 層級 1.8
先前,Kotlin DSL 使用 Kotlin API 層級 1.4。從 Gradle 8.0 開始,Kotlin DSL 使用 Kotlin API 層級 1.8。此變更會套用自 Kotlin 1.4.0 以來對 Kotlin 語言和標準函式庫所做的所有改進。
如需有關此升級中中斷和非中斷變更的資訊,請參閱下列連結至 Kotlin 文件
請注意,Kotlin Gradle 外掛程式 1.8.0 已開始使用 Java 工具鏈。建議您設定工具鏈,而不是在 Kotlin 專案中定義 Java sourceCompatibility
/targetCompatibility
。
另請注意,Kotlin Gradle 外掛程式 1.8.0 引入了具有延遲設定屬性的 compilerOptions
,以取代不支援延遲設定的 kotlinOptions
。建議您使用 compilerOptions
而不是 kotlinOptions
來設定 Kotlin 編譯。
kotlinDslPluginOptions.jvmTarget
已棄用
先前,您可以在使用 kotlin-dsl
外掛程式時,使用 kotlinDslPluginOptions.jvmTarget
來設定編譯程式碼時應使用的 JVM 目標。
從 Gradle 8.0 開始,kotlinDslPluginOptions.jvmTarget
已棄用。您應該改為 設定 Java 工具鏈。
如果您已設定 Java 工具鏈,且 kotlinDslPluginOptions.jvmTarget
未設定,則 Gradle 8.0 現在會使用 Java 工具鏈做為 JVM 目標,而不是先前的預設目標 (1.8)。
Java 基礎外掛程式現在會設定 Jar、War 和 Ear 目標目錄預設值
先前,base
外掛會將 destinationDirectory 的 Jar、War 和 Ear 工作設定為 BasePluginExtension#getLibsDirectory 指定的目錄。在 Gradle 8.0 中,java-base
會處理這個設定。對於已直接或間接透過 java
、application
、java-library
或其他 JVM 生態系統外掛套用 java-base
外掛的專案,不需要變更。
不應使用上傳工作
Upload
工作已過時,目前預計在 Gradle 9.0 中移除。雖然這個類型仍存在,但已不再具有功能,執行時會擲回例外。保留它的唯一目的是避免中斷外掛。請改用 maven-publish
或 ivy-publish
外掛中的工作。
組態不再允許作為相依項
在 dependencies
DSL 區塊中新增組態作為相依項,或使用 DependencyHandler
類別的 doAdd(Configuration, Object, Closure)
方法以程式方式新增,已不再允許,並且會失敗並擲回例外。若要複製此行為的許多面向,請改用 Configuration
上的 extendsFrom(Configuration)
方法來延伸組態。
已標示為不建議用於消耗的組態現在不可消耗
下列組態從未打算被消耗
-
由
AntlrPlugin
建立的antlr
組態 -
由
ScalaBasePlugin
建立的zinc
組態 -
由
WarPlugin
建立的providedCompile
和providedRuntime
組態
這些組態已標示為不建議用於消耗,現在已不可消耗。嘗試消耗它們會導致錯誤。
相同的消耗品配置現在為錯誤
如果專案有多個消耗品配置共用相同的屬性和功能宣告,則在發布或解析為依賴項時,建置會失敗。這項變更先前已標示為不建議使用。
outgoingVariants
報告會對受影響的配置發出警告。
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 來執行。
測試套件中相依性宣告的變更
作為持續發展測試套件的一部分,測試套件 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 開始,設定其他屬性而不指定語言版本的工具鏈規格會被視為無效。無效規格已棄用,且會在 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()
方法及其相關的設定器。這些已棄用的元素將在 Gradle 的未來版本中移除。
在某些組態區塊中,已棄用對外部範圍方法的隱式參照
在 Gradle 7.6 之前,Groovy 腳本允許在會擲出 `MissingMethodException` 的命名容器組態方法中存取根專案組態方法。考慮以下片段,了解此行為的範例
當提供的閉包對於組態而言是無效的組態閉包時,Gradle 允許從 configurations
區塊內存取頂層 repositories
區塊。在此情況下,repositories
閉包執行就像在腳本層級中呼叫一樣,並建立未組態的 repositories
組態
configurations {
repositories {
mavenCentral()
}
someConf {
canBeConsumed = false
canBeResolved = false
}
}
此行為也適用於不會立即執行的閉包。在此情況下,afterResolve
僅在執行 resolve
任務時執行。distributions
閉包是有效的頂層腳本閉包。但它對於組態而言是無效的組態閉包。此範例會立即建立 conf
組態。在 resolve
任務執行期間,distributions
區塊執行就像在腳本層級中宣告一樣
configurations {
conf.incoming.afterResolve {
distributions {
myDist {
contents {}
}
}
}
}
task resolve {
dependsOn configurations.conf
doFirst {
configurations.conf.files() // Trigger `afterResolve`
}
}
從 Gradle 7.6 開始,此行為已棄用。從 Gradle 8.0 開始,此行為將被移除。Gradle 會改為擲出底層的 MissingMethodException
。若要減輕此變更,請考慮以下解決方案
configurations {
conf.incoming.afterResolve {
// Fully qualify the reference.
project.distributions {
myDist {
contents {}
}
}
}
}
configurations {
conf
}
// Extract the script-level closure to the script root scope.
configurations.conf.incoming.afterResolve {
distributions {
myDist {
contents {}
}
}
}
從 7.4 及更早版本升級
已棄用 IncrementalTaskInputs 類型
IncrementalTaskInputs
類型用於實作增量任務,亦即可以最佳化為在變更的輸入子集上執行,而不是整個輸入的任務。此類型有許多缺點。特別是使用此類型時,無法判斷變更與哪個輸入相關聯。
現在您應該改用 InputChanges
類型。請參閱 使用者指南中關於實作增量任務的部分,以取得更多詳細資訊。
潛在的重大變更
版本目錄僅接受單一 TOML 匯入檔案
使用 from
導入方法時,只會接受單一檔案。這表示解析為多個檔案的符號(例如 Project.files(java.lang.Object…) 方法,當傳遞多個檔案時)將導致建置失敗。
預設工具整合版本的更新
-
Checkstyle 已更新至 Checkstyle 8.45.1。
-
JaCoCo 已更新至 0.8.8。
由 eclipse
外掛程式產生的類別路徑檔案已變更
在測試組態中定義的專案相依性會取得 test=true
類別路徑屬性。JVM 測試套件外掛程式定義的所有來源組和相依性在預設情況下也會標記為測試程式碼。現在您可以透過 eclipse
外掛程式 DSL 自訂測試來源組和相依性
eclipse {
classpath {
testSourceSets = [sourcesSets.test, sourceSets.myTestSourceSet]
testConfigurations = [configuration.myTestConfiguration]
}
}
或者,您可以在 eclipse.classpath.file.whenMerged { }
區塊中調整或移除類別路徑屬性。
使用 GPG 指令時,簽署外掛程式預設為 gpg
,而非 gpg2
簽署外掛程式的預設可執行檔 在使用 GPG 指令時 已從 gpg2
變更為 gpg
。此變更的動機是 GPG 2.x 已穩定,而發行版已開始透過不連結 gpg2
可執行檔來進行移轉。
若要設定舊預設值,可以在 gradle.properties
中手動定義可執行檔
signing.gnupg.executable=gpg2
mustRunAfter
約束不再會因 finalizedBy
相依性而遭違反
在之前的 Gradle 版本中,常規工作與最終化工作相依性之間的 mustRunAfter
約束並不會受到重視。
針對具體範例,請考慮下列工作圖形定義
tasks {
register("dockerTest") {
dependsOn("dockerUp") // dependsOn createContainer mustRunAfter removeContainer
finalizedBy("dockerStop") // dependsOn removeContainer
}
register("dockerUp") {
dependsOn("createContainer")
}
register("dockerStop") {
dependsOn("removeContainer")
}
register("createContainer") {
mustRunAfter("removeContainer")
}
register("removeContainer") {
}
}
相關約束為
-
dockerStop
是dockerTest
的最終化作業,因此它必須在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 程式碼。
移除測試工作者的隱式 --add-opens
在 Gradle 7.5 之前,JDK 模組 java.base/java.util
和 java.base/java.lang
會在 JDK9+ 上的測試工作者中自動開啟,方法是傳遞 --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 任務預設使用工具鏈並平行執行
現在,Checkstyle 外掛程式 使用 Gradle 工作人員 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
選項不建議使用
為了保持一致性,這已變更為 --single-path
。API 方法保持不變,這只會影響 CLI。
Groovydoc includePrivate
屬性不建議使用
有一個新的 access
屬性,允許更精細地控制包含在 Groovydoc 中的內容。
在組態時間必須使用基於提供者的 API 來執行外部程序
當啟用組態快取時,使用 Project.exec
、Project.javaexec
,以及標準 Java 和 Groovy API 在組態時間執行外部程序現已不建議使用。這將在 Gradle 8.0 及後續版本中成為錯誤。Gradle 7.5 引入了與組態快取相容的方式,可使用 基於提供者的 API 或 ValueSource
介面的自訂實作來執行外部程序並取得其輸出。 組態快取章節 提供更多詳細資訊,協助您移轉至新的 API。
從 7.3 及更早版本升級
潛在的重大變更
預設工具整合版本的更新
-
PMD 已更新至 PMD 6.39.0。
不建議使用的項目
AdoptOpenJDK 工具鏈下載
在 Eclipse 基金會下,從 AdoptOpenJDK 移轉至 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 的詳細資訊。
組建完成事件
Gradle 組態快取不支援建置完成的監聽器。因此,下列 API 已標示為已棄用,並將在 Gradle 8.0 中移除
請參閱 組態快取章節,以取得如何將這些用法移轉到組態快取支援的 API 的詳細資訊。
從任務動作呼叫 Task.getProject()
從任務動作在執行時間呼叫 Task.getProject() 已標示為已棄用,並將在 Gradle 8.0 中變成錯誤。此方法可在組態時間使用,但建議避免執行此動作。
請參閱 組態快取章節,深入了解如何將這些用法移轉到組態快取支援的 API。
從任務動作呼叫 Task.getTaskDependencies()
從任務動作在執行時間呼叫 Task.getTaskDependencies() 已標示為已棄用,並將在 Gradle 8.0 中變成錯誤。此方法可在組態時間使用,但建議避免執行此動作。
請參閱 組態快取章節,深入了解如何將這些用法移轉到組態快取支援的 API。
在任務中使用建置服務,但未宣告對應的 Task.usesService
Gradle 需要這些資訊,才能適當地遵循建置服務的生命週期及其使用限制。
這將在未來的 Gradle 版本中變成錯誤。
請查看 共用建置服務文件,以取得更多資訊。
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 的 應用程式外掛程式 所產生的啟動指令碼已更新,以避免在攻擊者能夠變更環境變數時,這些指令碼可能用於執行任意程式碼的情況。
您可以使用最新版本的 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
-
動態委派
-
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
用於指定自訂建置檔位置
已被不建議使用。
使用 buildFile 屬性在 GradleBuild 任務中設定自訂建置檔已被不建議使用。
請改用 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=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
的資訊。