Evaluate "Exec" task arguments at execution time


(Pavel Dudka) #1

I have 2 Exec tasks. Output from one task should be an input for another:

task bar(type: Exec) {
    commandLine('./someShellScript')
    standardOutput = new ByteArrayOutputStream()
    ext.output = {
        return standardOutput.toString()
    }
}

task foo(type: Exec) {
    dependsOn bar
    commandLine('./someOtherSript,'
                bar.ext.output()) //this is an output from first task
    standardOutput = new ByteArrayOutputStream()
    ext.output = {
        return standardOutput.toString()
    }
}

But after I wrote this, I realized that evaluation of foo's commandLine happens at the configuration stage (bar.ext.output() is called before bar is executed).

How do I make this kind of connection between these 2 Exec tasks when one acts as input for another?


(Mark Vieira) #2

You could use a lazy evaluated GString for this.

commandLine './someOtherScript', "${->bar.output()}"

(Pavel Dudka) #3

Ha! Didn’t know about this one! You saved my day! Thanks!


(Adrien) #5

Hi,

that works really well for a string, but how would you do for a list? I tried something like


task mytask(type: Exec) {
  def cmd = []

  doFirst {
    cmd.add("ls")
  }

  commandLine { -> cmd }
}

with no success, the closure is called at evaluation time (the example above makes no sense per se, imagine that the list we add to cmd comes from another task’s output)


(Mark Vieira) #6

Realistically, the only other option is to use a “configuration task”, that is, a task whose action configures another task.

task foo(type: Exec) {
  dependsOn 'configureFoo'
}

task configureFoo {
  doLast {
    foo.commandLine = // grab from other task's output
  }
}