Я пытаюсь создать простую программу 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 (например, как описано на странице это), но плагин кажется довольно сложным в использовании, и у меня уже достаточно проблем с рядом сложностей в этом проекте, которые Я не решаюсь вводить в эту смесь плагины с очень слабой документацией и открытым исходным кодом. Я действительно пытаюсь создать самую простую возможную программу "Hello, World" на JavaFX / Gradle на данный момент, и это пока что казалось на удивление сложным. .).
Любая помощь будет оценена по достоинству.


Surprisingly, my Google searches have not turned up a document that maps each Groovy construct to its equivalent Kotlin construct or explains in general how to convert Groovy DSL code to equivalent Kotlin DSL code.
Пожалуйста, взгляните на 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')
}
Спасибо за указатель на документ. К сожалению, похоже, что он не предоставляет полного сопоставления Groovy-to-Kotlin и не отвечает на мой конкретный вопрос. В частности, похоже, что нет никакого свойства с именем "jvmArgs", доступного в области действия вызова "doFirst". Я попытался указать явный тип для вызова getByName ('tasks.getByName <Run> ("run")'), но это тоже не сработало.
Решает ли этот комментарий к проблеме Gradle вашу проблему? Если да, то я соответствующим образом обновлю свой ответ.
К сожалению, этот комментарий решает другую проблему (а именно, как найти определенные задачи, которые реализуют интерфейс, который не является их суперклассом задач). Ответ @lwestby верен в том смысле, что в этом случае будет использоваться правильный тип JavaExec, а не Run as Я предполагал.
Спасибо, я соответствующим образом отредактировал свой ответ, чтобы избежать путаницы.
Используя 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")
}
}
Спасибо. Я смог успешно запустить свою программу, используя этот синтаксис. Отметка ответа как «Принято».
В Gradle 5.0 и kotlin-dsl 1.0 задачи, которые зарегистрированы или созданы плагинами, могут быть статически доступны через контейнер tasks (TaskContainer. В примечания к выпуску представлен этот пример:
plugins { java } tasks { named<Test>("test") { testLogging.showStacktraces = true } }you can now write:
plugins { java } tasks { test { testLogging.showStacktraces = true } }
В вашем примере вы, скорее всего, используете плагин application, который регистрирует задачу run, чтобы вы могли настроить ее аналогичным образом. Одна проблема, о которой следует знать, заключается в том, что run конфликтует с методом Kotlin stdlib run, поэтому вам нужно применить обходной путь, чтобы убедиться, что он вызывается (см. Градл / Котлин-DSL / вопросы / 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"
)
}
}
}
Другие ответы показывают, как вы можете использовать имя, тип или комбинацию для запроса контейнера для конкретных задач.
Я обновился до Gradle 5, но не смог заставить этот код работать так, как написано здесь, потому что run - это также имя стандартной функции расширения Kotlin, доступной для всех классов (kotlin.run в стандартной библиотеке) и Gradle настаивал на использовании этого вместо org.gradle.kotlin.dsl.run. Мне пришлось использовать «import org.gradle.kotlin.dsl.run как run1», а затем использовать «run1» в моем коде. Есть ли более чистый способ сделать это?
Хороший улов @SomeGuy - я обновил ответ и добавил ссылку на открытую проблему, похожую на
Примечание. Чтобы никого не сбить с толку, «Котлин, эквивалентный первой части» на самом деле более правильно
tasks.named<JavaCompile>('compileJava'){ ... }, который будет влиять только на одну конкретную задачу JavaCompile с заданным именем, а не на все они (например, задача 'compileTestJava' также может существуют и имеют тип JavaCompile).