当前位置: 首页 > 知识库问答 >
问题:

基于属性值的动态任务依赖关系

袁宜
2023-03-14

我需要创建一个插件,提供一个交互式任务,调用方式如下:

> ./gradlew analyzeSomething --configuration compileClasspath

在这里,-配置参数应该是用于分析的项目中的配置的名称。

然而,这种分析需要从配置中计算一些数据,这可能很昂贵。因此,我想缓存这些数据,但是,很自然,在配置内容发生变化(例如用户添加了依赖项)的情况下,缓存会失效。理想情况下,我会利用内置的Gradle任务依赖机制,它将跟踪任务依赖关系,并允许不运行计算,除非其输入发生变化。

这是我想出的解决方案,但不起作用。首先,在AnalyzeWhat类中声明两个属性:

abstract class AnalyzeSomethingTask : DefaultTask() {
    @get:Internal
    @get:Option(option = "configuration", description = "Configuration")
    abstract val configuration: Property<String>

    @get:Internal
    abstract val dataCacheFile: RegularFileProperty
}

其次,创建一个任务规则来实例化执行昂贵计算的任务:

abstract class PrecomputeTask : DefaultTask() {
    @get:InputFiles
    abstract val classpath: ConfigurableFileCollection

    @get:OutputFile
    abstract val outputFile: RegularFileProperty
}

project.tasks.addRule("Pattern precompute<Configuration>") {
    val taskName = this
    if (taskName.startsWith("precompute")) {
        val configurationName = taskName.removePrefix("precompute").decapitalize()
        val configuration = project.configurations.getByName(configurationName)
        project.tasks.register<PrecomputeTask>(taskName) {
            classpath.from(configuration)
            outputFile.set(temporaryDir.resolve("data.txt"))
        }
    }
}

最后,在项目中创建analyzeSomething任务。AfterEvalueblock(因此任务的所有属性都已设置,包括命令行上的属性)在analyzeSomething和规则生成的任务之一之间建立依赖关系:

val analyzeSomething = project.tasks.register<AnalyzeSomethingTask>("analyzeSomething")
project.afterEvaluate {
    analyzeSomething.configure {
        val precomputeTaskName = "precompute" + configuration.get().capitalize()
        dataCacheFile.set(
            project.tasks.named<PrecomputeTask>(precomputeTaskName)
                .flatMap { it.outputFile }
        )
    }
}

但是,这种方法不起作用,因为显然在这种设置中,无论在什么时候调用register()和任何其他集合配置方法,都无法调用它们:

> ./gradlew analyzeSomething --configuration runtimeClasspath
Caused by: org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreationException: Could not create task ':analyzeSomething'.
...
Caused by: org.gradle.api.internal.AbstractMutationGuard$IllegalMutationException: DefaultTaskContainer#create(String, Class, Action) on task set cannot be executed in the current context.

所以我的问题是,有没有一种基于属性名设置任务依赖关系的方法,如果没有,那么做我想做的事情的更好方法是什么?

共有1个答案

须敏学
2023-03-14

有趣的是,一旦我摆脱了项目,这种方法就可以工作了。afterEvaluate,一些中等复杂的提供商正在洗牌:

// instead of
val analyzeSomething = project.tasks.register<AnalyzeSomethingTask>("analyzeSomething")
project.afterEvaluate {
    analyzeSomething.configure {
        val precomputeTaskName = "precompute" + configuration.get().capitalize()
        dataCacheFile.set(
            project.tasks.named<PrecomputeTask>(precomputeTaskName)
                .flatMap { it.outputFile }
        )
    }
}

// do this

project.tasks.register<AnalyzeSomethingTask>("analyzeSomething") {
    dataCacheFile.set(
        configuration.flatMap { c ->
            val precomputeTaskName = "precompute" + c.capitalize()
            project.tasks.named<PrecomputeTask>(precomputeTaskName)
                .flatMap { it.outputFile }
        }
    )
}

我真的很好奇为什么这种方法比项目更有效。afterEvaluate基于,但它似乎工作正常,因为它会将适当的预计算*任务添加到任务图中,并将其输出用于分析。

 类似资料:
  • 我有一些与jdbc相关的通用代码,我想单独打包到一个可运行的jar中,其中已经包含了所需的jdbc库,因此每个数据库类型都有一个单独的可运行jar。源代码将保持不变,但打包的jdbc jar将不同。 例如jdbc app postgres。jar将只包含postgres jdbc jar,而jdbc应用程序mysql。jar将包含mysql jdbc jar。 是否可以使用gradle对任务或任何

  • 我有两个互斥的任务,它们都应该在完成后启动。 我提到它们是互斥的,因为我不想让< code>bootRun依赖于它们中的任何一个。相反,我在寻找一个类似如下的流程: 我尝试了以下方法, 因此,将启动设置()和bootRun(与的类似设置)。这会导致在项目'中找不到路径'bootRun'的 我还尝试将A/B任务声明为:< code > task A(type:org . spring framewo

  • 因此,自从添加新的Room android架构库以来,这种情况已经开始发生。我在AppDatabase_Impl没有过期时遇到问题,我通过在注释中添加kapt来修复它: < li>Android Room持久性库和Kotlin < li >在Kotlin中实现房间持久性库 < in Kotlin中的房间持久性库实现(Gradle错误) 我怀疑其他错误是由于AS、Kotlin和Java 8造成的,所

  • 将gradle及其spring-boot插件(1.5.1)和第一个spirit插件一起使用会引发一个错误: b)如何从“启动重新打包”中删除“fsm”的依赖项? c)是否可以显示一个分级任务依赖关系图?(不是项目依赖关系)

  • 就像你所猜想的那样, 你可以声明任务之间的依赖关系. 例子 6.6. 申明任务之间的依赖关系 build.gradle task hello << { println 'Hello world!' } task intro(dependsOn: hello) << { println "I'm Gradle" } gradle -q intro 命令的输出 > gradle -q

  • 问题内容: 可以运行以了解模块任务的依赖性。有没有办法找到 buildscript依赖 的 传递依赖 ? 示例: 直接取决于: 可以在MVNRepository上看到。但是,这些工件有其自己的依赖性。有没有找到方法而无需手动遍历整个依赖树的方法? 为了澄清起见,我正在谈论的类路径由以下方式定义: 问题答案: 您可以使用以下命令: Udacity提供了很棒的Android Gradle 教程,但是您