Scala 插件
Scala 插件扩展了 Java 插件,以增加对 Scala 项目的支持。该插件还支持联合编译,允许您在两个方向上自由混合和匹配 Scala 和 Java 代码及其依赖项。例如,一个 Scala 类可以扩展一个 Java 类,而该 Java 类又可以扩展一个 Scala 类。这使得可以使用最适合工作的语言,并在需要时用另一种语言重写任何类。
请注意,如果您想从 API / 实现分离 中受益,您也可以将 java-library
插件应用于您的 Scala 项目。
用法
要使用 Scala 插件,请在您的构建脚本中包含以下内容
plugins {
id("scala")
}
plugins {
id("scala")
}
任务
Scala 插件向项目添加以下任务。有关更改 Java 编译任务依赖项的信息,请参见此处。
compileScala
— ScalaCompile-
依赖于:
compileJava
编译生产 Scala 源文件。
compileTestScala
— ScalaCompile-
依赖于:
compileTestJava
编译测试 Scala 源文件。
compileSourceSetScala
— ScalaCompile-
依赖于:
compileSourceSetJava
编译给定源集的 Scala 源文件。
scaladoc
— ScalaDoc-
为生产 Scala 源文件生成 API 文档。
ScalaCompile
和 ScalaDoc
任务开箱即用地支持 Java 工具链。
Scala 插件向 Java 插件添加的任务添加以下依赖项。
任务名称 | 依赖于 |
---|---|
|
|
|
|
|
|

