Reputation: 78
I have a gradle project with the following structure:
I have a sequence of tasks (let's call them taskA, taskB, taskC), that take one input file (let's call it source.tar.gz) and generates an output file (let's call it dist.tar.gz). Assume taskA/taskB/taskC will need to run processes, etc.
I also have a task (called taskZ) that makes sure to cleanup after taskA, taskB, taskC. Assume it will stop processes started by the first set of tasks.
I have a custom task called 'make' that depends on the build and its finalized. Something like this:
task make {
dependsOn taskA, taskB, taskC
finalizedBy taskZ
}
Finally, gradle's built in 'assemble' task depends on my custom 'make' task.
I would like to let gradle know that make's input is 'source.tar.gz' file and output is 'dist.tar.gz' so 'make' doesn't need to run if 'dist.tar.gz' is newer than 'source.tar.gz'.
I tried declaring 'make' input and outputs, like this:
task make {
dependsOn taskA, taskB, taskC
finalizedBy taskZ
inputs.file("$projectDir/src/main/source.tar.gz")
outputs.file("$buildDir/dist.tar.gz")
}
But gradle is still running the whole process everytime.
Is there any way I can tell gradle to skip 'make' task and its dependencies?
Upvotes: 0
Views: 904
Reputation: 78
I solved my problem following the suggestion from @lu.koerfer. I set tasks taskA, taskB, taskC, make, taskZ to have the same inputs and outputs. An I also marked taskB, taskC, taskZ to only run if taskA was not UP-TO-DATE.
With that configuration, taskA will only run if gradle uses its own mechanism to execute taskA, and only if taskA is not marked as UP-TO-DATE by gradle, then the rest of the tasks will run.
task taskA {
...
}
task taskB {
...
onlyIf { !taskA.state.upToDate }
}
task taskC {
...
onlyIf { !taskA.state.upToDate }
}
task taskZ {
...
onlyIf { !taskA.state.upToDate }
}
task make {
dependsOn taskA, taskB, taskC
finalizedBy taskZ
...
}
[taskA, taskB, taskC, taskZ, make].each { t ->
t.inputs.file("$projectDir/src/main/source.tar.gz")
t.outputs.file("$buildDir/dist.tar.gz")
}
This works as expected. Sometimes gradle up to date mechanism may not work. If you need to force-run all tasks, just run:
./gradlew make --rerun-tasks
Upvotes: 0
Reputation: 4492
Gradle's incremental build is not solely based on timestamps (timestamps may not even be considered these days), so it won't help with what you're trying to do. On top of that, I'm pretty sure tasks A -> C will always run even with make
configured that way. make
must first ensure that its dependencies are run or already up to date.
Given this, I think you may need to use a dedicated timestamp check in an onlyIf()
check. Something like:
make.onlyIf { inputFile.lastModified() > outputFile.lastModified() }
where inputFile
and outputFile
are paths to the relevant files (using project.file()
for example). I don't think this is terribly reliable, but it may suffice for your use case.
Alternatively, create a custom task that performs B and C together, if you can configure such a task with appropriate defined inputs and outputs. I think this is the better solution based on the information given.
Upvotes: 1