Groovy 插件扩展了 Java 插件,以增加对 Groovy 项目的支持。它可以处理 Groovy 代码、混合 Groovy 和 Java 代码,甚至纯 Java 代码(尽管我们不一定建议将其用于后者)。该插件支持 联合编译(joint compilation),这使您可以自由地混合和匹配 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 和 properties 文件。

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 代码:通过它们的 classpathgroovyClasspath。前者用于定位源代码引用的类,通常包含 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 (只读)

默认值: 非空

此源集的 Groovy 源文件。包含 Groovy 源代码目录中找到的所有 .groovy.java 文件,并排除所有其他类型的文件。

groovy.srcDirsSet<File>

默认值: [projectDir/src/name/groovy]

包含此源集的 Groovy 源文件的源代码目录。也可包含用于联合编译的 Java 源文件。可以使用指定多个文件中描述的任何方法进行设置。

allGroovyFileTree (只读)

默认值: 非空

此源集的所有 Groovy 源文件。仅包含 Groovy 源代码目录中找到的 .groovy 文件。

这些属性由类型为 GroovySourceSet 的约定对象提供。

Groovy 插件还修改了一些源集属性

Groovy 插件 - 修改的源集属性

属性名称 变更

allJava

添加 Groovy 源代码目录中找到的所有 .java 文件。

allSource

添加 Groovy 源代码目录中找到的所有源文件。

GroovyCompile

Groovy 插件为项目中的每个源集添加一个 GroovyCompile 任务。该任务类型通过扩展 AbstractCompileJavaCompile 任务有很多共同之处(请参阅相关的 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 扩展上定义了工具链则会被配置。

避免编译

警告:Groovy 避免编译是 Gradle 5.6 以来的孵化特性。已知存在不准确之处,请自行承担风险启用。

要启用 Groovy 避免编译的孵化支持,请在您的 settings 文件中添加 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。这意味着对 source-retention 注解的更改不会触发完全重新编译。

已知问题

  • 资源更改不会触发重新编译,这可能会导致一些不正确的情况 — 例如扩展模块

针对 Java 6 或 Java 7 进行编译和测试

随着 工具链支持 被添加到 GroovyCompile 中,可以使用与运行 Gradle 的 Java 版本不同的 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 工具引入的相同约定。