项目布局
Scala 插件假定项目布局如下所示。所有 Scala 源目录都可以包含 Scala 和 Java 代码。Java 源目录可能只包含 Java 源代码。这些目录都不需要存在或包含任何内容;Scala 插件只会编译它找到的任何内容。
src/main/java
-
生产 Java 源代码。
src/main/resources
-
生产资源,例如 XML 和 properties 文件。
src/main/scala
-
生产 Scala 源代码。也可能包含用于联合编译的 Java 源文件。
src/test/java
-
测试 Java 源代码。
src/test/resources
-
测试资源。
src/test/scala
-
测试 Scala 源代码。也可能包含用于联合编译的 Java 源文件。
src/sourceSet/java
-
源集名为 sourceSet 的 Java 源代码。
src/sourceSet/resources
-
源集名为 sourceSet 的资源。
src/sourceSet/scala
-
给定源集的 Scala 源文件。也可能包含用于联合编译的 Java 源文件。
更改项目布局
就像 Java 插件一样,Scala 插件允许您为 Scala 生产和测试源文件配置自定义位置。
sourceSets {
main {
scala {
setSrcDirs(listOf("src/scala"))
}
}
test {
scala {
setSrcDirs(listOf("test/scala"))
}
}
}
sourceSets {
main {
scala {
srcDirs = ['src/scala']
}
}
test {
scala {
srcDirs = ['test/scala']
}
}
}
Scala 版本
可以直接在 scala
扩展上声明 Scala 版本。依赖项会根据声明的 Scala 版本自动添加到 scalaToolchain
配置中。scalaToolchainRuntimeClasspath
配置解析 scalaToolchain
配置上声明的依赖项,并包含运行 Scala 编译器所需的文件。
当设置 scalaVersion 属性时,无需声明 Scala SDK 的直接依赖项。 |
repositories {
mavenCentral()
}
scala {
scalaVersion = "2.13.12"
}
repositories {
mavenCentral()
}
scala {
scalaVersion = "2.13.12"
}
配置 Gradle 以使用 Scala 3 与 Scala 2 没有区别。
repositories {
mavenCentral()
}
scala {
scalaVersion = "3.6.3"
}
repositories {
mavenCentral()
}
scala {
scalaVersion = "3.6.3"
}
scalaVersion 属性正在孵化中。 |
声明 Scala 依赖项
当不使用 scalaVersion
属性时,必须在 implementation
配置上手动声明 Scala SDK 依赖项。不建议使用此模式,因为它依赖于从生产运行时类路径推断 Scala 类路径。从 scala
扩展中省略 Scala 版本将在未来的 Gradle 版本中弃用。
Scala 2 项目需要声明 scala-library
依赖项。
repositories {
mavenCentral()
}
dependencies {
implementation("org.scala-lang:scala-library:2.13.12")
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.scala-lang:scala-library:2.13.12")
}
Scala 3 项目需要声明 scala3-library_3
依赖项
repositories {
mavenCentral()
}
dependencies {
implementation("org.scala-lang:scala3-library_3:3.6.3")
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.scala-lang:scala3-library_3:3.6.3")
}
如果 Scala 仅用于测试代码,则应将 scala-library
依赖项添加到 testImplementation
配置中
dependencies {
testImplementation("org.scala-lang:scala-library:2.13.12")
}
dependencies {
testImplementation("org.scala-lang:scala-library:2.13.12")
}
scalaClasspath 的自动配置
ScalaCompile
和 ScalaDoc
任务通过两种方式使用 Scala 代码:在其 classpath
上及其 scalaClasspath
上。前者用于定位源代码引用的类,通常包含 scala-library
以及其他库。后者用于加载和执行 Scala 编译器和 Scaladoc 工具,分别应仅包含 scala-compiler
库及其依赖项。
如果未设置 scala
扩展的 scalaVersion
属性,并且未显式配置任务的 scalaClasspath
,则 Scala(基本)插件将尝试从任务的 classpath
推断类路径。这样做的方法如下
-
如果在
classpath
上找到scala-library
jar,并且项目至少声明了一个仓库,则会将相应的scala-compiler
仓库依赖项添加到scalaClasspath
。 -
否则,任务的执行将失败,并显示一条消息,指出无法推断
scalaClasspath
。
配置 Zinc 编译器
Scala 插件使用名为 zinc
的配置来解析 Zinc 编译器 及其依赖项。Gradle 将提供 Zinc 的默认版本,但如果您需要使用特定的 Zinc 版本,则可以更改它。Gradle 支持 1.6.0 及更高版本的 Zinc。
scala {
scalaVersion = "2.13.12"
zincVersion = "1.10.4"
}
scala {
scalaVersion = "2.13.12"
zincVersion = "1.10.4"
}
Zinc 编译器本身需要与您的应用程序所需的版本兼容的 scala-library
版本。Gradle 会负责为您指定兼容的 scala-library
版本。
您可以通过为 zinc
配置运行 dependencyInsight 来诊断所选 Zinc 编译器版本的问题。
Gradle 版本 | 支持的 Zinc 版本 | Zinc 坐标 | 所需的 Scala 版本 | 支持的 Scala 编译版本 |
---|---|---|---|---|
7.5 及更高版本 |
SBT Zinc。版本 1.6.0 及更高版本。 |
|
运行 Zinc 需要 Scala |
可以编译 Scala |
6.0 到 7.5 |
SBT Zinc。版本 1.2.0 及更高版本。 |
|
运行 Zinc 需要 Scala |
可以编译 Scala |
1.x 到 5.x |
已弃用 Typesafe Zinc 编译器。 版本 0.3.0 及更高版本,但 0.3.2 到 0.3.5.2 除外。 |
|
运行 Zinc 需要 Scala |
可以编译 Scala |
向 Scala 编译器添加插件
Scala 插件添加了一个名为 scalaCompilerPlugins
的配置,用于声明和解析可选的编译器插件。
dependencies {
scalaCompilerPlugins("org.typelevel:kind-projector_2.13.12:0.13.2")
}
dependencies {
scalaCompilerPlugins("org.typelevel:kind-projector_2.13.12:0.13.2")
}
约定属性
Scala 插件没有向项目添加任何约定属性。
源集属性
Scala 插件向项目中的每个源集添加以下扩展。您可以在构建脚本中使用它们,就像它们是源集对象的属性一样。
scala
— SourceDirectorySet (只读)-
此源集的 Scala 源文件。包含在 Scala 源目录中找到的所有
.scala
和.java
文件,并排除所有其他类型的文件。默认值:非空。 scala.srcDirs
—Set<File>
-
包含此源集的 Scala 源文件的源目录。也可能包含用于联合编译的 Java 源文件。可以使用理解隐式转换为文件集合中描述的任何内容进行设置。默认值:
[projectDir/src/name/scala]
。 allScala
— FileTree (只读)-
此源集的所有 Scala 源文件。仅包含在 Scala 源目录中找到的
.scala
文件。默认值:非空。
这些扩展由 ScalaSourceSet 类型的对象支持。
Scala 插件还修改了一些源集属性
属性名称 | 更改 |
---|---|
|
添加在 Scala 源目录中找到的所有 |
|
添加在 Scala 源目录中找到的所有源文件。 |
目标字节码级别和 Java API 版本
运行 Scala 编译任务时,Gradle 始终会添加一个参数来配置 Scala 编译器的 Java 目标,该目标派生自 Gradle 配置
-
当使用工具链时,将选择
-release
选项,或者对于较旧的 Scala 版本,将选择target
,其版本与配置的工具链的 Java 语言级别匹配。 -
当不使用工具链时,Gradle 将始终传递一个
target
标志 - 确切值取决于 Scala 版本 - 以编译为 Java 8 字节码。
这意味着将工具链与最新的 Java 版本和旧版本的 Scala 版本一起使用可能会导致失败,因为 Scala 在一段时间内仅支持 Java 8 字节码。解决方案是在工具链中使用正确的 Java 版本,或在需要时显式降级目标。 |
下表解释了 Gradle 计算的值
Scala 版本 | 正在使用的工具链 | 参数值 |
---|---|---|
版本 < |
是 |
|
否 |
|
|
|
是 |
|
否 |
|
|
|
是 |
|
否 |
|
|
|
是 |
|
否 |
|
在 ScalaCompile.scalaCompileOptions.additionalParameters
上显式设置任何这些标志,或使用包含 java-output-version
的标志,会禁用该逻辑,而支持显式标志。
在外部进程中编译
Scala 编译在外部进程中进行。
外部进程的内存设置默认为 JVM 的默认值。要调整内存设置,请根据需要配置 scalaCompileOptions.forkOptions
属性
tasks.withType<ScalaCompile>().configureEach {
scalaCompileOptions.forkOptions.apply {
memoryMaximumSize = "1g"
jvmArgs = listOf("-XX:MaxMetaspaceSize=512m")
}
}
tasks.withType(ScalaCompile) {
scalaCompileOptions.forkOptions.with {
memoryMaximumSize = '1g'
jvmArgs = ['-XX:MaxMetaspaceSize=512m']
}
}
增量编译
通过仅编译自上次编译以来源代码已更改的类以及受这些更改影响的类,增量编译可以显着减少 Scala 编译时间。当频繁编译小代码增量时,它特别有效,这在开发时经常完成。
tasks.withType<ScalaCompile>().configureEach {
scalaCompileOptions.apply {
isForce = true
}
}
tasks.withType(ScalaCompile) {
scalaCompileOptions.with {
force = true
}
}
注意: 仅当至少一个输入源文件已更改时,才会导致重新编译所有类。如果源文件没有更改,则 compileScala
任务仍将像往常一样被视为 UP-TO-DATE
。
基于 Zinc 的 Scala 编译器支持 Java 和 Scala 代码的联合编译。默认情况下,src/main/scala
下的所有 Java 和 Scala 代码都将参与联合编译。即使 Java 代码也将以增量方式编译。
增量编译需要对源代码进行依赖性分析。此分析的结果存储在 scalaCompileOptions.incrementalOptions.analysisFile
指定的文件中(该文件具有合理的默认值)。在多项目构建中,分析文件会传递到下游 ScalaCompile
任务,以实现跨项目边界的增量编译。对于 Scala 插件添加的 ScalaCompile
任务,无需任何配置即可使其工作。对于您可能添加的其他 ScalaCompile
任务,需要配置属性 scalaCompileOptions.incrementalOptions.publishedCode
以指向代码传递到下游 ScalaCompile
任务的类文件夹或 Jar 存档。请注意,如果 publishedCode
未正确设置,则下游任务可能不会重新编译受上游更改影响的代码,从而导致不正确的编译结果。
请注意,不支持 Zinc 基于 Nailgun 的守护程序模式。相反,我们计划增强 Gradle 自己的编译器守护程序,使其在 Gradle 调用之间保持活动状态,从而重用相同的 Scala 编译器。预计这将为 Scala 编译带来另一个显着的加速。
Eclipse 集成
当 Eclipse 插件遇到 Scala 项目时,它会添加额外的配置,使项目可以开箱即用地与 Scala IDE 一起使用。具体来说,该插件添加了一个 Scala nature 和依赖项容器。
IntelliJ IDEA 集成
当 IDEA 插件遇到 Scala 项目时,它会添加额外的配置,使项目可以开箱即用地与 IDEA 一起使用。具体来说,该插件添加了一个 Scala SDK(IntelliJ IDEA 14+)和一个与项目类路径上的 Scala 版本匹配的 Scala 编译器库。Scala 插件向后兼容早期版本的 IntelliJ IDEA,并且可以通过在 IdeaModel 上配置 targetVersion
来添加 Scala facet 而不是默认的 Scala SDK。
idea {
targetVersion = "13"
}
idea {
targetVersion = '13'
}