Gradle Scala 插件

2022-08-03 15:31 更新

Scala 的插件繼承自 Java 插件并添加了對 Scala 項(xiàng)目的支持。它可以處理 Scala 代碼,以及混合的 Scala 和 Java 代碼,甚至是純 Java 代碼(盡管我們不一定推薦使用)。該插件支持聯(lián)合編譯,聯(lián)合編譯可以通過 Scala 及 Java 的各自的依賴任意地混合及匹配它們的代碼。例如,一個 Scala 類可以繼承自一個 Java 類,而這個 Java 類也可以繼承自一個 Scala 類。這樣一來,我們就能夠在項(xiàng)目中使用最適合的語言,并且在有需要的情況下用其他的語言重寫其中的任何類。

用法

要使用 Scala 插件,請?jiān)跇?gòu)建腳本中包含以下語句:

使用 Scala 插件

build.gradle

apply plugin: 'scala'  

任務(wù)

Scala 的插件向 project 中添加了以下任務(wù)。

表 25.1. Scala 插件 - 任務(wù)

任務(wù)名稱 依賴于 類型 描述
compileScala compileJava ScalaCompile 編譯production 的 Scala 源文件。
compileTestScala compileTestJava ScalaCompile 編譯test 的 Scala 的源文件。
SourceSetScala SourceSetJava ScalaCompile 編譯給定的source set 里的 Scala 源文件。
scaladoc - scaladoc 為production 里的 Scala 源文件生成 API 文檔。

Scala 插件向 Java 插件所加入的 tasks 添加了以下的依賴。

表 24.2. Scala 感覺 插件 - 額外的 task 依賴

任務(wù)名稱 依賴于
classes compileScala
testClasses compileTestScala
sourceSetClasses SourceSetScala

圖 25.1. Scala 插件-任務(wù)

項(xiàng)目布局

Scala 插件會假定如下所示的項(xiàng)目布局。所有 Scala 的源目錄都可以包含 Scala和Java 代碼。Java 源目錄只能包含 Java 源代碼。這些目錄不一定是存在的,或是里面包含有什么內(nèi)容;Scala 插件只會進(jìn)行編譯,而不管它發(fā)現(xiàn)什么。

表 25.3. Scala 插件 - 項(xiàng)目布局

目錄 意義
src/main/java 產(chǎn)品的Java源代碼
src/main/resources 產(chǎn)品的資源
src/main/scala Production Scala 源代碼。此外可能包含聯(lián)合編譯的 Java 源代碼。
src/test/java Java 測試源代碼
src/test/resources 測試資源
src/test/scala Test Scala 源代碼。此外可能包含聯(lián)合編譯的 Java 源代碼。
sourceSet/java 給定的源集的Java源代碼
sourceSet/resources 給定的源集的資源
sourceSet/scala 給定的source set 的 Scala 源代碼。此外可能包含聯(lián)合編譯的 Java 源代碼。

更改項(xiàng)目布局

和 Java 插件一樣,Scala 插件允許把 Scala 的 production 和 test 的源文件配置為自定義的位置。

自定義 Scala 源文件布局

build.gradle

sourceSets {
    main {
        scala
            srcDirs = ['src/scala']
        }
    }
    test {
        scala
            srcDirs = ['test/scala']
        }
    }
}  

依賴管理

Scala 項(xiàng)目需要聲明一個 scala-library 依賴項(xiàng)。這個依賴會在編譯和運(yùn)行的類路徑時用到。它還將用于分別獲取 Scala 編譯器及 Scaladoc 工具。

如果 Scala 用于 production 代碼, scala-library 依賴應(yīng)該添加到 compile 的配置中:

為production 代碼定義一個Scala 依賴

build.gradle

repositories {
    mavenCentral()
}
dependencies {
    compile 'org.scala-lang:scala-library:2.9.1'
}  

如果 Scala 僅用于測試代碼, scala-library 依賴應(yīng)被添加到 testCompile 配置中:

為 test 代碼定義一個Scala 依賴

build.gradle

dependencies {
    testCompile "org.scala-lang:scala-library:2.9.2"
}  

scalaClasspath 的自動配置

