本章節提供您將 Gradle 7.x 建構遷移至 Gradle 8.0 所需的資訊。若要從 Gradle 6.x 或更早版本遷移,請先完成較舊版本的遷移指南

我們建議所有使用者遵循以下步驟

  1. 嘗試執行 gradle help --scan 並檢視產生的建構掃描的棄用檢視

    Deprecations View of a Gradle Build Scan

    這樣您就可以看到任何適用於您建構的棄用警告。

    或者,您可以執行 gradle help --warning-mode=all 以在主控台中查看棄用警告,但它可能不會報告那麼詳細的資訊。

  2. 更新您的外掛程式。

    某些外掛程式會因為這個新版本的 Gradle 而無法運作,例如因為它們使用了已被移除或變更的內部 API。先前的步驟將透過在外掛程式嘗試使用已棄用的 API 部分時發出棄用警告,來協助您識別潛在的問題。

  3. 執行 gradle wrapper --gradle-version 8.13 以將專案更新至 8.13。

  4. 嘗試執行專案並使用問題排解指南偵錯任何錯誤。

從 7.6 及更早版本升級

現在變成錯誤的警告

使用 finalizedBymustRunAftershouldRunAfter 參考包含建構中的 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 類型中已棄用的 destinationenabled 屬性。請改為使用 outputLocationrequired 屬性。

已移除 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 類型中已棄用的 appendixarchiveNamearchivePathbaseNameclassifierdestinationDirextensionversion 屬性。請改為使用 archiveAppendixarchiveFileNamearchiveFilearchiveBaseNamearchiveClassifierdestinationDirectoryarchiveExtensionarchiveVersion 屬性。

IdeaModule API 清理

已移除 IdeaModule 類型中已棄用的 testSourceDirstestResourceDirs 屬性。這會影響 org.gradle.plugins.ide.idea.model.IdeaModule 類型,而不是 org.gradle.tooling.model.idea.IdeaModule 類型。請改為使用 testSourcestestResources 屬性。

AbstractCompile API 棄用

先前已棄用的 AbstractCompiledestinationDir 屬性仍然被棄用,現在使用時會發出棄用警告。它現在計劃在 Gradle 9.0 中移除。請改為使用 destinationDirectory 屬性。

ResolvedComponentResult API 清理

已移除 ResolvedComponentResult 介面中已棄用的 getVariant 方法。請改為使用 getVariants 方法。

程式碼品質外掛程式 API 清理

已移除 CheckstyleCodeNarcPmd task 類型中已棄用的 antBuilder 屬性。請改為使用 Project 類型的 ant 屬性。

Usage API 清理

已移除 Usage 類型中已棄用的公開欄位 JAVA_API_CLASSESJAVA_API_JARSJAVA_RUNTIME_CLASSESJAVA_RUNTIME_JARSJAVA_RUNTIME_RESOURCES。這些值在內部 JavaEcosystemSupport 類別中可用,以與先前發佈的模組相容,但不應用於任何新的發佈。

ExternalDependency API 清理

已移除 ExternalDependency 介面中已棄用的 setForce(boolean) 方法。請改為使用 version(Action) 方法來配置嚴格版本。

從 Kotlin DSL 中移除建構掃描方法

已從 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#mapProvider#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.utiljava.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 也會相依於 classesprocessResources 以及新增至 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 相依於 compileJavaprocessResourcesclasses。現在,只有 compileJavalistClassFiles 的 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 中會產生錯誤,並且會導致建構失敗。

變成錯誤的警告

Gradle 不會忽略具有 @SkipWhenEmpty 的檔案樹狀結構的空目錄

先前,Gradle 用於偵測以 @SkipWhenEmpty 註解的輸入檔案集合是否僅由檔案樹狀結構組成,然後自動忽略目錄。若要在 Gradle 8.0 及更高版本中忽略目錄,需要使用 @IgnoreEmptyDirectories 明確註解輸入屬性。如需更多資訊,請參閱檔案樹狀結構和空目錄處理

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

JavaVersion 的字串格式已變更為符合官方 Java 版本控制。從 Java 9 開始,語言版本不得包含 1. 前綴。這會影響 JavaCompile task 和 JavaExtensionsourceCompatiblitytargetCompatibility 屬性的格式。從字串解析 JavaVersion 時,仍然支援舊格式。

