Как создать задачу Gradle, которая всегда выполняется?

Я, вероятно, упускаю из виду что-то довольно важное/очевидное, но как я могу создать задачу, которая всегда будет выполняться для каждой задачи/цели?

Я могу сделать что-то вроде:

task someTask << {
    println "I sometimes run"
}
println "I always run"

Но было бы гораздо желательнее иметь всегда работающую часть в задаче.

Самое близкое, что я пришел, это:

task someTask << {
    println "I sometimes run"
}

println "I always run"

void helloThing() {
    println "I always run too. Hello?"
}

helloThing()

Таким образом, использование метода является «хорошим» решением, но я надеялся, что будет способ специально назначить/повторно использовать задачу.

Надеюсь, у кого-то есть способ сделать это. :)


person CasualT    schedule 09.01.2014    source источник
comment
Если есть N задач, то эту функцию нужно вызывать N раз, верно? Что делать, если некоторые задачи НИКОГДА не выполняются в данной сборке?   -  person akhikhl    schedule 09.01.2014
comment
Или вы хотите, чтобы функция вызывалась для каждого проекта?   -  person akhikhl    schedule 09.01.2014
comment
Один раз за сборку. Независимо от того, какие задачи вызываются.   -  person CasualT    schedule 09.01.2014
comment
Это необычное требование, и для него нет первоклассной функции. Каков вариант использования?   -  person Peter Niederwieser    schedule 09.01.2014
comment
Я предполагаю, что мысль заключалась в более организационном подходе к общим "задачам" сборки ... но я мог бы просто прибегнуть к использованию методов для некоторых из этих случаев.   -  person CasualT    schedule 09.01.2014
comment
Один конкретный случай касался информации о диагностике/состоянии системы. Что, в некоторых случаях, я бы просто хотел вызвать задачу «systemStatus», но я также хотел бы, чтобы эта информация выплевывалась для каждой сборки. (конечно, я мог бы сделать что-то подобное с методами под капотом... но просто подумал, что это может быть общий способ сделать это с задачами).   -  person CasualT    schedule 09.01.2014


Ответы (3)


Предполагая, что цель состоит в том, чтобы распечатать информацию о системе, вы можете либо просто всегда печатать информацию на этапе настройки (вне объявления задачи), либо иметь фиктивную задачу systemStatus, которая ничего не делает (поскольку информация все равно печатается). Или вы можете реализовать его как обычную задачу и убедиться, что задача всегда запускается, добавив ":systemStatus" в качестве первого элемента gradle.startParameter.taskNames (списка строк), что имитирует кого-то, кто всегда печатает gradle :systemStatus .... Или вы можете использовать хук, такой как gradle.projectsLoaded { ... }, чтобы напечатать там информацию.

person Peter Niederwieser    schedule 09.01.2014
comment
Это крутой трюк с динамическим управлением списком taskNames. (для справки, это работает: gradle.startParameter.taskNames = [:someTask] + gradle.startParameter.taskNames) - person CasualT; 10.01.2014
comment
Есть идеи, как «привязать» задачу к другой задаче, кроме как с «выполнить», что не рекомендуется? - person Ivan Balashov; 22.01.2015

Это прикрепляет закрытие к каждой задаче в каждом проекте в данной сборке:

def someClosure = { task ->
  println "task executed: $task"
}

allprojects {
  afterEvaluate {
    for(def task in it.tasks)
      task << someClosure
  }
}

Если вам нужно, чтобы функция/замыкание вызывались только один раз за сборку, перед всеми задачами всех проектов, используйте это:

task('MyTask') << {
  println 'Pre-build hook!'
}

allprojects {
  afterEvaluate {
    for(def task in it.tasks)
      if(task != rootProject.tasks.MyTask)
        task.dependsOn rootProject.tasks.MyTask
  }
}

Если вам нужно, чтобы функция/замыкание вызывались только один раз за сборку, после всех задач всех проектов, используйте это:

task('MyTask') << {
  println 'Post-build hook!'
}

allprojects {
  afterEvaluate {
    for(def task in it.tasks)
      if(task != rootProject.tasks.MyTask)
        task.finalizedBy rootProject.tasks.MyTask
  }
}
person akhikhl    schedule 09.01.2014
comment
Хмммм... это довольно удобно... немного более многословно, чем я надеялся, но все же довольно просто. - person CasualT; 09.01.2014
comment
Я обновил свой ответ, заботясь о том, что вы сказали: один раз за сборку. - person akhikhl; 10.01.2014
comment
Лучше использовать хук для каждой сборки, чем хук для каждого проекта. Второй фрагмент запустит задачу в конце сборки, а не в начале. - person Peter Niederwieser; 10.01.2014
comment
Я выбрал ответ Питера, потому что он немного короче. Тем не менее, я мог бы использовать и этот другой подход. (но я могу выбрать только один ответ ;)). Спасибо за помощь. :) - person CasualT; 10.01.2014
comment
Хороший вопрос, Питер, спасибо. Я расширил ответ двумя вариантами: крючок до сборки и после сборки. - person akhikhl; 10.01.2014
comment
Участвовать в таких дискуссиях одно удовольствие, многому учишься :) - person akhikhl; 10.01.2014
comment
Меня только что осенило, что есть одно (потенциально важное) отличие между решением от @PeterNiederwieser и от меня: вариант Питера будет вызываться ВСЕГДА, независимо от выполнения других задач. Мой вариант (post-hook и pre-hook) будет вызываться ТОЛЬКО ТОГДА, когда хотя бы одна другая задача была выполнена (напрямую или как зависимость). Например, если все задачи актуальны, то хуки не выполняются. - person akhikhl; 10.01.2014

Что плохого в том, чтобы вызвать его прямо из корня build.gradle?

task init << {
    println "I always run"
}

tasks.init.execute()
person Nick Grealy    schedule 14.10.2015
comment
execute() теперь является устаревшей функцией и будет удалена в Gradle 5.0. - person DPancs; 18.05.2018