To utilize the gradle build cache, gradle must have exclusive access to the output files.
In a project I work on files can also be generated by a GUI tool when the user tests the configuration so gradle is not exclusively used. The build system is slowly migrated to gradle, this is also a way to utilize the gradle cache for longer running operations.
To avoid OVERLAPPING_OUTPUTS when building if the output has been touched by tools outside gradle, the outputs must be cleaned on build.
If the base plugin is applied, the lifecycle cleanTaskName can be used. However, this is not logical when implementing and can give performance problem. See the annotated snippet below.
String cleanTask(String s) {
return 'clean' + s.substring(0,1).toUpperCase() + s.substring(1)
}
void apply(Project project) {
// get default lifecycle including clean tasks
project.plugins.apply(BasePlugin)
def a = project.tasks.register('a')
def b = project.tasks.register('b')
a.configure {
//OK to set dependency here, no side effects
dependsOn cleanTask(name)
}
//adding dependencies to 'cleanB' will configure cleanB and 'b'
//regardless if 'b' is considered to be executed
// (this may be a side effect of project.tasks.named()
project.tasks.named(cleanTask(b.name)).configure {
dependsOn a
onlyIf { a.get().getDidWork() }
}
genRteCacheTask.configure {
dependsOn cleanTask(name)
// This will also create cleanB, B
onlyIf { project.tasks.named(cleanTask(name)).get().getDidWork() }
}
}
Dependencies could also have been set as following, but that adds yet another source line
a<-b; cleanB<-B; cleanB.mustRunAfter(a)
It is possible to get around the cleanB, b is always created by creating a custom task that cleans the outputs for b. But the dependency is the same and it seems better to use the clean tasks.
Is there any better way to force outputs to be deleted so outputs are not overlapping in this situation?
(I would also like some way to get gradle to ignore outputs and still create cache, but that is another question.)