Scala 外掛程式擴充 Java 外掛程式,以新增對 Scala 專案的支援。此外掛程式也支援聯合編譯,讓您可以自由混合和搭配 Scala 和 Java 程式碼,並在兩者之間建立相依性。例如,Scala 類別可以延伸 Java 類別,而 Java 類別又可以延伸 Scala 類別。這讓您可以使用最適合此工作的語言,並在需要時以其他語言改寫任何類別。

請注意,如果您想要受益於 API/實作分離,您也可以將 java-library 外掛程式套用至您的 Scala 專案。

使用方式

若要使用 Scala 外掛程式,請在您的建置指令碼中包含下列內容

build.gradle.kts
plugins {
    scala
}
build.gradle
plugins {
    id 'scala'
}

任務

Scala 外掛程式會將下列任務加入專案。有關變更 Java 編譯任務相依性的資訊請見此處

compileScalaScalaCompile

相依於compileJava

編譯生產用 Scala 原始檔。

compileTestScalaScalaCompile

相依於compileTestJava

編譯測試用 Scala 原始檔。

compileSourceSetScalaScalaCompile

相依於compileSourceSetJava

編譯指定原始檔組的 Scala 原始檔。

scaladocScalaDoc

為生產用 Scala 原始檔產生 API 文件。

ScalaCompileScalaDoc 任務支援現成的Java 工具鏈

Scala 外掛程式會將下列相依性加入 Java 外掛程式所加入的任務。

表 1. Scala 外掛程式 - 其他任務相依性
任務名稱 相依於

classes

compileScala

testClasses

compileTestScala

sourceSetClasses

compileSourceSetScala

scalaPluginTasks
圖 1. Scala 外掛程式 - 任務

專案配置

Scala 外掛程式假設專案配置如下所示。所有 Scala 原始檔目錄都可以包含 Scala Java 程式碼。Java 原始檔目錄只能包含 Java 原始檔程式碼。這些目錄都不需要存在或包含任何內容;Scala 外掛程式只會編譯它找到的內容。

src/main/java

生產用 Java 原始檔。

src/main/resources

生產用資源,例如 XML 和屬性檔。

src/main/scala

生產用 Scala 原始檔。也可以包含 Java 原始檔,以進行聯合編譯。

src/test/java

測試用 Java 原始檔。

src/test/resources

測試用資源。

src/test/scala

測試用 Scala 原始檔。也可以包含 Java 原始檔,以進行聯合編譯。

src/sourceSet/java

名為 sourceSet 的 source set 的 Java 原始碼。

src/sourceSet/resources

名為 sourceSet 的 source set 的資源。

src/sourceSet/scala

給定 source set 的 Scala 原始碼檔案。也可以包含用於聯合編譯的 Java 原始碼檔案。

變更專案配置

就像 Java 外掛程式一樣,Scala 外掛程式允許您設定 Scala 產生和測試原始碼檔案的客製化位置。

build.gradle.kts
sourceSets {
    main {
        scala {
            setSrcDirs(listOf("src/scala"))
        }
    }
    test {
        scala {
            setSrcDirs(listOf("test/scala"))
        }
    }
}
build.gradle
sourceSets {
    main {
        scala {
            srcDirs = ['src/scala']
        }
    }
    test {
        scala {
            srcDirs = ['test/scala']
        }
    }
}

相依性管理

Scala 專案需要宣告 scala-library 相依性。這個相依性會用於編譯和執行時期類別路徑。它也會用於分別取得 Scala 編譯器和 Scaladoc 工具。[1]

如果 Scala 用於產生程式碼,則應將 scala-library 相依性新增至 implementation 設定

build.gradle.kts
repositories {
    mavenCentral()
}

dependencies {
    implementation("org.scala-lang:scala-library:2.13.12")
    testImplementation("junit:junit:4.13")
}
build.gradle
repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.scala-lang:scala-library:2.13.12'
    testImplementation 'junit:junit:4.13'
}

如果您想使用 Scala 3 而不是 scala-library 相依性,則應新增 scala3-library_3 相依性

build.gradle.kts
plugins {
    scala
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.scala-lang:scala3-library_3:3.0.1")
    testImplementation("org.scalatest:scalatest_3:3.2.9")
    testImplementation("junit:junit:4.13")
}

