I thought I understood how task inputs and outputs worked, but I just came across a case that broke my understanding.
Given these two tasks:
task a {
ext {
outDir = new File( buildDir, 'aout' )
outFile = new File( buildDir, 'a.out' )
}
outputs.dir( outDir )
outputs.file( outFile )
doLast {
outDir.mkdirs()
new File( outDir, 'a.anotherOut' ).text = 'A'
outFile.text = 'A'
}
}
task b {
ext {
inThings = [tasks.a, file( 'another.in' )]
}
inputs.files( inThings )
doLast {
println inputs.files.join( '\n' )
}
}
I expect the execution of task b to list the a.out, a.anotherOut, and another.in files. Instead the aout directory is listed in place of a.anotherOut. My expectation is based on the documentation of TaskInputs.files()/Project.files(), which states that a Task is converted to its outputs. Since TaskOutputs.dir() includes the files in the directory as part of the task’s outputs, I figured those child files would be part of b’s input files.
$ ./gradlew b
:a
:b
/home/cdore/sandbox/gradle-tests/gradle-taskoutputs-test/build/aout
/home/cdore/sandbox/gradle-tests/gradle-taskoutputs-test/build/a.out
/home/cdore/sandbox/gradle-tests/gradle-taskoutputs-test/another.in
Looking at how SourceTask.getSource() works, it would seem that b should be something like the following instead, which works:
task c {
ext {
inThings = [tasks.a, file( 'another.in' )]
}
inputs.files( project.files( inThings ).asFileTree )
doLast {
println inputs.files.join( '\n' )
}
}
$ ./gradlew c
:a
:c
/home/cdore/sandbox/gradle-tests/gradle-taskoutputs-test/build/aout/a.anotherOut
/home/cdore/sandbox/gradle-tests/gradle-taskoutputs-test/build/a.out
/home/cdore/sandbox/gradle-tests/gradle-taskoutputs-test/another.in
Is there a more appropriate way to achieve the correct results, or is this “project.files(inputStuff).asFileTree” pattern something I should be using in my tasks and task classes going forward.
Thanks, Chris