Gradle 7.6

Gradle 8.0

1.8

1.8

1.9

9

1.10

10

11

11

預編譯 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
settings.gradle.kts
includeBuild("nested")
nested/settings.gradle.kts
includeBuild("nestedNested")
.
├── settings.gradle
└── nested
    ├── settings.gradle
    └── nestedNested
        └── settings.gradle
settings.gradle
includeBuild("nested")
nested/settings.gradle
includeBuild("nestedNested")

在 Gradle 8.0 之前,您執行 gradle :nestedNested:compileJava。在 Gradle 8.0 中,調用變更為 gradle :nested:nestedNested:compileJava

使用 eclipse wtp 外掛程式新增 jst.ejb 現在會移除 jst.utility 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 中,將 ruleSetConfigruleSetFiles 設定為非空值會隱含地忽略預設規則。

Report getOutputLocation 傳回類型從 Provider 變更為 Property

ReportoutputLocation 屬性現在傳回類型為 Property<? extends FileSystemLocation> 的值。先前,outputLocation 傳回類型為 Provider<? extends FileSystemLocation> 的值。

此變更使 Report API 在內部更加一致,並允許更符合慣例的報告任務配置。

先前已標記為 @Deprecated 的用法

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

可以替換為

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

許多內建和自訂報告(例如 JUnit 使用的報告)都實作此介面。針對包含先前方法簽名的較早 Gradle 版本編譯的外掛程式可能需要重新編譯,才能與包含新簽名的較新 Gradle 版本一起使用。

已移除外部外掛程式驗證外掛程式

孵化中的外掛程式 ExternalPluginValidationPlugin 已移除。使用 java-gradle-pluginvalidatePlugins 任務來驗證開發中的外掛程式。

與過去版本相比,可重現的封存檔可能會變更

Gradle 將用於建立封存檔的壓縮程式庫從基於 Ant 的程式庫變更為 Apache Commons Compress™。因此,從相同內容建立的封存檔不太可能與使用舊程式庫建立的舊版本在位元組層級上完全相同。

升級至 Kotlin 1.8.10

內嵌的 Kotlin 已更新至 Kotlin 1.8.10。另請參閱 Kotlin 1.8.0 版本說明。如需更多資訊,請參閱 Kotlin 的版本說明

將 Kotlin DSL 更新至 Kotlin API 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 JarWarEar 任務配置為 BasePluginExtension#getLibsDirectory 指定的目錄。在 Gradle 8.0 中,java-base 處理此配置。對於已直接或間接透過 java-base 外掛程式或透過 javaapplicationjava-library 或其他 JVM 生態系統外掛程式套用專案,不需要進行任何變更。

不應使用 Upload Task

Upload 任務仍然已棄用,現在計劃在 Gradle 9.0 中移除。雖然此類型仍然存在,但它不再起作用,並且在執行時會擲回例外。保留它僅僅是為了避免破壞外掛程式。請改為使用 maven-publishivy-publish 外掛程式中的任務。

不再允許將 Configuration 作為 Dependencies

不再允許在 dependencies DSL 區塊中新增 Configuration 作為相依性,或以程式設計方式使用 DependencyHandler 類別的 doAdd(Configuration, Object, Closure) 方法,並且會因例外而失敗。若要複製此行為的許多方面,請改為在 Configuration 上使用 extendsFrom(Configuration) 方法來擴充配置。

已棄用供取用的配置現在不可取用

以下配置從未打算被取用

  • AntlrPlugin 建立的 antlr 配置

  • ScalaBasePlugin 建立的 zinc 配置

  • WarPlugin 建立的 providedCompileprovidedRuntime 配置

這些配置已棄用供取用,現在已不可取用。嘗試取用它們將導致錯誤。

相同的可取用配置現在會導致錯誤

如果專案有多個可取用配置,這些配置共用相同的屬性和功能宣告,則在發布或解析作為該專案的相依性時,建置將會失敗。這先前已棄用

outgoingVariants 報告將針對受影響的配置發出警告。

適用於 JVM 專案的基於 Toolchain 的任務

