Gradle 插件任务上的共享 @Input 属性,最好是嵌套配置

Shared @Input properties on Gradle Plugin tasks, ideally nested config

我的 gradle 插件生成了许多具有共享配置的任务。此配置需要标记为@Input,因此当它发生更改时,任务将被标记为过时并重新评估。我发现在应该应用于多个任务时共享配置具有挑战性。我正在使用 avoiding 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) {}
    }
}

当前配置:

目前我必须共享状态的最佳方式如下。这有一个问题是它容易出错并且不会自动共享设置:

apply plugin: MyPlugin

// Kludgy way of sharing configuration across two tasks:
def sharedConfig = "SHARED-CONFIG"

myPluginTaskOne {
    config sharedConfig
}

myPluginTaskTwo {
    config sharedConfig
}

首选配置:

我想做的是类似下面的配置,但具有跟踪@Input 依赖项和最新测试的所有好处。

myPluginConfig {
    config "SHARED-CONFIG"
    // myPluginTaskOne and myPluginTaskTwo both gets automatic
    // 'SHARED-CONFIG' through Gradle
}

您似乎可以自动添加任务之间的依赖关系(见下文)。是否可以仅配置第一个任务,然后让 @Input 滴入第二个任务的 @Input?

让我们尝试根据 CopySpec.from() 如何使用 Project.files() 评估参数来删除任务依赖性。 Gradle可以自动为我们添加任务依赖。这还将生成器任务的输出添加为 zip 任务的输入。

来自https://gradle.org/feature-spotlight-incremental-builds/

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

myPluginConfig {
    sharedConfig 'value'
}

在您的插件中:

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

以 Mark 的评论为基础。这是一个适用于所有任务且不能被覆盖(配置)的 属性 示例。

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) {}
        }
    }
}