dependencies {
    implementation("commons-collections:commons-collections:3.2.2")
}
build.gradle
plugins {
    id 'scala'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.scala-lang:scala3-library_3:3.0.1'
    implementation 'commons-collections:commons-collections:3.2.2'
    testImplementation 'org.scalatest:scalatest_3:3.2.9'
    testImplementation 'junit:junit:4.13'
}

如果 Scala 僅用於測試程式碼,則應將 scala-library 相依性新增至 testImplementation 設定

build.gradle.kts
dependencies {
    testImplementation("org.scala-lang:scala-library:2.13.12")
}
build.gradle
dependencies {
    testImplementation 'org.scala-lang:scala-library:2.13.12'
}

scalaClasspath 的自動設定

ScalaCompileScalaDoc 任務以兩種方式使用 Scala 程式碼:在它們的 classpath 上,以及在它們的 scalaClasspath 上。前者用於尋找原始碼引用的類別,通常會包含 scala-library 和其他函式庫。後者分別用於載入和執行 Scala 編譯器和 Scaladoc 工具,並且應該只包含 scala-compiler 函式庫及其相依性。

除非任務的 scalaClasspath 已明確設定,否則 Scala (基本) 外掛程式會嘗試從任務的 classpath 推斷它。這會以下列方式進行

  • 如果在 classpath 上找到 scala-library jar,且專案已宣告至少一個儲存庫,則會將對應的 scala-compiler 儲存庫相依性新增至 scalaClasspath

  • 否則,任務的執行會失敗,並顯示一則訊息,指出無法推斷 scalaClasspath

設定 Zinc 編譯器

Scala 外掛程式使用名為 zinc 的組態來解析 Zinc 編譯器 及其相依性。Gradle 會提供 Zinc 的預設版本,但如果您需要使用特定 Zinc 版本,您可以變更它。Gradle 支援 Zinc 1.6.0 以上的版本。

build.gradle.kts
scala {
    zincVersion = "1.9.3"
}
build.gradle
scala {
    zincVersion = "1.9.3"
}

Zinc 編譯器本身需要相容的 scala-library 版本,可能與您的應用程式所需的版本不同。Gradle 會為您指定相容的 scala-library 版本。

您可以執行 zinc 組態的 dependencyInsight 來診斷 Zinc 編譯器所選版本的問題。

表格 2. Zinc 相容性表格
Gradle 版本 支援的 Zinc 版本 Zinc 座標 所需的 Scala 版本 支援的 Scala 編譯版本

7.5 及更新版本

SBT Zinc。1.6.0 以上的版本。

org.scala-sbt:zinc_2.13

執行 Zinc 需要 Scala 2.13.x

可以編譯 Scala 2.10.x3.x

6.0 至 7.5

SBT Zinc。1.2.0 以上的版本。

org.scala-sbt:zinc_2.12

執行 Zinc 需要 Scala 2.12.x

可以編譯 Scala 2.10.x2.13.x

1.x 至 5.x

已棄用 Typesafe Zinc 編譯器。 0.3.0 以上的版本,但 0.3.2 至 0.3.5.2 除外。

com.typesafe.zinc:zinc

執行 Zinc 需要 Scala 2.10.x

可以編譯 Scala 2.9.x2.12.x

將外掛程式新增至 Scala 編譯器

Scala 外掛程式會新增名為 scalaCompilerPlugins 的組態,用於宣告和解析選用的編譯器外掛程式。

build.gradle.kts
dependencies {
    implementation("org.scala-lang:scala-library:2.13.12")
    scalaCompilerPlugins("org.typelevel:kind-projector_2.13.12:0.13.2")
}
build.gradle
dependencies {
    implementation "org.scala-lang:scala-library:2.13.12"
    scalaCompilerPlugins "org.typelevel:kind-projector_2.13.12:0.13.2"
}

慣例屬性

Scala 外掛程式不會將任何慣例屬性新增至專案。

Source set properties

Scala 外掛會將以下擴充套件新增到專案中的每個來源組。您可以在建置指令碼中使用這些擴充套件,就像它們是來源組物件的屬性一樣。

scalaSourceDirectorySet(唯讀)

這個來源組的 Scala 來源檔案。包含在 Scala 來源目錄中找到的所有 .scala.java 檔案,並排除所有其他類型的檔案。預設值:非 Null。

scala.srcDirsSet<File>