ScalaCompile 和 ScalaDoc tasks 會以兩種方式使用 Scala: 在它們的 classpath 以及scalaClasspath 上。前者用于在源代碼中查找類的引用,通常會包含 scala-library 和其他庫。后者用來分別加載和執(zhí)行 Scala 編譯器和 Scala 工具,并且應(yīng)該只包含 scala-library及其依賴項(xiàng)。

除非顯式配置了一個 task 的 scalaClasspath ,否則 Scala(基礎(chǔ))插件會嘗試推斷該 task 的 classpath。以如下方式進(jìn)行:

  • 如果在 classpath 中找到 scala-library Jar ,并且該項(xiàng)目已經(jīng)在至少一個倉庫中聲明了它,那么相應(yīng)的 scala-compiler 的倉庫依賴將添加到 scalaClasspath中。
  • 其他情況,該 task 將執(zhí)行失敗,并提示無法推斷 scalaClasspath。

公約屬性

Scala 插件沒有向 project 添加任何的公約屬性。

source set 屬性

Scala 的插件向 project 的每一個 source set 添加了下列的公約屬性。你可以在你的構(gòu)建腳本中,把這些屬性當(dāng)成是 source set 對象中的屬性一樣使用。

表 25.4. Scala 插件 - source set 屬性

屬性名稱 類型 默認(rèn)值 描述
scala SourceDirectorySet (read-only) 非空 該source set 中的 Scala 源文件。包含在 Scala 源目錄中找到的所有的.java文件,并排除所有其他類型的文件。
scala.srcDirs Set<File>. name/scala] 源目錄包含該 source set 中的 Scala 源文件。此外可能還包含用于聯(lián)合編譯的 Java 源文件。
allScala FileTree (read-only) 非空 該source set 中的所有 Scala 源文件。包含在 Scala 源目錄中找到的所有的.scala文件。

這些屬性由一個 ScalaSourceSet 的約定對象提供。

Scala 的插件還修改了一些 source set 的屬性:

表 25.5. Scala 插件 - source set 屬性

屬性名稱 修改的內(nèi)容
allJava 添加在 Scala 源目錄中找到的所有.java文件。
allSource 添加在 Scala 的源目錄中找到的所有源文件。

Fast Scala Compiler

Scala 插件包含了對 fsc,即 Fast Scala Compiler 的支持。fsc 運(yùn)行在一個單獨(dú)的進(jìn)程中,并且可以顯著地提高編譯速度。

啟用 Fast Scala Compiler

build.gradle

compileScala
    scalaCompileOptions.useCompileDaemon = true
    // optionally specify host and port of the daemon:
    scalaCompileOptions.daemonServer = "localhost:4243"
}  

注意,每當(dāng) fsc 的編譯類路徑的內(nèi)容發(fā)生變化時,它都需要重新啟動。(它本身不會去檢測編譯類路徑的更改。)這使得它不太適合于多項(xiàng)目的構(gòu)建。

在外部進(jìn)程中編譯

當(dāng) scalaCompileOptions.fork 設(shè)置為 true 時,編譯會在外部進(jìn)程中進(jìn)行。fork 的詳細(xì)情況依賴于所使用的編譯器。基于 Ant 的編譯器 (scalaCompileOptions.useAnt = true) 將為每個 ScalaCompile 任務(wù) fork 一個新進(jìn)程,而默認(rèn)情況下它不進(jìn)行 fork?;?Zinc 的編譯器 (scalaCompileOptions.useAnt = false) 將利用 Gradle 編譯器守護(hù)進(jìn)程,且默認(rèn)情況下也是這樣。

外部過程默認(rèn)使用JVM 的的默認(rèn)內(nèi)存設(shè)置。如果要調(diào)整內(nèi)存設(shè)置,請根據(jù)需要配置scalaCompileOptions.forkOptions :

調(diào)整內(nèi)存設(shè)置

build.gradle

tasks.withType(ScalaCompile) {
    configure(scalaCompileOptions.forkOptions) {
        memoryMaximumSize = '1g'
        jvmArgs = ['-XX:MaxPermSize=512m']
    }
}  

增量編譯

增量編譯是只編譯那些源代碼在上一次編譯之后有修改的類,及那些受這些修改影響到的類,它可以大大減少 Scala 的編譯時間。頻繁編譯代碼的增量部分是非常有用的,因?yàn)樵陂_發(fā)時我們經(jīng)常要這樣做。

