Noel Yap
Noel Yap

Reputation: 19808

How to do something before Gradle task's dependencies are executed?

I have the following in build.gradle:

task aoeu << {
    println "**************************** during"
}

tasks.publish.dependsOn(aoeu)

tasks.publish.doFirst {
    println "************************* before"
}

tasks.publish.doLast {
    println "************************* after"
}

Its output is:

:aoeu
**************************** during
:publish
************************* before
************************* after

But what I really need is for the 'during' to happen between 'before' and 'after'. How can this be done? Should 'publish' simply depend on 'before'? If so, how can I guarantee that it happen before other dependencies?

Upvotes: 17

Views: 42419

Answers (3)

Youngjae
Youngjae

Reputation: 25080

Ordering tasks is headache, and << is deprecated syntax.

I ended up to weave tasks as below.

task publish {
    println "here we go"
}

task task1 {
    println "first"
}

task task2 {
    println "second"
}

task task3 {
    println "third"
}

// task execution order. this executes bottom to top order.
publish.dependsOn task3
task3.dependsOn task2
task2.dependsOn task1

The publish task result is as below;

here we go
first
second
third

Upvotes: 0

Noel Yap
Noel Yap

Reputation: 19808

task snth << {
    println "************************* before"
}

task aoeu << {
    println "**************************** during aoeu"
}
publish.dependsOn(aoeu)

task ueoa << {
    println "**************************** during ueoa"
}
publish.dependsOn(ueoa)

publish.doLast {
    println "************************* after"
}

publish.dependsOn.each { dependency ->
    if (dependency instanceof Task) {
        dependency.dependsOn(snth)
    }
}

will output:

:snth
************************* before
:aoeu
**************************** during aoeu
:ueoa
**************************** during ueoa
:publish
************************* after

If you want the dependency added recursively:

def recursivelyAddDependsOn(Task parent, Task dependsOn) {
    if (!parent.equals(dependsOn)) {
        parent.dependsOn(dependsOn)

        def tasks = parent.dependsOn.findAll { dependency ->
            dependency instanceof Task
        }
        tasks.each { task ->
            recursivelyAddDependsOn(task, dependsOn)
        }
    }
}

recursivelyAddDependsOn(publish, snth)

And a more functional solution is:

def recursivelyApplyToTaskDependencies(Task parent, Closure closure) {
    closure(parent)

    parent.dependsOn.findAll { dependency ->
        dependency instanceof Task
    }.each { task ->
        recursivelyApplyToTaskDependencies(task, closure)
    }
}

def recursivelyAddTaskDependency(Task parent, Task dependency) {
    def addTaskDependency = { p ->
        if (!p.name.equals(dependency.name)) {
            p.dependsOn(dependency)
        }
    }

    recursivelyApplyToTaskDependencies(parent, addTaskDependency)
}

recursivelyAddTaskDependency(publish, snth)

Upvotes: 4

pepuch
pepuch

Reputation: 6516

As far as I know your code should work propertly but it doesn't. doFirst should be executed in configuration phase which is run before doLast (execution phase). BTW this code works fine:

As Peter Niederwiser wrote here https://stackoverflow.com/a/9204159/2069368 doFirst run in execution phase as first statement (before doLast) so your code works fine. This example will show you execution order in gradle build:

task publish {
    println "(1) before (run in configuration phase)" // this will run before gradle dependencies
}

task aoeu << {
    println "(2) during  (run in execution phase as last statement)"
}

tasks.publish.dependsOn(aoeu)
tasks.publish.doLast {
    println "(4) after  (run in execution phase as last statement)"
}

tasks.publish.doFirst {
    println "(3) after  (run in execution phase as FORST statement - before doLast/<<)"
}

It will return

C:\>gradle publish
(1) before (run in configuration phase)
:aoeu
(2) during  (run in execution phase as last statement)
:publish
(3) after  (run in execution phase as FORST statement - before doLast/<<)
(4) after  (run in execution phase as last statement)

[UPDATE]

Here http://gradle.1045684.n5.nabble.com/task-run-order-lt-lt-syntax-doLast-doFirst-etc-td3337481.html is great question with great example which shows execution order.

Read this article about gradle lifecycle, it will help you understand it.

[UPDATE] If you want to run task aoeu in publish execution phase you can call aoeu.execute in publish.doFirst. But as far as I know it shouldn't be done in that way.

task publish {
}

task aoeu << {
    println "(2) during  (run in execution phase as last statement)"
}

tasks.publish.doLast {
    println "(3) after  (run in execution phase as last statement)"
}

tasks.publish.doFirst {
    println "(1) after  (run in execution phase as FORST statement - before doLast/<<)"
    aoeu.execute()
}

will return

C:\>gradle publish
:publish
(1) after  (run in execution phase as FORST statement - before doLast/<<)
(2) during  (run in execution phase as last statement)
(3) after  (run in execution phase as last statement)

As I see you want to run aoeu in the middle of publish task. I think that the best way to do it will be to divide publish task into two separate tasks and use depends, mustRunAfter to control execution order. Look at this example:

task publishInit << {
    println '(1)'
}

task aoeu << {
    println '(2)'
}

task publish << {
    println '(3)'
}

publish.dependsOn publishInit
publish.dependsOn aoeu
aoeu.mustRunAfter publishInit

It will return

C:\>gradle publish
:publishInit
(1)
:aoeu
(2)
:publish
(3)

Upvotes: 17

Related Questions