Groovy Gradle插件任务上的共享@Input属性,理想情况下为嵌套配置

Groovy Gradle插件任务上的共享@Input属性,理想情况下为嵌套配置,groovy,gradle,Groovy,Gradle,我的gradle插件生成许多具有共享配置的任务。此配置需要标记为@Input,因此当它被更改时,任务将被标记为过时并重新评估。我发现,当配置应用于多个任务时,共享配置很有挑战性。我正在使用规避project.afterEvaluate来允许增量编译。此示例是我目前拥有的内容的简化版本: 当前插件代码: class MyPluginTaskOne extends DefaultTask { @Input config = "default" @TaskAction publ

我的gradle插件生成许多具有共享配置的任务。此配置需要标记为@Input,因此当它被更改时,任务将被标记为过时并重新评估。我发现,当配置应用于多个任务时,共享配置很有挑战性。我正在使用规避
project.afterEvaluate
来允许增量编译。此示例是我目前拥有的内容的简化版本:

当前插件代码:

class MyPluginTaskOne extends DefaultTask {
    @Input config = "default"
    @TaskAction
    public void action() {
        // something that depends on config
    }
}

class MyPluginTaskTwo extends DefaultTask {
    @Input config = "default"
    @TaskAction
    public void action() {
        // something that depends on config
    }
}

class MyPluginExtension {
    // blank for now
}

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("myPluginConfig", MyPluginExtension)
        project.tasks.create(name: 'myPluginTaskOne', type: MyPluginTaskOne) {}
        project.tasks.create(name: 'myPluginTaskTwo', type: MyPluginTaskTwo) {}
    }
}
首选配置:

class MyPluginTaskOne extends DefaultTask {
    @Input config = "default"
    @TaskAction
    public void action() {
        // something that depends on config
    }
}

class MyPluginTaskTwo extends DefaultTask {
    @Input config = "default"
    @TaskAction
    public void action() {
        // something that depends on config
    }
}

class MyPluginExtension {
    // blank for now
}

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("myPluginConfig", MyPluginExtension)
        project.tasks.create(name: 'myPluginTaskOne', type: MyPluginTaskOne) {}
        project.tasks.create(name: 'myPluginTaskTwo', type: MyPluginTaskTwo) {}
    }
}
我想做的是一个类似于以下内容的配置,但具有跟踪@Input依赖项和最新测试的所有好处

myPluginConfig {
    config "SHARED-CONFIG"
    // myPluginTaskOne and myPluginTaskTwo both gets automatic
    // 'SHARED-CONFIG' through Gradle
}
您似乎可以在任务之间自动添加依赖项(请参见下文)。是否可以只配置第一个任务,然后在第二个任务上将@Input滴流到@Input

让我们根据CopySpec.from()如何使用Project.files()计算参数,尝试删除任务依赖项。Gradle可以自动为我们添加任务依赖项。这还会将生成器任务的输出作为输入添加到zip任务中


开始,最常见的约定是使用扩展来执行此操作。看起来你已经开始这么做了。然后,您将在扩展上定义属性,然后您的插件将读取扩展并在所有相关任务上设置属性

myPluginConfig {
    sharedConfig 'value'
}
在您的插件中:

def extension = extensions.create("myPluginConfig", MyPluginExtension)
project.afterEvaluate {
    // read prop from `extension` and set prop on tasks
}

以马克的评论为基础。下面是一个应用于所有任务且无法重写的属性示例(配置)

类MyPluginTaskOne扩展了DefaultTask{
@输入字符串getConfig(){project.mypluginofig.config}
@任务行动
公共无效行动(){
//这取决于配置
}
}
类MyPluginTaskTwo扩展了DefaultTask{
@输入字符串getConfig(){project.mypluginofig.config}
@任务行动
公共无效行动(){
//这取决于配置
}
}
类myplugin{
字符串配置
}
类MyPlugin实现插件{
无效申请(项目){
project.with{
extensions.create(“MyPluginFig”,MyPluginExtension)
创建(名称:'myPluginTaskOne',类型:myPluginTaskOne){}
创建(名称:'myPluginTaskTwo',类型:myPluginTaskTwo){}
}
}
}

我有一个扩展设置,但在调用
.with
期间,它没有从修改的扩展对象获取更新的值。在@biggay的建议下,我从
.afterEvaluate
切换到
.with
。我记不起
.afterEvaluate
的问题了,但我认为是因为它干扰了依赖关系。请看这里:每种方法都有优点/缺点。对于@biggay提到的方法,所讨论的属性不被视为任务输入,因此不用于增量构建支持(您正在尝试实现)。您可以通过向每个任务添加一个getter方法来解决这个问题,该方法返回扩展属性,并使用
@Input
进行注释。问题是该属性实际上是只读的,不能为每个任务单独设置(这可能很好)。
with()
afterEvaluate()
之间的区别在于后者被推迟到项目配置之后。我们非常支持增量构建。有些配置是特定于任务的,有些是共享的,所以我们可以混合使用这些技术。你能概述一下返回带有
@Input
注释的扩展对象的getter方法吗?这听起来很接近我们想要的。这是用于j2objc gradle脚本的,目前运行超过900行。完整脚本:基本上,根据@bigdaz给出的示例,如果您想将扩展属性作为任务的输入,您可以向任务添加一个方法,如so
@input String getToolHome(){project.mypluginfig.toolHome}
。谢谢,我已经尝试了许多变体,但我无法得到正确编译和工作的东西。你能帮我把你的答案改成
project.with
风格,并给出一个工作
@Input String getToolHome(){…}
示例吗。这听起来好像能解决我的问题。谢谢这个@biggay。我成功地重新编写了j2objc gradle插件,输入/输出机制运行良好。
class MyPluginTaskOne extends DefaultTask {
    @Input String getConfig() { project.myPluginConfig.config }
    @TaskAction
    public void action() {
        // something that depends on config
    }
}

class MyPluginTaskTwo extends DefaultTask {
    @Input String getConfig() { project.myPluginConfig.config }
    @TaskAction
    public void action() {
        // something that depends on config
    }
}

class MyPluginExtension {
    String config
}

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.with { 
            extensions.create("myPluginConfig", MyPluginExtension)
            tasks.create(name: 'myPluginTaskOne', type: MyPluginTaskOne) {}
            tasks.create(name: 'myPluginTaskTwo', type: MyPluginTaskTwo) {}
        }
    }
}