Как сделать что-либо до Gradle зависимостей задач?

У меня есть следующее в build.gradle:

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

tasks.publish.dependsOn(aoeu)

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

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

Его вывод:

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

Но мне действительно нужно, чтобы "во время" происходило между "до" и "после". Как это может быть сделано? Должно ли "публиковать" просто зависеть от "до"? Если да, то как я могу гарантировать, что это произойдет до других зависимостей?

Ответ 1

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(aoeu)
    }
}

выведет:

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

Если вы хотите, чтобы зависимость была добавлена ​​рекурсивно:

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)

И более функциональное решение:

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)

Ответ 2

Насколько я знаю, ваш код должен работать корректно, но это не так. doFirst должен выполняться в фазе конфигурации, которая выполняется до doLast (этап выполнения). Кстати, этот код отлично работает:

Как писал Peter Niederwiser fooobar.com/info/490209/... doFirst запускать в фазе выполнения как первый оператор (до doLast), поэтому ваш код работает нормально. В этом примере будет показан порядок выполнения в 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/<<)"
}

Он вернет

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)

[ОБНОВЛЕНИЕ]

Здесь http://gradle.1045684.n5.nabble.com/task-run-order-lt-lt-syntax-doLast-doFirst-etc-td3337481.html - отличный вопрос с большим примером, который показывает порядок выполнения.

Прочитайте эту статью о жизненном цикле gradle, это поможет вам понять это.

[ОБНОВЛЕНИЕ] Если вы хотите запустить задачу aoeu в фазе publish, вы можете вызвать aoeu.execute в publish.doFirst. Но насколько я знаю, это не должно быть сделано таким образом.

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()
}

вернет

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)

Как я вижу, вы хотите запустить aoeu в середине задачи publish. Я думаю, что лучший способ сделать это - разделить задачу publish на две отдельные задачи и использовать depends, mustRunAfter для управления порядком выполнения. Посмотрите на этот пример:

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

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

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

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

Он вернет

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