【译】Gradle 4.3.1 用户指南——57. Scala插件

Gradle的Scala插件扩展了Java插件,增加了对Scala工程的支持。可以处理纯Scala代码,Scala和Java代码,甚至纯java代码(并不推荐这种使用方式)。此插件支持联合编译,允许开发者自由的混编Scala和Java,并支持两者的依赖管理。例如:一个Scala类可以扩展一个Java类,而这个Java类本身也扩展自另一个Scala类。这使得开发者在工作中可以自由选择更合适的语言,也可以任意重写其他语言的类。

1. 使用

使用Scala插件需要在build脚本中增加下面这行:

apply plugin: 'scala'

2. 任务

Scala插件会给工程添加下面的任务

名称依赖类型描述
compileScalacompileJavaScalaCompile编译Scala生产源码
compileTestScalacompileTestJavaScalaCompile编译Scala测试源码
compileSourceSetScalacompileSourceSetJavaScalaCompile编译指定Scala源码
scaladoc-ScalaDoc为Scala生产源码生成API文档

同时Scala插件将向Java插件的任务中添加如下依赖:

名称依赖
classescompileScala
testClassescompileTestScala
sourceSetClassescompileSourceSetScala

3. 项目布局

Scala插件的假定项目布局如下。其中所有Scala代码目录都可以包含Scala和Java代码。但Java代码目录只能含有Java源码。这些目录并不必须存在,也不需要包含任何内容;Scala插件会自动编译它自己能找到的东西。

目录含义
src/main/javaJava 生产代码
src/main/resources生产资源文件
src/test/javaJava 测试代码
src/test/resources测试资源文件
src/test/scalaScala测试资源文件。同时允许包含Java资源
src/sourceSet/java指定source set专用的Java资源文件
src/sourceSet/resources指定source set专用的资源文件
src/sourceSet/Scala指定source set专用的Scala资源文件,允许包含Java资源

3.1 修改项目布局

和Java插件一样,Scala插件也允许你自定义布局:

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

4. 依赖管理

Scala工程需要声明scala-library依赖项。它不仅用于编译期和运行期的class path,还用于获取Scala编译器和ScalaDoc工具。
如果Scala用于生产代码,那么scala-library依赖必须被加入到compile配置:

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.scala-lang:scala-library:2.11.8'
    testCompile 'org.scalatest:scalatest_2.11:3.0.0'
    testCompile 'junit:junit:4.12'
}

如果Scala仅用于测试代码,那么它需要被加入到testCompile配置:

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

5. scalaClasspath的自动配置

ScalaCompile和ScalaDoc任务会从两种途径来消费Scala代码:从它们的classpath及它们的scalaClasspath。前者用于定位由源代码引用的类,通常包含scala-library以及其他库。后者用于加载和执行Scala编译器和Scala工具,应该只包含Scalascala-compiler库及其依赖项。

除非明确地配置scalaClasspath,否则Scala插件将尝试从任务的classpath中推断它。具体如下:

  • 如果在classpath中找到了scala-library,而且工程至少含有一个仓库声明,那么scala-compiler仓库会被加入到scalaClasspath
  • 否则,执行任务时会失败,并提示无法推断scalaClasspath

6. 设置Zinc编译器

Scala插件使用 "zinc" 配置项来配置Zinc编译器及其依赖。gradle提供了Zinc的默认版本,如果需要指定特定版本,需要在配置中写明版本号,如 "com.typesafe.zinc:zinc:0.3.6"。gradle支持0.3.0及以上版本。但是由于Zinc编译器回退的原因,0.3.2到0.3.5.2之间的版本无法使用。

dependencies {
    zinc 'com.typesafe.zinc:zinc:0.3.9'
}

声明scala-library时需要格外小心它与Zinc编译器之间的兼容关系。一般来说gradle会为你添加一个兼容的scala-library,但是一个更大的依赖解析规则可能会强制导入一个不兼容的版本。
比如,使用 configurations.all 强制指定一个 scala-library 版本的同时也会修改Zinc compiler版本:

configurations.all {
    resolutionStrategy.force "org.scala-lang:scala-library:2.11.7"
}

当需要排查错误时,你可以通过运行 dependencyInsight 来检查Zinc编译器实际版本。

7. 约定属性

Scala插件不会给工程添加任何新的约定属性。(Java插件会添加好几个)

8. Source set 属性

Scala插件会向Source set添加下列属性。你可以在build脚本中使用这些属性,就像使用source set对象自身的属性一样。

属性名类型默认值描述
scala

SourceDirectorySet

(read-only)

Not null