從 Gradle 8.0 開始,所有具有 toolchain 支援的核心 Java 任務現在都無條件地使用 toolchain。如果套用了 JavaBasePlugin,則任務上 tool 屬性的慣例值由在 java 擴充功能上配置的 toolchain 定義。如果沒有明確配置 toolchain,則會使用對應於執行 Gradle 的 JVM 的 toolchain。

同樣地,來自 Groovy 和 Scala 外掛程式的任務也依賴 toolchain 來判斷它們在哪個 JVM 上執行。

Scala 編譯目標

透過上述 toolchain 變更,現在始終為 Scala 編譯任務提供 targetrelease 參數。確切的參數和值取決於 toolchain 的使用情況(或不使用)和 Scala 版本。

請參閱 Scala 外掛程式文件以了解詳細資訊。

Plugin Publish 外掛程式中已捨棄 pluginBundle

Gradle 8 不再支援 pluginBundle 擴充功能。其功能已合併到 gradlePlugin 區塊中。這些變更需要 Plugin Publish 外掛程式的最新版本 (1.0.+)。關於配置外掛程式發布的文件可以在 Portal 上使用者手冊中找到。

從 7.5 和更早版本升級

AttributeSchema.setAttributeDisambiguationPrecedence(List)AttributeSchema.getAttributeDisambiguationPrecedence() 方法現在接受並傳回 List 而不是 Collection,以更好地表明這些集合中元素的順序非常重要。

嚴格 Kotlin DSL 預編譯腳本外掛程式存取器產生

如果在此類預編譯腳本中請求的外掛程式套用失敗,則預編譯腳本外掛程式的類型安全 Kotlin DSL 存取器產生預設不會導致建置失敗。由於原因可能是環境性的,並且為了向後相容性,此行為尚未變更。

早在 Gradle 7.1 中,負責存取器產生的 :generatePrecompiledScriptPluginAccessors 任務已預設標記為不可快取。引入了 org.gradle.kotlin.dsl.precompiled.accessors.strict 系統屬性,以便選擇加入更嚴格的操作模式,該模式在外掛程式套用失敗時會導致建置失敗,並為該任務啟用建置快取。

從 Gradle 7.6 開始,Kotlin DSL 預編譯腳本外掛程式的非嚴格存取器產生已被棄用。這將在 Gradle 8.0 中變更。嚴格存取器產生將成為預設設定。若要選擇加入嚴格行為,請將 'org.gradle.kotlin.dsl.precompiled.accessors.strict' 系統屬性設定為 true

這可以在建置根目錄的 gradle.properties 檔案中持久實現

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

潛在的重大變更

升級至 Kotlin 1.7.10

內嵌的 Kotlin 已更新至 Kotlin 1.7.10

Gradle 不隨附 kotlin-gradle-plugin,但升級至 1.7.10 可以帶來新版本。例如,當您使用 kotlin-dsl 外掛程式時。

kotlin-gradle-plugin 版本 1.7.10 變更了 KotlinCompile 任務類型的類型階層。它不再從 AbstractCompile 擴充。如果您過去使用 AbstractCompile 選取 Kotlin 編譯任務,則需要將其變更為 KotlinCompile

例如,此

tasks.named<AbstractCompile>("compileKotlin")

需要變更為

tasks.named<KotlinCompile>("compileKotlin")

同樣地,如果您過去使用 AbstractCompile 篩選任務,您將不再獲得 Kotlin 編譯任務

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

需要變更為

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

升級至 Groovy 3.0.13

Groovy 已更新至 Groovy 3.0.13

由於先前的版本為 3.0.10,因此也包含 3.0.113.0.12 的變更。

升級至 CodeNarc 3.1.0

CodeNarc 的預設版本已更新至 3.1.0

升級至 PMD 6.48.0

PMD 已更新至 PMD 6.48.0

配置不存在的可執行檔現在會失敗

當為 JavaCompileTest 任務明確配置可執行檔時,如果此可執行檔不存在,Gradle 現在會發出錯誤。過去,任務將使用預設 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 中的替換集合

