Groovy 外掛程式擴展了 Java 外掛程式,以增加對 Groovy 專案的支援。它可以處理 Groovy 程式碼、混合的 Groovy 和 Java 程式碼,甚至純 Java 程式碼(儘管我們不一定建議將其用於後者)。此外掛程式支援聯合編譯,這讓您可以自由地混合和匹配 Groovy 和 Java 程式碼,並在兩個方向上都有相依性。例如,Groovy 類別可以擴展 Java 類別,而 Java 類別又可以擴展 Groovy 類別。這使得可以使用最適合工作的語言,並在需要時以另一種語言重寫任何類別。

請注意,如果您想受益於 API / 實作分離,您也可以將 java-library 外掛程式應用於您的 Groovy 專案。

用法

若要使用 Groovy 外掛程式,請在您的建置腳本中包含以下內容

build.gradle.kts
plugins {
    groovy
}
build.gradle
plugins {
    id 'groovy'
}

任務

Groovy 外掛程式將以下任務新增至專案。關於變更 Java 編譯任務的相依性的資訊,請參閱此處

compileGroovyGroovyCompile

相依於compileJava

編譯生產 Groovy 原始碼檔案。

compileTestGroovyGroovyCompile

相依於compileTestJava

編譯測試 Groovy 原始碼檔案。

compileSourceSetGroovyGroovyCompile

相依於compileSourceSetJava

編譯給定原始碼集的 Groovy 原始碼檔案。

groovydocGroovydoc

為生產 Groovy 原始碼檔案產生 API 文件。

Groovy 外掛程式將以下相依性新增至 Java 外掛程式新增的任務。

表 1. Groovy 外掛程式 - 其他任務相依性
任務名稱 相依於

classes

compileGroovy

testClasses

compileTestGroovy

sourceSetClasses

compileSourceSetGroovy

groovyPluginTasks
圖 1. Groovy 外掛程式 - 任務

專案佈局

Groovy 外掛程式假設 Groovy 佈局中顯示的專案佈局。所有 Groovy 原始碼目錄都可以包含 Groovy Java 程式碼。Java 原始碼目錄可能僅包含 Java 原始碼。[1] 這些目錄都不需要存在或在其中有任何內容;Groovy 外掛程式只會編譯它找到的任何內容。

src/main/java

生產 Java 原始碼。

src/main/resources

生產資源,例如 XML 和屬性檔案。

src/main/groovy

生產 Groovy 原始碼。也可能包含用於聯合編譯的 Java 原始碼檔案。

src/test/java

測試 Java 原始碼。

src/test/resources

測試資源。

src/test/groovy

測試 Groovy 原始碼。也可能包含用於聯合編譯的 Java 原始碼檔案。

src/sourceSet/java

名為 sourceSet 的原始碼集的 Java 原始碼。

src/sourceSet/resources

名為 sourceSet 的原始碼集的資源。

src/sourceSet/groovy

給定原始碼集的 Groovy 原始碼檔案。也可能包含用於聯合編譯的 Java 原始碼檔案。

變更專案佈局

就像 Java 外掛程式一樣,Groovy 外掛程式允許您為 Groovy 生產和測試原始碼檔案配置自訂位置。

build.gradle.kts
sourceSets {
    main {
        groovy {
            setSrcDirs(listOf("src/groovy"))
        }
    }

    test {
        groovy {
            setSrcDirs(listOf("test/groovy"))
        }
    }
}
build.gradle
sourceSets {
    main {
        groovy {
            srcDirs = ['src/groovy']
        }
    }

    test {
        groovy {
            srcDirs = ['test/groovy']
        }
    }
}

相依性管理

由於 Gradle 的建置語言基於 Groovy,因此 Gradle 已經附帶了 Groovy 程式庫。然而,Groovy 專案需要明確宣告 Groovy 相依性。此相依性將在編譯和執行階段類別路徑上使用。它也將用於取得 Groovy 編譯器和 Groovydoc 工具。

如果 Groovy 用於生產程式碼,則應將 Groovy 相依性新增至 implementation 配置

build.gradle.kts
repositories {
    mavenCentral()
}

