预编译脚本插件通常是已编译并作为 Java 类文件打包在库中的 Kotlin 脚本。这些脚本旨在作为二进制 Gradle 插件使用,并建议作为约定插件使用。

约定插件是一种插件,通常使用您自己的约定(即默认值)配置现有的核心插件和社区插件,例如通过使用 java.toolchain.languageVersion = JavaLanguageVersion.of(17) 设置 Java 版本。约定插件还用于强制执行项目标准并帮助简化构建过程。它们可以应用和配置插件、创建新任务和扩展、设置依赖项等等。

设置插件 ID

预编译脚本的插件 ID 源自其文件名和可选的包声明。

例如,位于 src/main/groovy(或 src/main/kotlin)中且没有包声明的名为 code-quality.gradle(.kts) 的脚本将作为 code-quality 插件公开

buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}
app/build.gradle.kts
plugins {
    id("code-quality")
}
buildSrc/build.gradle
plugins {
    id 'groovy-gradle-plugin'
}
app/build.gradle
plugins {
    id 'code-quality'
}

另一方面,位于 src/main/kotlin/my 中且包声明为 my 的名为 code-quality.gradle.kts 的脚本将作为 my.code-quality 插件公开

buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}
app/build.gradle.kts
plugins {
    id("my.code-quality")
}
Groovy 预编译脚本插件不能有包。

使用扩展使插件可配置

扩展对象在插件中常用,用于向构建脚本公开配置选项和附加功能。

当您应用定义扩展的插件时,您可以访问扩展对象并配置其属性或调用其方法以自定义插件或插件提供的任务的行为。

一个 Project 有一个关联的 ExtensionContainer 对象,其中包含已应用于项目的所有插件的设置和属性。您可以通过向此容器添加扩展对象来为您的插件提供配置。

让我们更新我们的 greetings 示例

buildSrc/src/main/kotlin/greetings.gradle.kts
// Create extension object
interface GreetingPluginExtension {
    val message: Property<String>
}

// Add the 'greeting' extension object to project
val extension = project.extensions.create<GreetingPluginExtension>("greeting")
buildSrc/src/main/groovy/greetings.gradle
// Create extension object
interface GreetingPluginExtension {
    Property<String> getMessage()
}

// Add the 'greeting' extension object to project
def extension = project.extensions.create("greeting", GreetingPluginExtension)

您可以直接使用 extension.message.set("Hi from Gradle,") 设置 message 属性的值。

但是,GreetingPluginExtension 对象将作为项目属性提供,其名称与扩展对象相同。您现在可以像这样访问 message

buildSrc/src/main/kotlin/greetings.gradle.kts
// Where the<GreetingPluginExtension>() is equivalent to project.extensions.getByType(GreetingPluginExtension::class.java)
the<GreetingPluginExtension>().message.set("Hi from Gradle")
buildSrc/src/main/groovy/greetings.gradle
extensions.findByType(GreetingPluginExtension).message.set("Hi from Gradle")

如果您应用 greetings 插件,您可以在构建脚本中设置约定

app/build.gradle.kts
plugins {
    application
    id("greetings")
}

greeting {
    message = "Hello from Gradle"
}
app/build.gradle
plugins {
    id 'application'
    id('greetings')
}

configure(greeting) {
    message = "Hello from Gradle"
}

添加默认配置作为约定

在插件中,您可以使用 project 对象定义默认值,也称为约定

约定属性是使用默认值初始化但可以覆盖的属性

buildSrc/src/main/kotlin/greetings.gradle.kts
// Create extension object
interface GreetingPluginExtension {
    val message: Property<String>
}

// Add the 'greeting' extension object to project
val extension = project.extensions.create<GreetingPluginExtension>("greeting")

// Set a default value for 'message'
extension.message.convention("Hello from Gradle")
buildSrc/src/main/groovy/greetings.gradle
// Create extension object
interface GreetingPluginExtension {
    Property<String> getMessage()
}

// Add the 'greeting' extension object to project
def extension = project.extensions.create("greeting", GreetingPluginExtension)

// Set a default value for 'message'
extension.message.convention("Hello from Gradle")

extension.message.convention(…​) 为扩展的 message 属性设置一个约定。此约定指定 message 的值应默认为 "Hello from Gradle"

如果 message 属性未明确设置,其值将自动设置为 "Hello from Gradle"

将扩展属性映射到任务属性

使用扩展并将其映射到自定义任务的输入/输出属性在插件中很常见。

在此示例中,GreetingPluginExtension 的 message 属性映射到 GreetingTask 的 message 属性作为输入

buildSrc/src/main/kotlin/greetings.gradle.kts
// Create extension object
interface GreetingPluginExtension {
    val message: Property<String>
}

// Add the 'greeting' extension object to project
val extension = project.extensions.create<GreetingPluginExtension>("greeting")

// Set a default value for 'message'
extension.message.convention("Hello from Gradle")

// Create a greeting task
abstract class GreetingTask : DefaultTask() {
    @Input
    val message = project.objects.property<String>()

    @TaskAction
    fun greet() {
        println("Message: ${message.get()}")
    }
}

// Register the task and set the convention
tasks.register<GreetingTask>("hello") {
    message.convention(extension.message)
}
buildSrc/src/main/groovy/greetings.gradle
// Create extension object
interface GreetingPluginExtension {
    Property<String> getMessage()
}

// Add the 'greeting' extension object to project
def extension = project.extensions.create("greeting", GreetingPluginExtension)

// Set a default value for 'message'
extension.message.convention("Hello from Gradle")

// Create a greeting task
abstract class GreetingTask extends DefaultTask {
    @Input
    abstract Property<String> getMessage()

    @TaskAction
    void greet() {
        println("Message: ${message.get()}")
    }
}

// Register the task and set the convention
tasks.register("hello", GreetingTask) {
    message.convention(extension.message)
}
$ gradle -q hello
Message: Hello from Gradle

这意味着对扩展的 message 属性的更改将触发任务被视为过时,确保任务使用新消息重新执行。

您可以在延迟配置中找到有关可用于任务实现和扩展的类型的更多信息。

应用外部插件

为了在预编译脚本插件中应用外部插件,它必须添加到插件构建文件中的插件项目的实现类路径中

buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.bmuschko:gradle-docker-plugin:6.4.0")
}
buildSrc/build.gradle
plugins {
    id 'groovy-gradle-plugin'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.bmuschko:gradle-docker-plugin:6.4.0'
}

然后可以在预编译脚本插件中应用它

buildSrc/src/main/kotlin/my-plugin.gradle.kts
plugins {
    id("com.bmuschko.docker-remote-api")
}
buildSrc/src/main/groovy/my-plugin.gradle
plugins {
    id 'com.bmuschko.docker-remote-api'
}

在这种情况下,插件版本在依赖声明中定义。