I have a simple class that prints to screen if the content of a project’s ‘src’ directory has been modified since the previous execution:
task checkIfProjectIsOutOfDate(type: IsOutOfDate) {
inputDir = file("${project.projectDir}/src")
outputDir = file("C:/empty-directory")
}
class IsOutOfDate extends DefaultTask {
@InputDirectory
def File inputDir
@OutputDirectory
def File outputDir
@TaskAction
void execute(IncrementalTaskInputs inputs) {
def outOfDate = false
inputs.outOfDate { change ->
println "out of date: ${change.file.name}"
}
inputs.removed { change ->
println "removed: ${change.file.name}"
}
}
}
This works as expected. I now need to modify this code to check each sub-project of a multi-project build.
RootProject
|— Project A
|— Project B
|— Project C
If I update my ‘listOutOfDateProjects’ to use ‘subprojects’:
task listOutOfDateProjects(type: IsOutOfDate) {
subprojects {
inputDir = file("${project.projectDir}/src")
outputDir = file("C:/emptyDirectory")
println "Configuring input & output directories for ${project.name}"
}
}
Now only the last of my subprojects (Project C) is evaluated, as I’m assuming ‘listOutOfDateProjects’ is configured for each subproject before ‘IsOutOfDate::execute’ is called.
My questions are:
a) How can I update the ‘listOutOfDateProjects’ task so each sub-project is evaluated for out of date inputs?
b) If I update the ‘IsOutOfDate::execute’ TaskAction to return a Boolean (true for out-of-date projects), how can I obtain this return value in my ‘listOutOfDateProjects’ task for each subproject?
sterling
(Sterling Greene)
November 24, 2015, 3:25am
2
Have you tried just creating the task for each project?
subprojects {
task checkIfProjectIsOutOfDate(type: IsOutOfDate) {
inputDir = file("${project.projectDir}/src")
outputDir = file("C:/empty-directory")
}
}
Thanks Sterling.
Placing the ‘subprojects’ block outside of the declaration of my task fixed the issue I was having executing this logic from a build.gradle file.
However after moving this logic to a custom plugin the problem of only the last subproject (Project C) being evaluate for out of date inputs is occurring once again.:
MyPlugin.groovy:
Class MyPlugin implements Plugin<Project> {
void apply(Project project) {
Task isOutOfDate = project.task('isOutOfDate', type: IsOutOfDate)
project.subprojects { currentProject ->
project.tasks.getByName('isOutOfDate') {
inputDir = new File("${currentProject.projectDir}/src")
outputDir = new File("C:/empty-directory")
}
}
}
}
IsOutOfDate.groovy:
class IsOutOfDate extends DefaultTask {
@InputDirectory
def File inputDir
@OutputDirectory
def File outputDir
@TaskAction
void execute(IncrementalTaskInputs inputs) {
inputs.outOfDate { change ->
println "out of date ${change.file.name}"
}
inputs.removed { change ->
println "removed: ${change.file.name}"
}
}
}
I’ve attempted creating another Plugin task to check all subprojects like so, but to no success - still only the last subproject get evaluated:
Task checkAllSubProjects = project.task('checkAllSubProjects')
project.subprojects { currentProject ->
Task isSubProjectOutOfDate = project.tasks.getByName('isOutOfDate') {
inputDir = new File("${currentProject.projectDir}/src")
outputDir = new File("C:/empty-directory")
}
checkAllSubProjects.dependsOn isSubProjectOutOfDate
}
Rene
(René Groeschke)
November 26, 2015, 8:35am
4
I see two options to put that logic into a plugin.
Option 1: Have a plugin that is applied on your root project only and adds a task for each subproject
Class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.subprojects { currentProject ->
Task isOutOfDate = currentProject.task('isOutOfDate', type: IsOutOfDate) {
inputDir = currentProject.file("src")
outputDir = new File("C:/empty-directory")
}
}
}
}
Option 2: Apply a plugin for each subproject and let the plugin create one task for the project it is applied to
Class MyPlugin implements Plugin<Project> {
void apply(Project project) {
Task isOutOfDate = project.task('isOutOfDate', type: IsOutOfDate) {
inputDir = project.file("src")
outputDir = new File("C:/empty-directory")
}
}
}
}
cheers,
René