本source set中Scala的代码文件。

包含Scala代码目录中的所有.scala和.java文件,过滤了所有其他文件类型

scala.srcDirsSet<File>[projectDir/src/name/scala]本source set中包含Scala代码文件的目录。也包括Java代码
allScala

FileTree

(read-only)

Not null

本source set中所有Scala代码文件。

只包含在Scala代码目录中找到的 .scala文件

这些约定的属性由类型为ScalaSourceSet的约定对象提供。
同时Scala插件也会修改一些已有的source set属性:

名称修改
allJava新加入了所有Scala代码目录中找到的.java文件
allSource新加入了所有Scala代码目录中的文件

9. 外部编译

Scala在一个外部的进程中编译。
外部进程的内存设置为JVM的默认值。可以通过修改 scalaCompileOptions.forkOptions 来根据需要调整内存:

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

10. 增量编译

增量编译指仅重新编译那些上次编译后改动的相关类,可以显著缩短编译时间。当项目开发阶段需要频繁的编译一些小的改动时,这项技术十分有用。
Scala插件默认集成Zinc(一个独立的sbt增量Scala编译器)来实现增量编译。(Zinc好像迁移到sbt下了, 老Zinc只维护,无新功能)。可以将force设置为true来禁用增量编译。

tasks.withType(ScalaCompile) {
    scalaCompileOptions.with {
        force = true
    }
}

注意:至少有一个代码文件改变后,全量编译才会起作用。如果没有任何代码改变,compileScala任务将视为UP-TO-DATE。
Zinc编译器支持Java和Scala的混编。默认情况下,src/main/scala 目录下的Java和Scala代码将被联合编译。Java的部分也是增量编译的。

增量编译依赖于对代码的相关性分析。这些分析结果将存放在由scalaCompileOptions.incrementalOptions.analysisFile 指定的文件中(有默认值)。在多项目的构建中,分析文件被传递给下游的ScalaCompile任务以支持跨项目的增量编译。对于Scala插件的ScalaCompile任务,此工作无需任何配置。但是对于其他由你自己添加的ScalaCompile任务,需要配置scalaCompileOptions.incrementalOptions.publishedCode 来指向此任务生成的class目录或者Jar文件,然后下游的ScalaCompile任务会通过此配置来编译增量。当 publishedCode 设置不正确时,上游修改代码时下游任务可能不会重新编译,从而引发编译错误。

注意:Zinc基于Nailgun的守护进程模式目前还不支持。因此我们计划增强gradle自身的编译器守护进程特性,使其跨Gradle的调用Scala编译器时保持存活。这将为Scala的编译速度带来显著提升。

11. Java6和Java7的编译及测试

Scala编译器会忽略Gradle的 targetCompatibility 及 sourceCompatibility 设置。在Scala2.11中,Scala编译器编译Java 6兼容的字节码。在Scala2.12中,Scala编译器编译Java 8兼容的字节码。如果项目中同时存在Java代码,可以按照Java插件相同的步骤来保证Java编译器的正确使用。

# in $HOME/.gradle/gradle.properties
java6Home=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
sourceCompatibility = 1.6

assert hasProperty('java6Home') : "Set the property 'java6Home' in your your gradle.properties pointing to a Java 6 installation"
def javaExecutablesPath = new File(java6Home, 'bin')
def javaExecutables = [:].withDefault { execName ->
    def executable = new File(javaExecutablesPath, execName)
    assert executable.exists() : "There is no ${execName} executable in ${javaExecutablesPath}"
    executable
}

tasks.withType(AbstractCompile) {
    options.with {
        fork = true
        forkOptions.javaHome = file(java6Home)
    }
}
tasks.withType(Test) {
    executable = javaExecutables.java
}
tasks.withType(JavaExec) {
    executable = javaExecutables.java
}
tasks.withType(Javadoc) {
    executable = javaExecutables.javadoc
}

12. Eclipse集成

Eclipse插件会为Scala工程添加额外的配置,以让工程与scala IDE一起正常工作。确切地说,插件会增加Scala特性及依赖容器。

13. IntelliJ IDEA集成

IDEA插件会为Scala工程添加额外的配置以让工程与IDEA一起正常工作。确切的说,插件添加了Scala SDK(IntelliJ IDEA 14+)及符合项目路径Scala版本的Scala编译器库。Scala插件向后兼容IntelliJ IDEA的早期版本,可以通过在IdeaModel上配置targetVersion添加Scala特性,替代默认的Scala SDK。

idea {
    targetVersion = "13"
}

 

转载于:https://my.oschina.net/landas/blog/1583897

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值