问题
In section 19.11. of the 4.2.1 user guide is this task rule example. How is the if predicate able to be true before the rule is even executed. I also noticed that when task groupPing is entered before the task rule the build fails. How are the tasks pingServer1, pingServer2 already created before the rule even starts?
tasks.addRule("Pattern: ping<ID>") { String taskName ->
if (taskName.startsWith("ping")) {
task(taskName) {
doLast {
println "Pinging: " + (taskName - 'ping')
}
}
}
}
task groupPing {
dependsOn pingServer1, pingServer2
}
回答1:
Per this book excerpt, the mechanism is similar to the methodMissing
functionality in Groovy and other languages. That is, if the task does not exist, then Gradle will deliberately check the task rules, which can clearly create tasks dynamically.
To address the comment, consider the following build.gradle
:
tasks.addRule("rule 1") { String taskName ->
println "TRACER xyz before if: ${taskName}"
if (taskName.startsWith("xyz")) {
println "TRACER xyz inside if: ${taskName}"
task(taskName) {
doLast {
println "xyz " + (taskName - "xyz")
}
}
}
}
tasks.addRule("rule 2") { String taskName ->
println "TRACER ping before if: ${taskName}"
if (taskName.startsWith("ping")) {
println "TRACER ping inside if: ${taskName}"
task(taskName) {
doLast {
println "Pinging: " + (taskName - "ping")
}
}
}
}
task foo {
println 'foo: config phase'
doFirst {
println 'foo: exec phase first'
}
doLast {
println 'foo: exec phase last'
}
}
task groupPing {
dependsOn pingServer1, pingServer2
println 'groupPing: config phase'
}
In essence, this does:
- Define "rule 1" which checks the
taskName
(aString
, not a task!) for prefixxyz
- Define "rule 2" which checks the
taskName
for prefixping
- Define task
foo
with some printlns - Define task
groupPing
with dependencies on dynamic tasks
Here is the output for foo
(spacing added). It illustrates that, in the configuration phase, Gradle invokes "rule 1" and then "rule 2" to define pingServer1
and pingServer2
:
$ gradle -q foo
foo: config phase
TRACER xyz before if: pingServer1
TRACER ping before if: pingServer1
TRACER ping inside if: pingServer1
TRACER xyz before if: pingServer2
TRACER ping before if: pingServer2
TRACER ping inside if: pingServer2
groupPing: config phase
foo: exec phase first
foo: exec phase last
来源:https://stackoverflow.com/questions/46964357/how-does-gradle-generate-a-new-task-from-a-task-rules