Task inputs and outputs from extension?

I am trying to create a task in a plugin who’s inputs and outputs are specified by the individual build files. However, it seems that the getInputs and getOutputs method are called as part of apply, so before the extension object is populated by the project build file.

What I tried: Setting a variable on the extension object, and then overriding the getInputs method, having the first call to getInputs parse the value in extension object and add it to the base inputs object. This doesn’t work because (as mentioned) getInputs is called from the build before the extension object is set. (My task extends DefaultTask)

This would have to be possible, because (for example) you can change your inputs to the java compile task, but it doesn’t seem to be possible using the extension convention?


When playing around with the above, I also found this weird behavior: Overwriting the getOutputs method with the following signature: public TaskOutputsInternal getOutputs() gets the following: “The return type of org.gradle.api.internal.TaskOutputsInternal getOutputs() in test.package.CodeGenTask is incompatible with org.gradle.api.tasks.TaskOutputs getOutputs() in org.gradle.api.internal.AbstractTask”

And if I change the signature to: public TaskOutputs getOutputs() gets the following: “The return type of org.gradle.api.tasks.TaskOutputs in test.package.CodeGenTask is incompatible with org.gradle.api.internal.TaskOutputsInternal getOutputs() in org.gradle.api.internal.AbstractTask”

Since the getInputs()/getOutputs() this is kind of moot, but it does seem like undesired behavior (or at least an error message reporting the wrong thing).

After writing this up, I realized that its possible that the underlying file collection is lazy, so that even though getInputs has already called, the you could change the inputs and have it work. If this is the case, then I am simply looking for the best hook that would allow me to to process the values in the extension after it has been set, but before the task runs.

The first thing to try is specifying a deferrable value for the inputs. The simplest way to do this is with a closure…

someTask.inputs.files { useTask ? task.outputs.files : myExtension.someInputFiles }

This works.

I had got it working using project.afterEvaluate, but that felt like a bit of a hack, this works better.