.sbt vs .scala
这里只讨论.sbt。
所谓构建定义
name := "hello"
这个Setting[String]将映射中的name键与"hello"关联(添加或替换)。将转换后的映射作为新的sbt映射。
总结:构建定义定义了一个Setting[T]列表,Setting[T]是会影响sbt映射键值对的转换,T是值得类型。
build.sbt如何定义settings
name := "hello"
version := "1.0"
scalaVersion := "2.9.2"
build.sbt中的表达式都是相互独立的,而且他们是表达式而不是完整的scala语句。在build.sbt中不能定义顶级的val,object,class和方法。
name.:=("hello")
scala name := 42 // will not compile ### Settings are separated by blank lines
// 没有空行,无法工作
name := "hello"
version := "1.0"
scalaVersion := "2.9.2"
sbt需要某种定界符来表明表达式在哪结束,下一个在哪开始。
.sbt文件包含一个Scala表达式列表,它不是完整的Scala程序,这些表达式必须先切分,然后逐个传给编译器。
如果想要一个完整的Scala程序,用.scala文件;.sbt文件是可选的。
键在Keys对象中定义
自定义键可以在.scala文件或插件中定义。
改变settings的另一个方式
:=是最简单的转换。还有其他方式。例如可以用+=向一个列表值添加内容。
其他的转换需要scopes的知识,所以后面再介绍。
任务键
有三种风味的键:(红烧,清蒸,还有油炸的)
InputKey[T]:是一个有命令行参数作为输入的任务键。入门指南中未涵盖InputKey。
TaskKey[T]定义一个任务,像compile或package这样的操作就是任务。任务可以返回Unit(就是Scala中的void),或返回一个和任务相关联的值,如package是一个TaskKey[File],它的值就是他创建的jar文件。
每次开始执行一个任务(比如在交互式sbt提示符后输入compile),sbt都会重新运行一次涉及到的任务。
虽然sbt的映射描述一个项目时,可以为诸如name的setting保持一个固定的字符串,但是它必须为诸如compile这样的任务保持可执行的代码——即使可执行代码最终返回一个字符串,它每次都会重新运行。
一个给定的键必须引用一个任务或普通的setting。也就是说,"taskiness"(是否每次重新运行)是这个键的属性,而不是值。
hello := {println("Hello!")}
从类型系统的观点来看,task key创建的Setting与setting key创建的Setting稍有不同,taskKey := 42返回一个Setting[Task[T]],而settingKey := 42返回一个Setting[T]。在大多数情况下这没多大差别,当任务执行的时候task key依然创建一个类型为T的值。(也就是说,当T是String,那么无论是调用task key,还是setting key,返回的值都是String类型的)
T和Task[T]隐含的区别是:一个setting key不能依赖一个task key,因为setting key的值只在项目加载的时候评估一次,而且不能重复执行。
sbt交互模式下的Keys
在sbt交互模式下,可以输入任务的名称来执行这个任务。因此输入compile就会运行compile任务,compile是一个task key。
如果输入一个setting key的名称,就会显示setting key的值。输入task key的名称会执行任务但不会显示结果值;要看任务的结果,可以用show <task name>。
在构建定义文件中,keys以驼峰式命名(沿袭Scala惯例),但在sbt命令行中用 连字符-分隔-单词 代替。这些在sbt中使用的 连字符-分隔 字符串是在Keys中定义的。例如,在Keys.scala,定义了一个键:
val scalacOptions = TaskKey[Seq[String]]("scalac-options", "Options for the Scala compiler.")
在sbt中要输入scalac-options,但在构建定义中得用scalacOptions。
要了解更多的键,在sbt命令提示符后输入inspect <keyname>。inspect显示的有些信息没什么意义,但是在顶端展示了setting的值类型,以及它的简短描述。
在build.sbt中引入
import sbt._
import Process._
import Keys._
(此外,如有你有.scala文件,它们的内容(Build或Plugin对象)将会被导入。)
添加类库依赖
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3"
libraryDependencies涉及两个复杂情况:+=操作符,以及%方法。+=向原来的值中追加,而非替换它。%方法用来从字符串构造ivy模块ID。