dependencies {
    implementation("org.codehaus.groovy:groovy-all:2.4.15")
}
build.gradle
repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.codehaus.groovy:groovy-all:2.4.15'
}

如果 Groovy 僅用於測試程式碼,則應將 Groovy 相依性新增至 testImplementation 配置

build.gradle.kts
dependencies {
    testImplementation("org.codehaus.groovy:groovy-all:2.4.15")
}
build.gradle
dependencies {
    testImplementation 'org.codehaus.groovy:groovy-all:2.4.15'
}

若要使用 Gradle 附帶的 Groovy 程式庫,請宣告 localGroovy() 相依性。請注意,不同的 Gradle 版本附帶不同的 Groovy 版本;因此,使用 localGroovy() 不如宣告常規 Groovy 相依性安全。

build.gradle.kts
dependencies {
    implementation(localGroovy())
}
build.gradle
dependencies {
    implementation localGroovy()
}

groovyClasspath 的自動配置

GroovyCompileGroovydoc 任務以兩種方式使用 Groovy 程式碼:在其 classpath 和其 groovyClasspath 上。前者用於定位原始碼引用的類別,並且通常會包含 Groovy 程式庫以及其他程式庫。後者用於載入和執行 Groovy 編譯器和 Groovydoc 工具,並且應僅包含 Groovy 程式庫及其相依性。

除非明確配置任務的 groovyClasspath,否則 Groovy(基礎)外掛程式將嘗試從任務的 classpath 推斷它。這是透過以下方式完成的

  • 如果在 classpath 上找到 groovy-all(-indy) Jar,則該 jar 將新增至 groovyClasspath

  • 如果在 classpath 上找到 groovy(-indy) jar,並且專案至少宣告了一個儲存庫,則對應的 groovy(-indy) 儲存庫相依性將新增至 groovyClasspath

  • 否則,任務的執行將失敗,並顯示一條訊息,指出無法推斷 groovyClasspath

請注意,每個 jar 的 “-indy” 變體是指具有 invokedynamic 支援的版本。

慣例屬性

Groovy 外掛程式不會將任何慣例屬性新增至專案。

原始碼集屬性

Groovy 外掛程式將以下擴展新增至專案中的每個原始碼集。您可以在建置腳本中使用這些屬性,就像它們是原始碼集物件的屬性一樣。

Groovy 外掛程式 — 原始碼集屬性

groovyGroovySourceDirectorySet(唯讀)

預設值:非 null

此原始碼集的 Groovy 原始碼檔案。包含在 Groovy 原始碼目錄中找到的所有 .groovy.java 檔案,並排除所有其他類型的檔案。

groovy.srcDirsSet<File>

預設值[projectDir/src/name/groovy]

包含此原始碼集的 Groovy 原始碼檔案的原始碼目錄。也可能包含用於聯合編譯的 Java 原始碼檔案。可以使用 指定多個檔案 中描述的任何內容進行設定。

allGroovyFileTree(唯讀)

預設值:非 null

此原始碼集的所有 Groovy 原始碼檔案。僅包含在 Groovy 原始碼目錄中找到的 .groovy 檔案。

這些屬性由 GroovySourceSet 類型的慣例物件提供。

Groovy 外掛程式也修改了一些原始碼集屬性

Groovy 外掛程式 - 修改的原始碼集屬性

屬性名稱 變更

allJava

新增在 Groovy 原始碼目錄中找到的所有 .java 檔案。

allSource

新增在 Groovy 原始碼目錄中找到的所有原始碼檔案。

GroovyCompile

Groovy 外掛程式為專案中的每個原始碼集新增一個 GroovyCompile 任務。任務類型與 JavaCompile 任務有很多共同之處,透過擴展 AbstractCompile(請參閱相關的 Java 外掛程式章節)。GroovyCompile 任務支援官方 Groovy 編譯器的大多數配置選項。該任務還可以利用 Java 工具鏈支援

表 2. Groovy 外掛程式 - GroovyCompile 屬性
任務屬性 類型 預設值

classpath

FileCollection

sourceSet.compileClasspath

source

FileTree。可以使用 指定多個檔案 中描述的任何內容進行設定。

