Dynamic task outputs depending on configuration properties


(rainer.frey) #1

I have a custom (groovy) Task class, and it’s set of output files is not directly represented as a property (which I could annotate), but is computed from two different configuration properties.

I can of course programmatically register these with the TaskOutputs from within the task class, but the question is when to call that registering code.

It needs to be called after the task is completely configured, to ensure that both properties are set, but it needs also to be called before the upToDate state of the task is evaluated.

Unfortunately ‘TaskContainer.whenTaskAdded()’ fires before the task is configured. Is 'taskGraph.whenReady()'suitable, or has the up-to-date state already been determined then?

Or what else would be the cleanest, most idiomatic way to handle this?


(Peter Niederwieser) #2

The idiomatic way is to declare a synthetic property that computes the input value, and annotate it with the appropriate input annotation. I believe the property can be read-only (i.e. you only declare a getter).


(Luke Daley) #3

You can register a callback for the actual value in the task constructor:

class MyTask extends DefaultTask {
  String a
  String b
    MyTask() {
    inputs.property("combined") { "$a:$b" }
  }
}

The signing plugin does this (kinda):

https://github.com/gradle/gradle/blob/master/subprojects/signing/src/main/groovy/org/gradle/plugins/signing/Sign.groovy#L69


(Adam Murdoch) #4

You can also use a read-only property:

class MyTask extends DefaultTask {
  String a
  String b
    @Input
  def getCombined() { return "$a:$b" }
}

(Adam Murdoch) #5

This is exactly what Peter is suggesting. Sorry, I should have done a better job reading the posts.


(rainer.frey) #6

Thanks all for the input, I’ll use a synthetic property. Looks much cleaner than anything I came up with.