预编译脚本插件通常是一个 Kotlin 脚本,它已被编译并作为 Java 类文件打包在库中分发。 这些脚本旨在作为二进制 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'
}

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