【问题标题】:Gradle Kotlin DSL equivalent for Groovy DSL 'run'?Gradle Kotlin DSL 等效于 Groovy DSL“运行”?
【发布时间】:2019-04-06 17:01:03
【问题描述】:

我正在尝试使用 Gradle,按照 here 的说明,使用 Kotlin 和 Java 11 构建一个简单的 JavaFX 11 程序。但是,此页面使用 Gradle 的 Groovy DSL,我正在尝试使用 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'
         ]
    }
}

据我所知,相当于第一部分的 Kotlin 似乎是:

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

但是,我无法弄清楚与第二部分等效的 Kotlin DSL 是什么。请注意,“run”是 Kotlin 标准库中的标准函数扩展,因此在 Kotlin DSL 中,此代码的 Kotlin 版本似乎不能出于相同目的使用名称“run”。

(注意:我考虑过尝试使用插件来支持 JavaFX(例如,如 this 页面所述),但该插件似乎使用起来相当复杂,而且我已经遇到了足够多的问题这个项目的复杂性,我犹豫是否将一个文档非常简单的开源插件引入到组合中。我现在真的正在尝试在 JavaFX/Gradle 中生成最简单的“Hello, World”程序,这有到目前为止似乎非常困难。)。

任何帮助将不胜感激。

【问题讨论】:

  • 注意:为避免混淆任何人,“Kotlin 等效于第一部分”实际上更正确的是tasks.named&lt;JavaCompile&gt;('compileJava'){ ... },它只会影响具有给定名称的一个特定 JavaCompile 任务,而不是所有任务(例如,“compileTestJava”任务也可能存在并具有 JavaCompile 类型。

标签: gradle javafx java-11 gradle-kotlin-dsl javafx-11


【解决方案1】:

令人惊讶的是,我的 Google 搜索没有找到将每个 Groovy 构造映射到其等效的 Kotlin 构造的文档,或者一般解释如何将 Groovy DSL 代码转换为等效的 Kotlin DSL 代码。

请查看https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/ 和esp。 Configuring tasks 部分。据此,我会说 Kotlin DSL 等价物是

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

【讨论】:

  • 感谢您提供指向文档的指针。不幸的是,它似乎没有提供完整的 Groovy 到 Kotlin 的映射,也没有回答我的具体问题。具体来说,“doFirst”调用范围内似乎没有任何名为“jvmArgs”的属性可用。我尝试为 getByName 调用 ('tasks.getByName("run")') 提供显式类型,但这也不起作用。
  • this comment 到 Gradle 问题是否解决了您的问题?如果是这样,我会相应地更新我的答案。
  • 不幸的是,该评论正在解决一个不同的问题(即如何找到实现不是其任务超类的接口的某些任务)。@lwestby 的答案是正确的,因为要使用的正确类型这个案例是 JavaExec,而不是我想象的 Run。
  • 谢谢,我已经相应地编辑了我的答案以避免混淆。
【解决方案2】:

使用配置避免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")
    }
}

【讨论】:

  • 谢谢。我能够使用这种语法成功运行我的程序。将此答案标记为“已接受”。
【解决方案3】:

使用 Gradle 5.0 和kotlin-dsl 1.0,可以通过tasks 容器(TaskContainer)静态访问插件注册或创建的任务。release notes 中提供了这个示例:

plugins {
    java
}

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

你现在可以写了:

plugins {
    java
}

tasks {
    test {
        testLogging.showStacktraces = true
    }
}

对于您的示例,您最有可能使用application 插件,该插件注册了run 任务,因此您可以以类似的方式对其进行配置。需要注意的一个问题是 run 与 Kotlin 标准库 run 方法发生冲突,因此您需要应用一些变通方法以确保它被调用(请参阅 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"
      )
    }
  }
}

其他答案展示了如何使用名称、类型或组合来查询特定任务的容器。

【讨论】:

  • 我更新到 Gradle 5,但无法让此代码按此处编写的那样工作,因为“运行”也是可用于所有类的标准 Kotlin 扩展函数的名称 (kotlin.run在标准库中),Gradle 坚持使用那个而不是 org.gradle.kotlin.dsl.run。我不得不使用“import org.gradle.kotlin.dsl.run as run1”,然后在我的代码中使用“run1”。有没有更清洁的方法来做到这一点?
  • 好消息@SomeGuy - 我已经更新了答案并添加了一个指向类似的未决问题的链接
猜你喜欢
  • 2019-09-15
  • 1970-01-01
  • 2019-03-22
  • 2018-11-05
  • 1970-01-01
  • 2022-10-14
  • 2022-12-10
  • 2018-09-13
  • 1970-01-01
相关资源
最近更新 更多