SilverJan SilverJan - 2 months ago 16
Groovy Question

Gradle dependsOn and dynamic variables

See the following scenario:

def dynamic = "original value"

task stuffThatHasToBeDoneBefore << {
doSomething(dynamic)
}

task b (dependsOn: stuffThatHasToBeDoneBefore) {
dynamic = "value of task b that never will be used by stuffThatHasToBeDoneBefore-task"
}

task c (dependsOn: stuffThatHasToBeDoneBefore) {
dynamic = "value of task c"
}


I want to use the stuffThatHasToBeDoneBefore-task multiple times in my build execution to reduce code duplicates.

Right now it isn't possible to execute task b and to be sure that the stuffThatHasToBeDoneBefore-task will be executed beforehand with the dynamic-value ("value of task b that never will be used by stuffThatHasToBeDoneBefore-task"), because the dynamic-variable value will be overwritten by task c in the configuration phase ("value of task c").

The only way I see to do this is the following:

task b_alternative << {
dynamic = "value of task b that will be used in stuffThatHasToBeDoneBefore-task now"
tasks.stuffThatHasToBeDoneBefore.execute()
}


Unfortunately this is just a workaround and I read in multiple sources that it isn't recommended to use tasks.taskname.execute()

Can anybody tell me how to structure the code so that I can reuse the stuffThatHasToBeDoneBefore-task with dynamic values?

Usually I would use a simple method instead of a task for it and pass the dynamic-value as an argument, but this is not possible because the stuffThatHasToBeDoneBefore-task is a Zip-typed task which is only available as a task and not as a method.

Answer

The solution to your problem is to use a custom task. You can have your custom task extend the ZipTask, and you can define a custom dynamic property on it, and a doSometing method that uses it. You then add doSomething to doFirst or doLast depending on when you want it to execute ( before or after the zip is made ).

Your build script becomes more expressive:

// import MyCustomTask here
task b (type: MyCustomTask) {
   dynamic = "value for task b"
}
task a (type: MyCustomTask) {
   dynamic = "value for task a"
}

Note that dynamic is no longer a variable in your build script, it's now a property of your custom task.