在约定插件中向 Gradle 项目添加自定义函数

问题描述 投票:0回答:1

Project
的 Gradle api 文档指出,可以通过以下方式向项目添加动态方法:

项目的一个属性,其值为闭包。闭包被视为一种方法,并使用提供的参数进行调用。该房产的位置如上所述。

我猜“如上所述”意味着可以使用动态项目属性。这些在 api 文档中描述为

一个项目有 5 个属性“范围”,它会在其中搜索属性。您可以通过构建文件中的名称或通过调用项目的 property(String) 方法来访问这些属性。范围是:

...

    项目的额外属性。每个项目都维护一个额外属性的映射,其中可以包含任意名称 -> 值对。一旦定义,该范围的属性就是可读可写的。有关更多详细信息,请参阅额外属性。
所以我想我可以写一个约定插件,例如“sayHello.gradle.kts”

// sayhello.gradle.kts val sayHello : (String) -> Unit = { who -> println("Hello $who") } ext.set("sayHello", sayHello)
然后使用我在另一个项目中添加的函数(或 lambda)

build.gradle.kts


// Some projects build.gradle.kts plugins { id("sayHello") } sayHello("René")
但我越来越

Script compilation errors: Line 7: sayHello("") ^ Expression 'sayHello' cannot be invoked as a function. The function 'invoke()' is not found Line 7: sayHello("") ^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public val TaskContainer.sayHello: TaskProvider<DefaultTask> defined in org.gradle.kotlin.dsl
我认为我对 Kotlin DSL 的理解是错误的,并阅读了 

Extra Properties 部分,但这仅显示了值是如何注册的,而不是闭包。

尽管如此,我尝试注册一个类似于示例值的闭包。所以我就这么做了:

val sayHelloFun : (String) -> Unit = { who -> println("Hello $who") } val sayHello by extra(sayHelloFun)
我收到了同样的错误消息。

有谁知道如何使用 Kotlin DSL 将自定义函数添加到约定插件中的

Project

gradle gradle-plugin
1个回答
0
投票
Kotlin DSL 中不支持动态属性访问

不幸的是,无法通过 Kotlin DSL 中的预编译脚本插件以这种方式向

Project

 对象添加函数。文档中涉及“五个项目范围”的
部分预计用户正在编写 Groovy 构建脚本,对于 Kotlin 来说并不严格准确:此类访问依赖于 Groovy 语言的动态功能。 为了证明这一点,请查看有关使用

额外属性

的文档。如果比较 Kotlin 和 Groovy 示例,您会发现所有 Kotlin 额外属性都必须使用属性的字符串名称作为键来访问,例如通过编写 extra["myProperty"],而 Groovy 可以直接访问它们。

替代品

由于 Kotlin 是静态类型的,我们需要一个 Kotlin 编译器可以看到的真实方法。我建议有两种选择:Gradle 扩展和 Kotlin 扩展函数。

Gradle 扩展

当您

创建扩展

时,Gradle 会为该扩展创建一个访问器。您可以使用它在应用插件的项目中创建一个函数,只不过您需要在扩展上调用它而不是直接 Project

// In plugin script
extensions.create<Greeter>("greeter")

abstract class Greeter {
    fun sayHello() {
        println("G'day mate")
    }
}

// In project build.gradle.kts

greeter.sayHello()

Kotlin 扩展函数

这种方法只是利用了 Kotlin 语言的常规

功能

。此类函数必须在 buildscript 类路径上的代码中定义,因此这在预编译脚本插件中不起作用(根据您的问题)。 但是,此类代码可以编写在

buildSrc

文件夹

1
中的常规 Kotlin 文件中。然后你可以简单地做: // In buildSrc/src/main/kotlin/Greeter.kt import org.gradle.api.Project fun Project.sayHello() { println("Howdy, partner") } fun waveGoodbye() { // or a regular function if you don't need the Project object println("Ciao, for now") } // In project build.gradle.kts sayHello() waveGoodbye()


1

此类代码也可以编写在类定义插件的编译中。

© www.soinside.com 2019 - 2024. All rights reserved.