2016-04-02 3 views
2

Есть ли какой-нибудь опрятный, простой способ абстрагировать элементы задачи в градиенте?DRY Gradle Tasks

Я создаю смешанный проект, который включает в себя некоторые Scala, которые должны быть скомпилированы в Javascript - что не представляется возможным с Gradle в одиночку. Однако я в конечном итоге с несколькими задачами, которые выглядят следующим образом:

task buildScalaJS(type: Exec) { 
    workingDir './scalajs' 
    commandLine '../sbt', 'fastOptJS' 
} 

task buildScalaJSLauncher(type: Exec, dependsOn: buildScalaJS) { 
    workingDir './scalajs' 
    commandLine '../sbt', 'scalaJSLauncher' 
} 

Моя первая мысль была абстрагировать это в функции, как:

def sbt(String... params) { 
    workingDir './scalajs' 
    commandLine('../sbt', params) 
} 

Однако эти свойства не существуют вне сферы определение задачи, поэтому это (понятно) приводит к ошибке.


Единственный способ, который я могу себе представить, чтобы иметь функцию, которая генерирует задачи:

def sbtTask(String taskName, String sbtTask = taskName, Map options) { 
    Map defaultOptions = [type: Exec] 
    task ("${taskName}", (defaultOptions << options)) { 
     workingDir './scalajs' 
     commandLine '../sbt', sbtTask 
    } 
} 

sbtTask('buildScalaJS', 'fastOptJS') 
sbtTask('buildScalaJSLauncher', 'scalaJSLauncher', dependsOn: 'buildScalaJS') 

Однако Gradle жалуется, что метод «sbtTask()» не может быть найден.


Может кто-нибудь предложить способ сделать это?

ответ

3

Ваш первый вариант должен работать, если добавить задачу в качестве аргумента sbt():

def sbt(task, String ... params) { 
    task.workingDir './scalajs' 
    task.commandLine('../sbt', params) 
} 

task buildScalaJS(type: Exec) { 
    sbt delegate, 'fastOptJS' 
} 

task buildScalaJSLauncher(type: Exec, dependsOn: buildScalaJS) { 
    sbt delegate, 'scalaJSLauncher' 
} 

EDIT: Теперь я вижу, что вы, вероятно, получите проблему с помощью метода CommandLine, так как аргументы будут переданы в (String, String []). Вам нужно будет объединить их в один список или массив, например: task.commandLine(['../sbt'] + (params as List))

Ваш второй вариант также должен работать, но у вас есть проблема в определении функции и определении задачи. Попробуйте изменить его примерно на следующее:

def sbtTask(Map options = [:], String taskName, String sbtTask) { 
    Map defaultOptions = [type: Exec] 
    task(defaultOptions + options, taskName) { 
     workingDir './scalajs' 
     commandLine '../sbt', sbtTask 
    } 
} 

sbtTask 'buildScalaJS', 'fastOptJS' 
sbtTask 'buildScalaJSLauncher', 'scalaJSLauncher', dependsOn: 'buildScalaJS' 
+0

Также +1 за то, что он сообщил мне о делете! Похоже, что основной проблемой I со вторым решением было упорядочение аргументов функции. Я немного поиграл с ним; Правильно ли я считаю, что наличие опций исключает другие значения по умолчанию? И карта параметров должна быть первым аргументом? –

+1

Первоначально я думал, что у вас могут быть другие значения по умолчанию даже с картой параметров, но он не мог заставить его работать при экспериментировании. И да, если карта опций является первым аргументом, вы можете поместить записи в карты в любом месте списка аргументов. – Steinar

+0

+1 ... «делегат» просто спас меня от увеличения количества заданий с повторными определениями в моем файле gradle, который теперь является СУХОЙ и более удобным для обслуживания – risteli