sourceSet.groovy

destinationDirectory

File.

sourceSet.groovy.destinationDirectory

groovyClasspath

FileCollection

groovy 配置(如果為非空);否則為在 classpath 上找到的 Groovy 程式庫

javaLauncher

Property<JavaLauncher>,請參閱工具鏈文件

無,但如果在 java 擴展上定義了工具鏈,則將進行配置。

避免編譯

注意:自 Gradle 5.6 以來,Groovy 避免編譯是一個正在孵化的功能。存在已知的不準確性,因此請自行承擔風險啟用它。

若要啟用對 Groovy 避免編譯的孵化支援,請將 enableFeaturePreview 新增至您的設定檔

settings.gradle
enableFeaturePreview('GROOVY_COMPILATION_AVOIDANCE')
settings.gradle.kts
enableFeaturePreview("GROOVY_COMPILATION_AVOIDANCE")

如果相依專案以 ABI 相容的方式(僅其私有 API 已變更)進行了變更,則 Groovy 編譯任務將是最新的。這表示如果專案 A 相依於專案 B,並且 B 中的類別以 ABI 相容的方式(通常,僅變更方法的主體)進行了變更,則 Gradle 不會重新編譯 A

有關不影響 ABI 並被忽略的變更類型詳細清單,請參閱Java 避免編譯

但是,與 Java 的註解處理類似,有多種方法可以自訂 Groovy 編譯過程,實作細節很重要。一些著名的範例是 Groovy AST 轉換。在這些情況下,這些相依性必須在一個名為 astTransformationClasspath 的類別路徑中單獨宣告

build.gradle.kts
val astTransformation by configurations.creating
dependencies {
    astTransformation(project(":ast-transformation"))
}
tasks.withType<GroovyCompile>().configureEach {
    astTransformationClasspath.from(astTransformation)
}
build.gradle
configurations { astTransformation }
dependencies {
    astTransformation(project(":ast-transformation"))
}
tasks.withType(GroovyCompile).configureEach {
    astTransformationClasspath.from(configurations.astTransformation)
}

增量 Groovy 編譯

自 5.6 起,Gradle 引入了一個實驗性的增量 Groovy 編譯器。若要為 Groovy 啟用增量編譯,您需要

buildSrc/src/main/kotlin/myproject.groovy-conventions.gradle.kts
tasks.withType<GroovyCompile>().configureEach {
    options.isIncremental = true
    options.incrementalAfterFailure = true
}
buildSrc/src/main/groovy/myproject.groovy-conventions.gradle
tasks.withType(GroovyCompile).configureEach {
    options.incremental = true
    options.incrementalAfterFailure = true
}

這為您帶來以下好處

  • 增量建置速度更快。

  • 如果僅變更一小部分 Groovy 原始碼檔案,則僅會重新編譯受影響的原始碼檔案。不需要重新編譯的類別在輸出目錄中保持不變。例如,如果您僅變更幾個 Groovy 測試類別,則無需重新編譯所有 Groovy 測試原始碼檔案 — 僅需要重新編譯已變更的檔案。

若要了解增量編譯的工作原理,請參閱增量 Java 編譯以取得詳細概述。請注意,與 Java 增量編譯有幾個不同之處

Groovy 編譯器不會在產生的註解類別位元組碼中保留 @Retention (GROOVY-9185),因此所有註解都是 RUNTIME。這表示對來源保留註解的變更不會觸發完整重新編譯。

已知問題

  • 對資源的變更不會觸發重新編譯,這可能會導致一些不正確 — 例如 擴展模組

為 Java 6 或 Java 7 編譯和測試

透過新增至 GroovyCompile工具鏈支援,可以使用與執行 Gradle 不同的 Java 版本來編譯 Groovy 程式碼。如果您也有 Java 原始碼檔案,這也將配置 JavaCompile 以使用正確的 Java 編譯器,如Java 外掛程式文件中所示。

範例:為 Groovy 配置 Java 7 建置

build.gradle.kts
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(7)
    }
}
build.gradle
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(7)
    }
}

1. Gradle 使用與 Russel Winder 的 Gant 工具引入的相同慣例。