介绍 Java 工具链
构建 Java 项目和运行 Gradle 都需要安装 JDK。大多数 Gradle 用户方便地使用运行 Gradle 的 Java 安装来构建和测试他们的应用程序。
虽然这在简单情况下是可以接受的,但这种方法存在一些问题。例如,如果构建需要在所有机器上使用相同的 Java 版本,则每个开发人员都需要了解该要求并手动安装该版本。
以前可以配置 Gradle 使用与运行 Gradle 的 Java 版本不同的 Java 版本构建项目。但是,这需要分别配置每个任务,例如编译、测试和 javadoc。
Gradle 6.7 引入了“Java 工具链支持”。简而言之,它允许您使用已安装的任何版本的 Java 运行 Gradle,而 Gradle 使用在单个位置声明的 Java 版本构建项目。Gradle 将自动配置构建,检测已安装的 JDK,并在尚未安装的情况下下载所需的 JDK。
不再需要 release
或 sourceCompatibility
调整,也不再需要描述应安装哪个 JDK 才能使构建正常工作的维基页面。优势是巨大的,让我们看看如何使用它!
介绍 Java 工具链支持
Java 工具链支持允许构建作者声明他们的项目需要哪个 Java 版本来编译、测试和运行他们的代码。
项目范围配置
让我们从构建作者至少需要做的事情开始
plugins {
id("java-library") // or id("application")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
就是这样!
在 Gradle 6.7 中,上述配置能带来什么?
你会得到
- 所有 Java 编译任务将使用 Java 11 进行构建。这意味着
main
和test
源集中的代码,以及您添加的任何自定义源集中的 Java 代码,都将使用配置的 Java 版本进行构建。 - 所有测试任务,包括默认的
test
任务和任何其他自定义Test
任务,都将使用 Java 11 运行测试。 javadoc
任务将使用 Java 11 构建文档。
此外,使用 application
插件,run
任务将使用 Java 11 启动您的应用程序。
在幕后,Gradle 将
- 从 已知位置 列表中找到 Java 11 安装,例如 asdf、jabba、SDKMAN! 或每个操作系统的标准位置
- 验证安装及其版本
- 如果未找到 Java 11 安装,Gradle 将尝试从 下载 AdoptOpenJDK
如果 Gradle 无法找到所需的 Java 版本,您可以告诉它 在哪里查找。
任务级别配置
在某些情况下,您需要为特定任务使用不同的工具链。假设您开发的库具有取决于其运行的 Java 版本的特定代码路径。您需要确保两个代码路径都被执行,因此将使用不同的 Java 版本运行一组测试。此场景支持如下。
tasks.register<Test>("extraTests") {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(14))
})
}
前往 文档 了解更多信息。
使用工具链的更多好处
除了我们之前讨论过的优势外,工具链还可以帮助解决更多情况。
Gradle 在构建尚未发布的 Java 版本(例如本文撰写时的 Java 16)的代码时存在问题,这可能会导致现有 Gradle 版本(例如当前的 6.7 版本)无法运行。
借助工具链支持,Gradle 6.7 能够完美地使用尚未发布的语言版本编译和测试代码。您只需要告诉它这样做即可。
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(16))
}
}
此外,代码在使用不同的 Java 版本构建和运行时可能会表现出不同的行为,这可能会导致难以诊断的问题。
即使没有影响系统行为的不兼容性,在不同机器上使用不同的 Java 版本构建项目也会降低构建性能,因为 构建缓存 丢失。
放宽 Gradle 上的 Java 版本约束
除了对构建作者的好处外,此功能还将对 Gradle 本身的开发产生影响。到目前为止,Gradle 假设它将使用与项目所需的相同版本的 Java 运行。这意味着 Gradle 必须能够使用一组跨越使用 Gradle 的项目的需要的 Java 版本运行。在 Java 5 到 8 的发布节奏中,这可能是可以接受的。随着新的 Java 发布计划,这将更加成问题。
从 6.7 版本开始,Gradle 需要
- 至少 Java 8 才能运行构建,
- 每天使用 11 构建
- 并测试到 Java 15。
所有这些都需要相当复杂的 CI 设置,并对 Gradle 核心开发施加了限制。例如,Gradle 工程师无法访问 Java 8 以外的功能和 API 来开发该工具。
一旦工具链在社区中被采用,我们最终将能够在 Gradle 的运行时要求方面不那么保守。Gradle 然后可能只在相对较新的 Java 版本上运行,同时通过工具链支持构建旧版 Java 版本的代码。
工具链的下一步是什么?
在 Gradle 6.7 中,工具链支持仅限于 Java 专用插件已知的任务
JavaCompile
Test
Javadoc
JavaExec
计划在下一个 Gradle 版本中添加对 Groovy 和 Scala 插件的工具链支持。
我们还希望,鉴于此功能对用户的益处,社区 插件作者将在他们自己的任务中利用工具链支持。