新闻

在Kotlin插件中支持Gradle JVM工具链

维护Gradle Build设置具有可靠和可重复的构建过程并不总是容易的。在这个博客文章中,我们将告诉您Kotlin最近增加了支持的毕业功能之一 -JVM工具链.该特性提供了一种独立于用户JDK的可复制构建的简单方法,而且还降低了使用多个JDK的复杂性。

什么是Gradle JVM工具链特性以及如何使用它?

构建Gradle JVM项目的问题

假设你维护一个JVM库或应用程序的Gradle构建设置。一个常见的用户错误是使用错误的JDK版本来编译项目,这将导致奇怪的错误。

当您的项目支持不同的JDK版本来编译或运行测试时,这变得更加复杂。您需要添加有关如何设置构建环境的广泛文档,某些自定义构建脚本为特定编译或测试任务选择正确的JDK版本以及复杂的CI设置。即便如此,错误可能会滑动,并且可以使用错误的条目填充Gradle远程构建缓存,导致稍后的发布构建中的难以调试错误。

不幸的是,Kotlin Gradle插件没有将JDK版本作为任务输入直到Kotlin 1.5.30发布

kotlin存储库也遭受了痛苦

正如您可能已经猜到的那样,这就是它在Kotlin存储库本身。Kotlin 1.6.0支持从JDK 1.6到17的JDK版本(此刻最新发布的版本)。此外,它使用编译器中的不同jdks,以及构建工具测试,以验证编译器的输出是否正确使用不同的jdks。

要开始使用Kotlin项目,贡献者必须在本地安装各种jdk。出于几个原因,这已经是一个痛苦的步骤。例如,在较新的macOS版本中,很难找到可用的JDK 1.6和JDK 1.7版本。为了克服这个问题,Kotlin存储库添加了一个标志来用JDK 1.8替换这些JDK。

之后,贡献者必须设置需要正确对应于JDK位置所需的所有环境变量。有时贡献者犯了一个错误并提供错误的JDK版本,再次导致奇怪的编译和测试错误。

最后,贡献者必须确保构建在JDK 1.8上运行(通常通过更改java_home.环境变量)。

解决方案:工具链特性

幸运的是,Gradle团队介绍了一个名为的新功能JVM工具链在6.7释放中。最初,只支持Java编译,但最近的Gradle 7.2版本,Groovy和Scala编译也使用JVM Toolchains。从中开始kotlin gradle插件为此功能增加了支持1.5.30释放!

用工具链构建——它有什么帮助?

JVM工具链特性做什么?

基于用户提供的规范,Gradle检测本地安装的JDK或JRE或下载所请求的JDK或下载。默认下载目标是gradle_user_home / jdks /目录。该规范包括以下内容:

  • Java主要语言版本
  • 可选供应商(例如,Azul的)
  • 可选实施(例如,J9.的)

工具箱可用后,Gradle提供了工具链工具,如javacjavadoc.,java.对相关任务的可执行文件。

此外,如果用户未明确设置规范,则Gradle配置源和目标兼容性值等于工具链。Kotlin Gradle Plugin对于Kotlin任务为相同的操作。

让我们从一个简单的案例开始:您的图书馆要求支持JDK版本11或更新。只需添加以下工具链规范build.gradle.kts

这将告诉Gradle找到JDK 11,并将其用于编译、javadoc和测试任务。如果你没有在本地安装JDK 11, Gradle会自动下载它。

让我们想象一下,在某个时刻,您决定对最新的JDK运行测试,以验证项目是否可以正常工作。使用工具链,同样很容易做到——你只需要添加一个新任务:

您可能还希望支持在较新的JDKS中引入的一些功能。您已经了解了Gradle Metadata,并希望用户使用最新的JDK能够使用所有发布的功能。这有点复杂,但仍然很容易做到:

您可以进一步脱颖而出,并添加运行任务,该任务将在JDK 11和JDK 15上运行您的项目。

在这些更改之后,新的开发人员可以立即开始为项目做出贡献。

更好的是,如果您在此更改之前配置了远程构建缓存 - 现在独立于JDK版本Gradle运行,则构建将为使用工具链的任务点击此远程缓存。请注意,您还应该定义工具链buildsrc.模块要充分利用远程构建缓存。

Kotlin插件中的工具链支持

与Java编译类似,Kotlin编译器也依赖于它所运行的带有默认配置的Kotlin/JVM目标的JDK。在这种情况下,Kotlin编译器使用它正在执行的JDK运行时类。但是,与此同时,Kotlin编译器具有选项-jdk-home通过以下描述:将指定位置的自定义JDK包含到类路径中,而不是默认的JAVA_HOME.实际上,Kotlin编译器本身总是独立于运行时JDK版本生成相同的输出-jdk-home(或相关-no-jdk)是指定的。

在Kotlin中,工具链支持只影响Kotlin/JVM-jdk-home选项的值,并另外设置-jvm-target值,如果该值未由用户显式设置。此外,Toolchain的主要JDK版本现在被视为现在输入的任务输入。

我们已经在Kotlin扩展中添加了一个特殊的DSL,以配置类似于Java的Gradle DSL的工具链。它强调了只影响Kotlin/JVM的工具链,并在仅使用Kotlin时略微简化了构建脚本。在底层,这个DSL在同一个Gradle模块中为Java和Kotlin编译配置了相同的默认工具链对象。或者,正如您已经猜到的,您仍然可以为Java工具链使用Gradle DSL。两种方法都是一样的:

Kotlin Gradle插件确保Kotlin和Java编译任务具有相同的JVM目标,以避免难以调试的错误。即使为特定任务显式地设置了工具链,Kotlin编译仍然会检查相关的Java编译JVM目标,如果存在不匹配,则会产生警告。这可以通过kotlin.jvm.target.validation.mode财产。

结论

我曾经问过Gradle开发人员关于工具链特性的看法,他们说允许用户在任何JDK上运行构建,但仍然生成相同的输出。

在此答案上展开,任何其输出取决于JDK / Java版本的任务都应使用Toolchain功能来选择预定义的JDK。这将允许用户具有独立于当前用户环境的可再生构建。

事实上,这已经在Kotlin回购中实现了!现在开发人员可以使用任何JDK来编译Kotlin,如果缺少JDK, Gradle会自动提供。你可以自己试一试——只要克隆芬兰湾的科特林回购并运行一些成绩任务。不幸的是,GradleTupthain功能在1.8版之前没有自动配置JDK,但Kotlin repo仍然需要一些模块的JDK 1.6和JDK 1.7。你可以加kotlin.build.isobsoletejdkoverRideEnabled = truelocal.properties强制构建仅使用JDK版本1.8和更新。

另请参阅

Baidu