testResourcesDirstestSourcesDirs 欄位及其 getter 和 setter 已棄用。將用法替換為現在穩定的 getTestSources()getTestResources() 方法及其各自的 setter。這些新方法傳回並由 ConfigurableFileCollection 實例支援,以提高使用彈性。Gradle 現在會在使用這些已棄用的方法時發出警告。它們將在 Gradle 的未來版本中移除。

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

getDestinationDir()setDestinationDir(File)getTestResultDirs()setTestResultDirs(Iterable) 方法已棄用。將用法替換為現在穩定的 getDestinationDirectory()getTestResults() 方法及其相關的 setter。這些已棄用的元素將在 Gradle 的未來版本中移除。

在某些配置區塊中,對容器配置閉包中外部範圍方法的已棄用隱含參考

在 Gradle 7.6 之前,Groovy 腳本允許在擲回 `MissingMethodException` 的命名容器配置方法中存取根專案配置方法。請考慮以下程式碼片段,以了解此行為的範例

當提供的閉包在其他方面是 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…) 方法) 將導致建置失敗。

預設工具整合版本的更新

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") {
    }
}

相關約束為

  • dockerStopdockerTest 的 finalizer,因此必須在 dockerTest 之後執行;

  • removeContainerdockerStop 的相依性,因此必須在 dockerStop 之前執行;

  • createContainer 必須在 removeContainer 之後執行;

在 Gradle 7.5 之前,gradle dockerTest 將產生以下執行順序,這違反了 :createContainer:removeContainer 之間的 mustRunAfter 約束

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

從 Gradle 7.5 開始,mustRunAfter 約束將完全被遵守,產生以下執行順序

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

Scala Zinc 版本已更新至 1.6.1

Zinc 是 Scala 增量編譯器,它允許 Gradle 始終編譯目前檔案變更所需的最少檔案集。它會考慮正在使用的方法和已變更的方法,這表示它比僅限於檔案間相依性更精細。

Zinc 版本已更新至最新的可用版本,以便從所有最新的錯誤修正中受益。因此,如果您使用 zincVersion 設定,建議您移除它並僅使用預設版本,因為 Gradle 僅能使用設定為 1.6.x 或更高版本的 Zinc 版本編譯 Scala 程式碼。

移除測試 workers 的隱含 --add-opens

在 Gradle 7.5 之前,JDK 模組 java.base/java.utiljava.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.langjava.base/java.util 模組來還原舊行為

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

如果您正在開發 Gradle 外掛程式,ProjectBuilder 依賴於 java.base/java.lang 模組中的反射。當套用 java-gradle-plugin 外掛程式時,Gradle 將自動將適當的 --add-opens 旗標新增至測試。

如果您使用 TestNG,則 5.14.6 之前的版本會執行非法反射。更新至至少 5.14.6 應該可以修正不相容問題。

Checkstyle 任務預設使用 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.execProject.javaexec 以及標準 Java 和 Groovy API 來執行外部程序,現在已被棄用。在 Gradle 8.0 及更高版本中將會變成錯誤。Gradle 7.5 引入了與配置快取相容的方式,透過 provider-based APIsValueSource 介面的自訂實作,來執行外部程序並取得其輸出。配置快取章節 有更多詳細資訊,可協助您遷移至新的 API。

從 7.3 及更早版本升級

棄用

AdoptOpenJDK 工具鏈下載

隨著 AdoptOpenJDK 轉移到 Eclipse 基金會下的 Adoptium,已無法再從其端點下載 AdoptOpenJDK 建置版本。取而代之的是,會回傳 Eclipse Temurin 或 IBM Semeru 建置版本。

當在 工具鏈規範 中指定 AdoptOpenJDK 供應商,且自動佈建使用該供應商時,Gradle 7.4+ 現在會發出棄用警告。如果您必須使用 AdoptOpenJDK,則應關閉自動下載。如果 Eclipse Temurin 或 IBM Semeru 建置版本適用於您,請指定 JvmVendorSpec.ADOPTIUMJvmVendorSpec.IBM 作為供應商,或讓供應商保持未指定狀態。

檔案樹狀結構與空目錄處理

