Reputation: 1379
In Gradle, how do I make the output of one task be a property and the input of another task be that same property? Especially in the context of that property being needed at configuration time.
I'm attempting to write a Tar
task that depends on user input. I'm having trouble with the need for lazy configuration given that the "baseName" is not known at configuration time.
Here's what I would like to work but it doesn't.
task saveDb(type: Tar, dependsOn: getTarBaseName) {
// Next line doesn't work but does if I surround 2nd param with '{}'
inputs.property("baseName", getTarBaseName.baseName) // Doesn't work
from file("$dbsDir/data")
destinationDir = file(project.dbsBackupDir)
baseName = getTarBaseName.baseName // Doesn't work
extension = 'tar'
compression = Compression.NONE
}
task getTarBaseName() {
doFirst {
def result = BuildUtil.promptForName() // Uses Swing to prompt for a name
getTarBaseName.ext.baseName = result
}
}
As you can see I'm using ext
to try to pass information between tasks, but that is just incidental not a requirement. Also I'm using 2 tasks, I'm completely willing to use only 1, however, that wouldn't really answer the general question which is one I hit against fairly often when attempting to use Gradle as a cross platform bash replacement for project related tasks.
Upvotes: 0
Views: 288
Reputation: 14503
To solve your specific problem (if I did not miss something), you don't need a second task. Just add a doFirst
closure to your Tar
task and set the baseName
property there to whatever you want:
task saveDb(type: Tar) {
// static configuration
doFirst {
baseName = BuildUtil.promptForName()
// or for another task (don't forget to depend on that task)
baseName = otherTask.myProperty
}
}
task otherTask {
doFirst {
ext.myProperty = BuildUtil.promptForName()
}
}
However, your question boils down a general difficulty in Gradle: when to apply a specific piece of configuration.
Gradle just introduced a rather new feature for lazy configuration: Provider
and Property
Gradle provides lazy properties, which delay the calculation of a property’s value until it’s absolutely required.
Before Gradle 4.0, only files could be lazy evaluated (via ConfigurableFileCollection
), as an example:
task myZip(type: Zip) {
// zip some files
}
task copyMyZip(type: Copy) {
from myZip
}
myZip.baseName = 'myZip'
Even if the name of the zip file is defined after the Zip
task is added to the Copy
task configuration, its correct path will be used for the copy operation.
Now, with Gradle 4.0 and up, all configuration parameters that implement Property
or Provider
can be bound easily (check out the link above) and you can also lazily read a configuration parameter by wrapping it into a Provider
, but it's difficult to put a provider value into an old configuration parameter. You still need to specify the moment when to evaluate (inside the task action, in a doFirst
closure or an afterEvaluate
handler). This problem is the topic of this discussion on GitHub.
Upvotes: 1