With a task producing an OutputFile, for example:
abstract class TimeStampTask : DefaultTask() {
@get: OutputFile
abstract val output: RegularFileProperty
@TaskAction
fun createFile() {
val outputFile = output.get().asFile
if (outputFile.exists()) {
outputFile.delete()
}
outputFile.createNewFile()
outputFile.appendText(Date().time.toString())
}
}
I want to lazily set the value of an Input for another task with the content of the produced OutputFile, during configuration phase. For example in build.gradle.kts :
val timestampTask = project.tasks.register<TimeStampTask>("timestamp") {
output.set(layout.buildDirectory.file(".timestamp"))
}
tasks.register<Zip>("packageDistribution") {
archiveFileName = timestampTask.flatMap { task ->
task.output.flatMap { project.provider { it.asFile.readText() } }
}
destinationDirectory = layout.buildDirectory.dir("dist")
from(layout.buildDirectory.dir("toArchive"))
}
But during execution of the task, there's a java.io.FileNotFoundException: xxxx/.timestamp (The system cannot find the file specified)
Is it possible to set lazily during configuration phase? Or there is no other possibility than setting in a doFirst block?
You don’t need to fall back to a doFirst
. You can keep it entirely lazy in the configuration phase, you just have to
declare a dependency so that Gradle knows “packageDistribution” must run after “timestamp”,
use the Provider-API properly (calling .set(...)
on the Property
, not assigning with =
), and
chain .flatMap{…}.map{…}
(or just .map{…}
on the task’s output) so that the file is only ever read at execution-time, after it’s been created.
val timestampTask = tasks.register<TimeStampTask>("timestamp") {
output.set(layout.buildDirectory.file(".timestamp"))
}
// derive a Provider<String> that will read the file later
val timestampContents: Provider<String> = timestampTask
// flatMap on a TaskProvider gives you a Task object at execution time
.flatMap { ts ->
// ts.output is a RegularFileProperty; map its file to its contents
ts.output.map { regFile ->
regFile.asFile.readText() // <-- this runs only when somebody actually resolves the Provider
}
}
tasks.register<Zip>("packageDistribution") {
// make sure we run timestamp before packaging
dependsOn(timestampTask)
// set the archiveFileName to our lazy provider
archiveFileName.set(timestampContents)
destinationDirectory.set(layout.buildDirectory.dir("dist"))
from(layout.buildDirectory.dir("toArchive"))
}