1. 概述
在这个教程中,我们将探讨Gradle工具链支持JVM项目的方法。我们将首先理解这个功能的动机,然后定义它,并通过实际示例进行演示。
2. 工具链背后的原因
在讨论什么是工具链之前,我们需要了解其存在的原因。假设我们要编写一个Java项目,它可能包含一些测试。因此,我们至少希望编译代码并运行测试。我们添加内置的java
Gradle插件,并指定所需的字节码版本:
plugins {
id 'java'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
此外,我们可以告诉Gradle根据需要将测试类编译成不同的字节码版本:
tasks {
compileTestJava {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}
到目前为止,一切正常。唯一的微妙之处是,为了编译源代码/测试类,Gradle使用了自己的JDK,即它运行的JDK。不过,我们可以通过指定确切的可执行文件来解决这个问题:
compileTestJava.getOptions().setFork(true)
compileTestJava.getOptions().getForkOptions().setExecutable('/home/mpolivaha/.jdks/corretto-17.0.4.1/bin/javac')
compileJava.getOptions().setFork(true)
compileJava.getOptions().getForkOptions().setExecutable('/home/mpolivaha/.jdks/corretto-17.0.4.1/bin/javac')
然而,如果在构建过程中使用了各种JDK,问题就出现了。
例如,假设我们在发布前必须在客户的JDK上测试我们的Java应用。这些JDK可能来自不同的供应商,尽管符合规范,但在细节上可能会有所不同。理论上,我们可以不使用工具链解决这个问题,但解决方案会复杂得多。工具链使需要为不同目的使用不同JDK的构建配置更加简单。
3. 工具链定义
从Gradle 6.7版本开始,引入了JVM工具链功能。虽然工具链的概念并不新鲜,Maven已经存在一段时间了此处链接。一般来说,工具链是一组用于构建、测试和运行软件所需的工具和二进制文件。因此,在Java中,我们可以将JDK视为Java工具链,因为它允许编译、测试和运行Java程序。
我们可以在项目级别定义工具链,如下所示:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
vendor = JvmVendorSpec.AMAZON
implementation = JvmImplementation.VENDOR_SPECIFIC
}
}
这样,我们可以指定所需的Java版本、JDK供应商以及该供应商特定的JVM实现。为了使工具链规范正确,至少需要设置版本.
当Gradle处理工具链时,它的行为很简单。首先,它会尝试在本地查找请求的工具链;这里有一个特定的算法。如果Gradle在本地找不到所需的工具链,它会尝试从远程查找并下载。如果Gradle无法在远程找到所需的工具链,构建就会失败。
值得一提的是,有时我们可能希望禁用自动提供。我们可以通过将\-Porg.gradle.java.installations.auto-download=false
传递给gradle
可执行文件来做到这一点。在这种情况下,如果工具链在本地找不到,Gradle构建将失败。
4. 在任务级别使用工具链
工具链的真正威力在于能够按任务方式指定JDK安装:
tasks.named('compileJava').get().configure {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(17)
vendor = JvmVendorSpec.AMAZON
implementation = JvmImplementation.VENDOR_SPECIFIC
}
}
tasks.register("testOnAmazonJdk", Test.class, {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
vendor = JvmVendorSpec.AMAZON
}
})
tasks.named("testClasses").get().finalizedBy("testOnAmazonJdk")
在上面的示例中,我们配置了compileJava
任务在Oracle JDK 15上运行。我们还创建了一个名为testOnAmazonJdk
的任务,它将在testClasses
任务之后运行。请注意,这个新任务也在单独的JDK上执行。
5. 查看本地工具链
最后,Gradle允许我们使用以下命令查看当前项目可用的本地工具链安装:
gradle javaToolchains
首先,Gradle会在当前位置搜索构建文件,然后根据构建文件中指定的位置/规则列出找到的工具链。
6. 总结
在这篇简短的教程中,我们回顾了Gradle的工具链功能。如果适用,这个功能简化了在构建过程中使用不同JDK的工作。它从Gradle 6.7开始可用,并且我们可以在任务级别应用,这使得这个功能非常有价值。
如往常一样,本文的源代码可以在GitHub上找到。