Controlling order of execution of statements wrt execution of a task


(Norman Walsh) #1

Apologies if this is an obvious n00b question and I’ve just failed to find the answer.
I have a custom task:

task myTask(type: MyType, dependsOn: [ "build1", "build2" ]) {
  inputs.file "build1/dep.file"
  inputs.file "build2/dep.file"
  myOption "build1/dep.file build2/dep.file"
}

This is fine, works like a charm.
But I realize that as I add dependencies, I have to update the input files and my option; that seems like an opportunity for error. So, I try to do it programatically:

task myTask(type: MyType, dependsOn: [ "build1", "build2" ]) {
  FileTree tree = fileTree(dir: ".").include("**/dep.file")
  String files = ""
  tree.each { file ->
    files = files + file.getAbsolutePath()
  }
  inputs.files tree
  myOption files
}

This doesn’t work because the tree is apparently constructed at configuration time and not at execution time. Use doFirst?

task myTask(type: MyType, dependsOn: [ "build1", "build2" ]) {
  FileTree tree = null
  String files = ""
  doFirst {
    tree = fileTree(dir: ".").include("**/dep.file")
    tree.each { file ->
      files = files + file.getAbsolutePath()
    }
  }
  inputs.files tree
  myOption files
}

Nope: NPE on tree. Move everything inside doFirst? Nope, then the task doesn’t see the options.
Am I overlooking the obvous?


(Mike Kobit) #2

The doFirst and doLast methods add actions that are run during the execution phase (see build lifecycle documentation). Your first example is greedily (during the configuration phase) looking up the files. In your third example you are adding an action with doFirst (executed at a later time) and then calling inputs.files tree where FileTree tree = null, so that is why you get that NPE.

The FileCollection and FileTree types are lazy, so you generally set them up in the configuration phase and then query the results at execution time (like in your doFirst or doLast or @TaskAction methods). So, you set them up like your second example myOption(fileTree(dir: ".").include("**/dep.file")) and then in the doFirst/@TaskAction/doLast blocks query and make use of the result.

It sounds like you may want to change the input type of myOption to be a FileCollection or FileTree with @InputFiles.

I’d recommend looking at both the Lazy Configuration: Working with files and Providers and Working With Files: File trees documentation sections.