Gradle:从另一个任务中调用任务

3

我知道目前调用一个任务的支持方法是使用dependsOnfinalizedBy,但我遇到了一个问题。

我有一个任务taskA,它可以独立使用。我还有另一个任务taskB,当被调用时,将依赖于taskA。问题在于taskB有额外的条件,如果这些条件失败,则需要跳过该任务。这是我想要实现的工作流程:

$ gradle taskA
:taskA

BUILD SUCCESSFUL
$ gradle taskB
checking condition 1... PASS
checking condition 2... PASS
:taskA
:taskB

BUILD SUCCESSFUL
$ gradle taskB
checking condition 1... PASS
checking condition 2... FAIL
:taskA SKIPPED
:taskB SKIPPED

BUILD SUCCESSFUL

如果直接调用或从不同任务的doFirstdependsOn中调用,taskA应该无论如何都会执行。但是如果调用了taskB,则必须满足条件才能执行taskA。这是我尝试过的方法:
project.tasks.create(name: "taskB", type: MyTask, dependsOn: "taskA")
project.taskB{
  onlyIf {
    if (!conditionA()){
      return false
    }
    if (!conditionB()){
      return false
    }
    return true
  }
}

这里的问题在于 taskA 会在检查 taskBonlyIf 条件之前执行,因此即使条件失败,taskA 也会执行。
我该如何解决这个问题?
2个回答

6

看起来只有在任务图被解析后才能进行配置。在早期阶段,所有条件都将在“配置”阶段进行评估,这太早了。请看这个例子:

task a {
  doLast {
      println 'a'
  }
}

task b {
  dependsOn a
  doLast {
      println 'b'
  }
}

gradle.taskGraph.whenReady { graph ->
    if (graph.hasTask(b)) {
        a.enabled = b.enabled = check1() && check2()
    }
}

boolean check1() {
  def ok = project.hasProperty('c')
  println "check 1: ${ok ? 'PASS' : 'FAIL'}"
  ok
}

boolean check2() {
  def ok = project.hasProperty('d')
  println "check 2: ${ok ? 'PASS' : 'FAIL'}"
  ok
}

并输出:

 ~/tutorial/stackoverflow/40850083/ [master] gradle a
:a
a

BUILD SUCCESSFUL

Total time: 1.728 secs

 ~/tutorial/stackoverflow/40850083/ [master] gradle b
check 1: FAIL
:a SKIPPED
:b SKIPPED

BUILD SUCCESSFUL

Total time: 1.739 secs

 ~/tutorial/stackoverflow/40850083/ [master] gradle b -Pc
check 1: PASS
check 2: FAIL
:a SKIPPED
:b SKIPPED

BUILD SUCCESSFUL

Total time: 1.714 secs

 ~/tutorial/stackoverflow/40850083/ [master] gradle b -Pc -Pd
check 1: PASS
check 2: PASS
:a
a
:b
b

BUILD SUCCESSFUL

Total time: 1.745 secs

@ewok,一个单独的Groovy文件配置插件?它是如何工作的?“gradle”被定义在“project”实例上,就像其他从未出现过的变量一样 ;) - Opal
我从build.gradle中调用apply plugin,它会在插件上执行apply()方法。该方法调用new PluginConfigurator().configure(project)PluginConfigurator.configure()方法是进行配置的地方。它需要一个类型为org.gradle.api.Project的参数。当我尝试将您建议的代码添加到该方法中时,我会得到No such property: gradle for class: plugin.PluginConfigurator的错误提示。 - ewok
1
@ewok,请重新表述你的问题,使其代表一个真正的问题。否则可能会很难提供帮助。 - Opal
@ewok,不要放弃。再试一次;)你提到了一个插件,但在你的问题中并没有提到插件。 - Opal
让我们在聊天室里继续这个讨论 - Opal
显示剩余4条评论

2

我知道大多数人不建议这样做,但我通过实际执行任务来完成它,如下所示:

task a {
  doLast {
      println 'a'
  }
}

task b {
  doLast {
      a.execute()
      println 'b'
  }

  outputs.upToDateWhen {
    conditionA() && conditionB()
  }
}

“execute” 不应直接被调用。 - Opal
他们这么说。我并不真正遵循编程原教旨主义。带有“不应该”的规则表明您正在打破一种范式,但有时打破一种范式是完成某些事情最容易的方法。 - xaviersjs
最简单的方式并不意味着应该遵循它。此外,这不是范式问题,而是破坏 Gradle 内部机制的问题。 - Opal
7
请自由地给出一个实际的原因,解释为什么调用execute是个不好的选择。 - Allen Luce
3
“随意提供一个实际原因,说明为什么调用execute是个坏主意”:“因为execute已经被弃用并且不再存在了…” - Steven Spungin
很不幸,execute已经不存在了! - Duncan McGregor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接