當在輸入檔案集合上使用 @SkipWhenEmpty 時,Gradle 會在判斷輸入為空時略過任務。如果輸入檔案集合僅包含檔案樹狀結構,Gradle 會忽略目錄以進行空性檢查。但是,當檢查輸入檔案集合的變更時,只有在存在 @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 中移除。用戶端應直接移除此呼叫。

此呼叫對於外部值的 Provider 是強制性的,例如 系統屬性環境變數Gradle 屬性檔案內容,這些值旨在與配置快取功能一起在配置時間使用。

從 7.4 版開始,Gradle 將隱式地將在配置時間使用的外部值視為配置快取輸入。

用戶端也可以自由使用標準 Java API(例如 System#getenv 讀取環境變數、System#getProperty 讀取系統屬性)以及 Gradle API(例如 Project#property(String)Project#findProperty(String) 讀取配置時間的 Gradle 屬性)。基於 Provider 的 API 仍然是將外部值連接到任務輸入的建議方式,以最大化配置快取的重複使用率。

任務執行監聽器和事件

Gradle 配置快取不支援直接存取 TaskProject 實例的監聽器和事件,這讓 Gradle 能夠平行執行任務,並在配置快取中儲存最少量資料。為了朝向無論配置快取是否啟用,API 皆保持一致的方向發展,以下 API 已棄用,並將在 Gradle 8.0 中移除或變成錯誤

請參閱 配置快取章節,以取得關於如何將這些用法遷移至配置快取支援的 API 的詳細資訊。

建置完成事件

Gradle 配置快取不支援建置完成監聽器。因此,以下 API 已棄用,並將在 Gradle 8.0 中移除

請參閱 配置快取章節,以取得關於如何將這些用法遷移至配置快取支援的 API 的詳細資訊。

從任務動作中呼叫 Task.getProject()

在執行時間從任務動作中呼叫 Task.getProject() 現在已被棄用,並將在 Gradle 8.0 中變成錯誤。此方法可以在配置時間使用,但建議避免這樣做。

請參閱 配置快取章節,以取得關於如何將這些用法遷移至配置快取支援的 API 的詳細資訊。

從任務動作中呼叫 Task.getTaskDependencies()

在執行時間從任務動作中呼叫 Task.getTaskDependencies() 現在已被棄用,並將在 Gradle 8.0 中變成錯誤。此方法可以在配置時間使用,但建議避免這樣做。

請參閱 配置快取章節,以取得關於如何將這些用法遷移至配置快取支援的 API 的詳細資訊。

從任務中使用建置服務而未明確宣告使用方式

Gradle 需要此資訊,以便正確地遵循建置服務生命週期及其使用限制。

這將在未來的 Gradle 版本中變成錯誤。

這可以透過透過 @ServiceReference 屬性(自 8.0 起)取用服務,或透過在任務上調用 usesService()(自 6.1 起)來完成。

請查看 共用建置服務文件 以取得更多資訊。

VersionCatalog 和 VersionCatalogBuilder 棄用

VersionCatalogVersionCatalogBuilder 中的某些方法現在已棄用,並計劃在 Gradle 8.0 中移除。受影響方法的 JavaDoc 中可以找到特定的取代方案。

這些方法的變更旨在提高 libs.versions.toml 檔案與 API 類別之間的一致性。

從 7.2 及更早版本升級

潛在的重大變更

捆綁的 Gradle 依賴項更新

plugins 區塊中外掛程式的應用順序

plugins 區塊中的外掛程式實際應用順序不一致,並且取決於外掛程式加入類別路徑的方式。

現在外掛程式始終按照它們在 plugins 區塊中宣告的相同順序應用,這在極少數情況下可能會變更現有建置的行為。

排除對依賴項解析中取代的依賴項的影響

在此版本之前,依賴項取代目標無法從依賴項圖表中排除。這是因為在執行取代之前檢查排除項所導致的。現在 Gradle 也將檢查取代結果的排除項。

版本目錄

產生的存取器不再提供對類型不安全 API 的存取。您必須改用 版本目錄擴充功能

Scala 中的工具鏈支援

當在 Scala 中使用工具鏈 時,Scala 編譯器的 -target 選項現在會自動設定。這表示使用 Scala 版本無法以其為目標的 Java 版本,將會導致錯誤。在編譯器選項中提供此標記將停用此行為,並允許使用較高的 Java 版本來編譯為較低的位元組碼目標。

宣告包含無法讀取內容的輸入或輸出目錄

為了進行最新檢查,Gradle 依賴於追蹤任務的輸入和輸出狀態。Gradle 過去會忽略輸入或輸出中無法讀取的檔案,以支援某些用例,儘管它無法追蹤其狀態。在任務上宣告包含無法讀取內容的輸入或輸出目錄已被棄用,這些用例現在透過宣告任務為未追蹤來支援。使用 @UntrackedTask 注釋或 Task.doNotTrackState() 方法來宣告任務為未追蹤。

當您使用 Copy 任務將單個檔案複製到包含無法讀取檔案的目錄中時,請使用方法 Task.doNotTrackState()

從 7.1 及更早版本升級

潛在的重大變更

應用程式啟動腳本和 Gradle Wrapper 腳本的安全性變更

由於 CVE-2021-32751gradlegradlew 和 Gradle 的 application plugin 產生的啟動腳本已更新,以避免在攻擊者能夠變更環境變數時,這些腳本可能被用於任意程式碼執行的情況。

您可以使用最新版本的 Gradle 來產生 gradlew 腳本,並使用它來執行舊版本的 Gradle。

對於大多數使用者來說,這應該是透明的;但是,對於依賴環境變數 JAVA_OPTSGRADLE_OPTS 傳遞具有複雜引號逸出參數的 Gradle 建置,可能會發生變更。如果您懷疑某些變更已損壞您的建置,且您找不到解決方案,請聯絡我們。

捆綁的 Gradle 依賴項更新

棄用

使用 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

來源集擴充功能的傳回類型已變更

以下來源集透過具有自訂類型的擴充功能貢獻

「慣用」的 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=customprofile 系統屬性傳遞給 Gradle,以執行 custom 設定檔分支中的程式碼。

Substitution.with 已由 Substitution.using 取代

使用 with 方法的 依賴項取代 已棄用,並由也允許鏈式調用的 using 方法取代。例如,依賴項取代規則 substitute(project(':a')).with(project(':b')) 應取代為 substitute(project(':a')).using(project(':b'))。透過鏈式調用,您可以新增取代原因,例如:substitute(project(':a')).using(project(':b')).because("a reason")

JavaExec 任務中已棄用的屬性

非階層式專案版面配置

Gradle 7.1 棄用了子專案位於專案根目錄外部的專案版面配置。但是,根據 社群回饋,我們決定在 Gradle 7.4 中撤回並移除了棄用。因此,Settings.includeFlat() 方法僅在 Gradle 7.1、7.2 和 7.3 中棄用。

已棄用的 Upload 任務

Gradle 過去有兩種發布成品的方式。現在,情況已經釐清,所有建置都應使用 maven-publish 外掛程式。舊式發布方式的最後一個殘留物是 Upload 任務,該任務已棄用,並計劃在 Gradle 8.0 中移除。現有的用戶端應遷移至 maven-publish 外掛程式

已棄用的慣例

慣例的概念已過時,並被擴充功能取代。為了在 Gradle API 中反映這一點,以下元素現在已棄用

慣例的內部用法也已清理(請參閱以下已棄用的項目)。

如果外掛程式作者複製了我們在內部完成的變更,請遷移至擴充功能。以下是一些範例

已棄用內部外掛程式組態的取用

某些核心 Gradle 外掛程式會宣告外掛程式本身使用的組態,這些組態不應發布或由另一個子專案直接取用。Gradle 沒有明確禁止這樣做。Gradle 7.1 棄用了這些組態的取用,這將在 Gradle 8.0 中變成錯誤。

以下外掛程式組態已棄用取用

外掛程式 已棄用取用的組態

codenarc

codenarc

pmd

pmd

checkstyle

checkstyle

antlr

antlr

jacoco

jacocoAntjacocoAgent

scala

zinc

war

providedCompileprovidedRuntime

如果您的用例需要在另一個專案中取用上述任何組態,請建立一個單獨的可取用組態,該組態從內部組態擴充。例如

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 中移除

用戶端應使用其外掛程式特定的配置來配置來源

例如,以下說明如何從外掛程式配置 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 的資訊。