Эквивалент Gradle Kotlin DSL для Groovy DSL 'run'?

Я пытаюсь создать простую программу JavaFX 11 с Kotlin и Java 11, используя Gradle, следуя инструкциям здесь. Однако на этой странице используется Groovy DSL от Gradle, и я пытаюсь использовать Kotlin DSL. Удивительно, но мои поиски в Google не нашли документа, который сопоставляет каждую конструкцию Groovy с ее эквивалентной конструкцией Kotlin или объясняет в целом, как преобразовать код Groovy DSL в эквивалентный код Kotlin DSL. (Это похоже на большой упущение в документации Gradle!).

В частности, этот документ содержит следующий код Groovy:

compileJava {
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'javafx.controls'
        ]
    }
}

run {
     doFirst {
         jvmArgs = [
             '--module-path', classpath.asPath,
             '--add-modules', 'javafx.controls'
         ]
    }
}

Насколько я могу судить, котлинский эквивалент первой части выглядит следующим образом:

tasks.withType<JavaCompile> {
    options.compilerArgs.addAll(arrayOf(
        "--module-path", classpath.asPath,
        "--add-modules", "javafx.controls"
    ))
}

Однако мне не удалось понять, что такое Kotlin DSL, эквивалентный второй части. Обратите внимание, что «run» - это стандартное расширение функции в стандартной библиотеке Kotlin, поэтому не похоже, что Kotlin-версия этого кода может использовать имя «run» для той же цели в Kotlin DSL.

(Примечание: я рассматривал возможность использования подключаемого модуля для поддержки JavaFX (как описано в this page, например), но плагин кажется довольно сложным в использовании, и у меня уже достаточно проблем с рядом сложностей в этом проекте, поэтому я не решаюсь ввести в него очень слабо документированный плагин с открытым исходным кодом. На данный момент я действительно пытаюсь создать самую простую программу "Hello, World" на JavaFX / Gradle, и это пока казалось на удивление сложным.)

Любая помощь будет оценена по достоинству.


person Some Guy    schedule 02.11.2018    source источник
comment
Примечание: Чтобы никого не сбить с толку, Kotlin, эквивалент первой части, на самом деле более правильно tasks.named<JavaCompile>('compileJava'){ ... }, который будет влиять только на одну конкретную задачу JavaCompile с заданным именем, а не на все они (например, задача 'compileTestJava' также может существовать и имеют тип JavaCompile).   -  person Some Guy    schedule 07.11.2018


Ответы (3)


Используя API-интерфейсы предотвращения конфигурации, эквивалент второго блока:

tasks.named<JavaExec>("run") {
    doFirst {
        jvmArgs = listOf("--module-path", classpath.asPath,"--add-modules", "javafx.controls")
    }
}

Ключ в том, что run имеет тип JavaExec, который, как и любой тип задачи, можно обнаружить, создав задачу для печати класса задачи, которую вы затем запускаете:

tasks.register("getName") {
    doFirst {
        print("Class name: ${tasks["run"].javaClass}")
    }
}

Обратите внимание, что по мере роста вашего приложения JavaFX вам нужно будет указать дополнительные модули, например:

tasks.named<JavaExec>("run") {
    doFirst {
        jvmArgs = listOf("--module-path", classpath.asPath,
            "--add-modules", "javafx.base,javafx.controls,javafx.graphics")
    }
}
person lwestby    schedule 03.11.2018
comment
Спасибо. Я смог успешно запустить свою программу, используя этот синтаксис. Отметка ответа как принятого. - person Some Guy; 07.11.2018

Удивительно, но мои поиски в Google не нашли документа, который сопоставляет каждую конструкцию Groovy с ее эквивалентной конструкцией Kotlin или объясняет в целом, как преобразовать код Groovy DSL в эквивалентный код Kotlin DSL.

Взгляните на https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/ и особенно. раздел Настройка задач. В соответствии с этим, я бы сказал, что эквивалент Kotlin DSL

tasks.named<JavaExec>("run").doFirst {
    jvmArgs = listOf('--module-path', classpath.asPath, '--add-modules', 'javafx.controls')
}
person sschuberth    schedule 02.11.2018
comment
Спасибо за указатель на документ. К сожалению, похоже, что он не предоставляет полного сопоставления Groovy-to-Kotlin и не отвечает на мой конкретный вопрос. В частности, похоже, что в области действия вызова doFirst нет никакого свойства с именем jvmArgs. Я попытался указать явный тип для вызова getByName ('tasks.getByName ‹Run› (run)'), но это тоже не сработало. - person Some Guy; 03.11.2018
comment
Решает ли этот комментарий к проблеме Gradle вашу проблему? Если да, то я соответствующим образом обновлю свой ответ. - person sschuberth; 03.11.2018
comment
К сожалению, этот комментарий решает другую проблему (а именно, как найти определенные задачи, которые реализуют интерфейс, который не является их суперклассом задач). Ответ @lwestby верен в том смысле, что в этом случае будет использоваться правильный тип JavaExec, а не Run as Я предполагал. - person Some Guy; 07.11.2018
comment
Спасибо, я соответствующим образом отредактировал свой ответ, чтобы избежать путаницы. - person sschuberth; 07.11.2018

В Gradle 5.0 и kotlin-dsl 1.0 задачи, которые зарегистрированы или созданы плагинами, могут быть статически доступны через контейнер tasks (_ 3_. Этот пример приведен в примечания к выпуску:

plugins {
    java
}

tasks {
    named<Test>("test") {
        testLogging.showStacktraces = true
    }
}

теперь вы можете написать:

plugins {
    java
}

tasks {
    test {
        testLogging.showStacktraces = true
    }
}

В вашем примере вы, скорее всего, используете плагин application, который регистрирует run задача, чтобы вы могли настроить ее аналогично. Следует иметь в виду, что run конфликтует со стандартной библиотекой Kotlin run < / a>, поэтому вам нужно применить обходной путь, чтобы убедиться, что он вызывается (см. gradle / kotlin-dsl / issues / 1175).

tasks {
  compileJava {
    doFirst {
      jvmArgs = listOf("--module-path", classpath.asPath,
          "--add-modules", "javafx.base,javafx.controls,javafx.graphics")
    }
  }

  (run) {
    doFirst {
      jvmArgs = listOf(
        "--module-path", classpath.asPath,
        "--add-modules", "javafx.controls"
      )
    }
  }
}

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

person mkobit    schedule 01.12.2018
comment
Я обновился до Gradle 5, но не смог заставить этот код работать так, как написано здесь, потому что run - это также имя стандартной функции расширения Kotlin, доступной для всех классов (kotlin.run в стандартной библиотеке) и Gradle настаивал на использовании этого вместо org.gradle.kotlin.dsl.run. Мне пришлось использовать import org.gradle.kotlin.dsl.run как run1, а затем использовать run1 в моем коде. Есть ли более чистый способ сделать это? - person Some Guy; 02.12.2018
comment
Хороший улов @SomeGuy - я обновил ответ и добавил ссылку на открытую проблему, похожую на - person mkobit; 04.12.2018