包含這個來源組的 Scala 來源檔案的來源目錄。也可以包含 Java 來源檔案以進行聯合編譯。可以使用 了解隱式轉換為檔案集合 中所述的任何內容來設定。預設值: [projectDir/src/name/scala]

allScalaFileTree(唯讀)

這個來源組的所有 Scala 來源檔案。僅包含在 Scala 來源目錄中找到的 .scala 檔案。預設值:非 Null。

這些擴充套件由 ScalaSourceSet 類型的物件支援。

Scala 外掛也會修改一些來源組屬性

表 3. Scala 外掛 - 來源組屬性
屬性名稱 變更

allJava

新增在 Scala 來源目錄中找到的所有 .java 檔案。

allSource

新增在 Scala 來源目錄中找到的所有來源檔案。

目標位元組碼層級和 Java API 版本

在執行 Scala 編譯工作時,Gradle 會總是新增一個參數,以根據 Gradle 組態設定 Scala 編譯器的 Java 目標,

  • 在使用工具鏈時,會選取 -release 選項或較舊 Scala 版本的 target,其版本與所組態工具鏈的 Java 語言層級相符。

  • 在不使用工具鏈時,Gradle 會總是傳遞一個 target 旗標(其確切值取決於 Scala 版本)以編譯為 Java 8 位元組碼。

這表示使用具有較新 Java 版本和舊 Scala 版本的工具鏈可能會導致失敗,因為 Scala 一段時間內僅支援 Java 8 位元組碼。因此,解決方案是使用工具鏈中的正確 Java 版本,或在需要時明確降低目標。

下表說明 Gradle 計算的值

表 4. 基於專案組態的 Scala 目標參數
Scala 版本 使用的工具鏈 參數值

版本 < 2.13.1

-target:jvm-1.<java_version>

-target:jvm-1.8

2.13.1 <= 版本 < 2.13.9

-target:<java_version>

-target:8

2.13.9 <= 版本 < 3.0

-release:<java_version>

-target:8

3.0 <= 版本

-release:<java_version>

-Xtarget:8

ScalaCompile.scalaCompileOptions.additionalParameters 上明確設定這些旗標中的任何一個,或使用包含 java-output-version 的旗標,會停用該邏輯,而使用明確的旗標。

在外部程序中編譯

Scala 編譯會在外部程序中進行。

外部程序的記憶體設定預設為 JVM 的預設值。如要調整記憶體設定,請視需要設定 scalaCompileOptions.forkOptions 屬性

build.gradle.kts
tasks.withType<ScalaCompile>().configureEach {
    scalaCompileOptions.forkOptions.apply {
        memoryMaximumSize = "1g"
        jvmArgs = listOf("-XX:MaxMetaspaceSize=512m")
    }
}
build.gradle
tasks.withType(ScalaCompile) {
    scalaCompileOptions.forkOptions.with {
        memoryMaximumSize = '1g'
        jvmArgs = ['-XX:MaxMetaspaceSize=512m']
    }
}

增量編譯

透過只編譯自上次編譯後原始碼已變更的類別,以及受這些變更影響的類別,增量編譯可以大幅縮短 Scala 編譯時間。當頻繁編譯小型的程式碼增量時,特別有效,例如在開發階段時。

Scala 外掛程式預設透過與 Zinc 整合來進行增量編譯,這是 sbt 的增量 Scala 編譯器的獨立版本。如果您要停用增量編譯,請在您的建置檔案中設定 force = true

build.gradle.kts
tasks.withType<ScalaCompile>().configureEach {
    scalaCompileOptions.apply {
        isForce = true
    }
}
build.gradle
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 特性及相依性容器。

IntelliJ IDEA 整合

當 IDEA 外掛程式遇到 Scala 專案時,它會新增其他設定,讓專案開箱即用地與 IDEA 搭配使用。具體來說,外掛程式會新增 Scala SDK(IntelliJ IDEA 14+)和與專案類別路徑上的 Scala 版本相符的 Scala 編譯器程式庫。Scala 外掛程式向下相容於早期版本的 IntelliJ IDEA,而且可以透過在 IdeaModel 上設定 targetVersion 來新增 Scala 方面,而不是預設的 Scala SDK。

build.gradle.kts
idea {
    targetVersion = "13"
}
build.gradle
idea {
    targetVersion = '13'
}