gradle扩展可以处理属性的懒惰评估吗? [英] Can gradle extensions handle lazy evaluation of a property?

查看:168
本文介绍了gradle扩展可以处理属性的懒惰评估吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个自定义gradle插件来处理一些模糊复杂的工作,并且在使用属性来配置该插件所应用的一些任务时遇到了令人沮丧的问题。

apply plugin:myPlugin

//提供应用插件的属性
myPluginProps {
message =Hello
}

//定义直接使用自定义任务的任务
任务thisTaskWorksFine(type:MyTask){
input = myPluginProps.message
}

//定义一个插件,它将应用我自定义类型的任务
class MyPlugin implements Plugin< Project> {
void apply(Project project){
project.extensions.create('myPluginProps',MyPluginExtension)

project.task(类型:MyTask,'thisTaskWorksIncorrectly'){
input = project.myPluginProps.message
}
}
}

//我的自定义插件用来获取输入的扩展名
class MyPluginExtension {
def字符串消息
}

//标准构建部分和插件使用的任务
class MyTask extends DefaultTask {
def字符串输入

@TaskAction
def action(){
println你给了我这个:$ {input}
}
}

使用此文件的结果如下所示:

<$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
建立成功

我认为这是非常意外的。在我看来,从插件中应用任务并直接写入一个任务应该在给定相同输入时产生相同的输出。在这种情况下,两个任务都被赋予 myPluginProps.message 作为输入,但插件应用的任务是贪婪的,并且在早期评估为null。 (在申请阶段?)

我发现的唯一解决方案是在插件任务的配置块中使用闭包,如下所示:

  //定义一个插件,它将应用我自定义类型的任务
class MyPlugin implements Plugin< Project> {
void apply(Project project){
project.extensions.create('myPluginProps',MyPluginExtension)

project.task(类型:MyTask,'thisTaskWorksIncorrectly'){
input = {project.myPluginProps.message}
}
}
}

这样可以很好地解决贪婪评估问题,除了 现在必须修改自定义任务以期望和处理闭包。这样做并不难,但我认为解决封闭问题不应该是任务的责任,因为插件是责备的。



我在这里错误地使用扩展名吗?还是他们不够?官方的立场似乎是我们应该使用扩展,但我还没有找到任何扩展可以做的例子我需要的。我可以继续使用闭包和编写一堆模板getter,它可以处理闭包和正常类型的封闭eval和setter,但它似乎非常违背groovy和gradle的哲学。如果有一种方法可以使用扩展并自动获得懒惰评估,我会非常高兴。 解决方案

通常的解决方案这个问题是使用约定映射:

  class MyPlugin implements Plugin< Project> ; {
void apply(Project project){
project.extensions.create('myPluginProps',MyPluginExtension)

project.task(类型:MyTask,'thisTaskWorksIncorrectly'){
conventionMapping.input = {project.myPluginProps.message}
}
}
}

然后在任务中:
$ b

class MyTask extends DefaultTask {
def字符串输入

@TaskAction
def action(){
println你给了我这个:$ {getInput()}
}

}



请注意, getter for input - 如果直接引用该字段,约定映射将不会启动。


I'm writing a custom gradle plugin to handle some vaguely complicated work and I have run into a frustrating problem while using properties to configure some of the tasks that the plugin applies.

apply plugin: myPlugin

//Provide properties for the applied plugin
myPluginProps {
    message = "Hello"
}

//Define a task that uses my custom task directly
task thisTaskWorksFine(type: MyTask) {
    input = myPluginProps.message
}

//Define a plugin that will apply a task of my custom type
class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create('myPluginProps', MyPluginExtension)

        project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
            input = project.myPluginProps.message
        }
    }
}

//The extension used by my custom plugin to get input
class MyPluginExtension {
    def String message
}

//The task used by both the standard build section and the plugin
class MyTask extends DefaultTask {
    def String input

    @TaskAction
    def action() {
        println "You gave me this: ${input}"
    }
}

The results from using this file are as follows:

$ gradle thisTaskWorksFine thisTaskWorksIncorrectly
:thisTaskWorksFine
You gave me this: Hello
:thisTaskWorksIncorrectly
You gave me this: null

BUILD SUCCESSFUL

I consider this to be very unexpected. To my mind, applying a task from the plugin and writing one directly should result in the same output when given the same input. In this case, both tasks are given myPluginProps.message as input, but the task applied by the plugin is greedy and evaluates to null early on. (During the apply phase?)

The only solution I have found is to use closures in the plugin task's configuration block like so:

//Define a plugin that will apply a task of my custom type
class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create('myPluginProps', MyPluginExtension)

        project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
            input = { project.myPluginProps.message }
        }
    }
}

That solves the greedy evaluation problem pretty nicely except that now the custom task has to be modified to expect and deal with a closure. It's not terrifically hard to do, but I don't think it should be the task's responsibility to deal with the closure, since the plugin is "to blame".

Am I using extensions incorrectly here? Or are they just not adequate? The official stance appears to be that we should use extensions but I've yet to find any examples where extensions could do what I need. I can move forward with my use of closures and writing a bunch of boilerplate getters that do closure eval and setters that can handle closures and normal types, but it seems very against the philosophy of groovy and therefore gradle. I would be very happy if there is a way that I can use extensions and get the lazy evaluation automatically.

解决方案

The usual solution for this problem is to use convention mapping:

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
       project.extensions.create('myPluginProps', MyPluginExtension)

        project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
            conventionMapping.input = { project.myPluginProps.message }
        }
    }
}

and then in the task:

class MyTask extends DefaultTask {
    def String input

    @TaskAction
    def action() {
        println "You gave me this: ${getInput()}"
    }

}

Please note that I explicitly used getter for input - the convention mapping won't kick in if you reference the field directly.

这篇关于gradle扩展可以处理属性的懒惰评估吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