Scala 插件現(xiàn)在通過集成 Zinc 來支持增量編譯, 它是 sbt 增量 Scala 編譯器的一個單機(jī)版本。若要把 ScalaCompile 任務(wù)從默認(rèn)的基于 Ant 的編譯器切換為新的基于 Zinc 的編譯器,需要將 scalaCompileOptions.useAnt 設(shè)置為 false:

激活基于 Zinc 編譯器

build.gradlev

tasks.withType(ScalaCompile) {
    scalaCompileOptions.useAnt = false
}  

除非在 API 文檔中另有說明,否則基于 Zinc 的據(jù)編譯器支持與基于 Ant 的編譯器完全相同的配置選項(xiàng)。但是,要注意的是,Zinc 編譯器需要 Java 6 或其以上版本來運(yùn)行。這意味著 Gradle 本身要使用 Java 6 或其以上版本。

Scala 插件添加了一個名為 zinc 的配置,以解析 Zinc 庫及其依賴。如果要重寫 Gradle 默認(rèn)情況下使用的 Zinc 版本,請?zhí)砑右粋€顯式的 Zinc 依賴項(xiàng) (例如zinc "com.typesafe.zinc:zinc:0.1.4")。無論使用哪一個 Zinc 版本,Zinc 都是使用在scalaTools配置上找到的 Scala 編譯器。

就像 Gradle 上基于Ant 的編譯器一樣,基于 Zinc 的編譯器支持 Java 和 Scala 代碼的聯(lián)合編譯。默認(rèn)情況下,在 src/main/scala 下的所有 Java 和 Scala 代碼都會進(jìn)行聯(lián)合編譯。使用基于 Zinc 的編譯器時,即使是 Java 代碼也將會進(jìn)行增量編譯。

增量編譯需要源代碼的相關(guān)性分析。解析結(jié)果進(jìn)入由 scalaCompileOptions.incrementalOptions.analysisFile 所指定的文件(它有一個合理的默認(rèn)值)。在多項(xiàng)目構(gòu)建中,分析文件被傳遞給下游的 ScalaCompile 任務(wù),以啟用跨項(xiàng)目的增量編譯。對于由 Scala 插件添加的 ScalaCompile 任務(wù),無需對這一點(diǎn)進(jìn)行配置。對于其他的 ScalaCompile 任務(wù),需要根據(jù)類文件夾或 Jar archive 的代碼中,是哪一個的代碼被傳遞給 ScalaCompile 任務(wù)的下游類路徑,把ScalaCompileOptions.incrementalOptions.publishedCode 配置為指向它們。注意,如果publishedCode 設(shè)置不正確,上游代碼發(fā)生變化時下游任務(wù)可能不會重新編譯代碼,導(dǎo)致編譯結(jié)果不正確。

由于依賴分析的系統(tǒng)開銷,一次干凈的編譯或在代碼有了較大的更改之后的編譯,可能花費(fèi)的時間要長于使用基于 Ant 的編譯器。對于 CI 構(gòu)建和版本的構(gòu)建中,我們目前推薦使用基于 Ant 的編譯器。

注意現(xiàn)在 Zinc 基于守護(hù)進(jìn)程模式的 Nailgun 還不支持。相反,我們打算加強(qiáng) Gradle 自己的編譯器守護(hù)進(jìn)程,使得在跨 Gradle 調(diào)用時繼續(xù)存活,利用同一個 Scala 編譯器。這將會為 Scala 編譯帶來另一個方面上的明顯加速。

eclipse 集成

當(dāng) Eclipse 插件遇到 Scala 項(xiàng)目時,它將添加額外的配置,使得項(xiàng)目能夠在使用 Scala IDE 時開箱即用。具體而言,該插件添加一個 Scala 性質(zhì)和依賴的容器。

IntelliJ 集成

當(dāng) IDEA 插件遇到 Scala 項(xiàng)目時,它將添加額外的配置,使得項(xiàng)目能夠在使用 IDEA 時開箱即用。具體而言,該插件添加了一個 Scala facet 和一個匹配項(xiàng)目的類路徑上的 Scala 版本的 Scala 編譯器類庫。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號