项目构建工具是项目开发中非常重要的一个部分,充分利用好它能够极大的提高项目开发的效率。在学习SCALA的过程中,我遇到了SBT(Simple Build Tool), SBT是SCALA 平台上标准的项目构建工具,当然你要用它来构建其他语言的项目也是可以的。SBT 没有Maven那么多概念和条条框框,但又比IVY要更加灵活,可以认为是一个精简版的Maven吧。这里对这阵子对SBT的学习做一个小的总结,希望对其他也初学阶段的朋友们有一点帮助,同时也便于以后查询翻阅,毕竟好记性不如烂笔头啊。
一、SBT 下载和安装
http://www.scala-sbt.org/download.html
最新稳定版是 0.13.13,由于scala是运行在JVM上的,所以需要有JRE(JRE的安装配置这里就不详述了)。这里以linux平台为例进行说明,将下载的.tgz文件解压缩,然后将SBT的可执行文件路径加到系统PATH环境变量里,就可以运行sbt使用了,当然你如果不闲麻烦也可以不配置PATH直接打全路径运行。
二、SBT `Hello World`
默认情况下,启动 sbt 的当前目录会作为项目的基本目录,也就是SBT会以这个目录作为根目录,它里面描述的路径也都是相对于这个根目录的。SBT项目的项目配置文件分两类:.sbt文件和.scala文件。.sbt文件是后面加上去的,最开始只有.scala文件。.sbt的出现简化了项目的配置,同时也使得配置更为清晰可读,但是.scala的配置更为灵活细致。这里为了简单起见,只使用.sbt文件,这对于一般项目来说也已经足够使用了。
SBT项目的目录层次结构跟maven类型,同样属于惯例优于配置的思想。下面就以一个简单的Hello world项目为例进行说明。
hello_world/
build.sbt
src/
main/
scala/
java/
resources/
test/
scala/
java/
resources/
project/
sbt.properties
plugins.sbt
这里只要把源文件放到 src/main/scala下面,其他先不用管,下一节进行分析。
//---------------HelloWorld----------------
object HelloWorld {
def main(args: Array[String]) {
println("Hello World!")
}
}
在hello_world目录下运行 sbt run(或者先运行sbt进入命令行模式,再输入run回车),即可看到运行结果。
三、SBT 基本概念
SBT会根据当前项目的配置文件得到一个哈希映射表来描述整个项目,然后当你输入表中一个Key的名字时,sbt就会执行该key对应的任务(或者显示对应的值)。项目的配置文件首先会生成一个大的配置列表 Seq[Setting],这个列表中每一个setting是对项目哈希表的一个更新,会生成一个新的哈希表替换原来的哈希表,SBT实际生成该哈希表的时候会先对Seq[Setting]中的配置进行一下优化调整,将对相同key的setting放到一起,同时被依赖的key放前面。
SBT的Key共有三种类型:
(1)settingKey[T]("description...") 第一次调用该Key时得到对应value,后期保持不变;
e.g. lazy val key1 = settingKey[String]("description1")
(2)taskKey[T]("description...") 每一次调用该Key时都重新执行对应的task;
e.g. lazy val key2 = taskKey[Unit]("description2")
(3)inputKey[T]("description...") 每一次调用该Key时都重新执行对应的task,且可以携带参数;
e.g. lazy val key3 = inputKey[String]("description3")
定义好Key,当然是给其赋予对应的值了(这里接着上面的例子进行说明),
(1)settingKey[T]("description...")
e.g. key1 := "hello world"
(2)taskKey[T]("description...")
e.g. key2 := {
println("hello world!")
}
(3)inputKey[T]("description...")
e.g. key3 := {
val args: Seq[String] = spaceDelimited("<arg>").parsed
args.mkString("-")
}
注意每一个配置表达式之间需要用一个空行分隔,用于区分不同的表达式,SBT会自动将key的定义相关表达式置前,同时把被依赖的key的配置置前。刚接触build.sbt文件时,我们发现很多key没有定义直接被使用了,其实不是这样的,SBT默认已经导入了一些定义好的key(import sbt._,Keys._)。另外,:=只是key的一个方法,返回值为一个setting用于更新项目哈希表,还有类似的方法 +=, ++=等等。
定义key时候的变量名会作为key的名字,key还有一个scope属性,决定了key作用的范围,这个scope的内容还比较丰富。scope 分成了三个轴:project 轴、configuration轴以及task轴,这使得可以很精确地确定key的使用范围,下面对每个轴进行简要说明。
(1)project 轴
这个是项目构建的概念,一个构建中可以有多个项目,一个sbt实例甚至可以起多个构建(虽然好像很少人这么做)
(2)configuration 轴
类似于maven里面configuration的概念,即:compile、test、package、run
(3)task轴
就是给taskKey所赋的函数中的作用域
举个具体scoped key的例子:
{file:/root/scala_test/hello_test_scala_pro/}hellotestpro/compile:key2::key1
简要分析:
project轴: {file:/root/scala_test/hello_test_scala_pro/}hellotestpro // 格式为 {project_uri}project_id
configuration轴: compile
task轴: key2
三个轴组成了key1的scope。
对于每个轴,都有一个Global的实例,表示在该轴的所有实例上都是有效的。为了简化输入,并不是每个key1调用的时候都需要写这么长的scope,SBT会在你给出具体值的轴上给出一些默认值。例如:没有写project轴时,默认是当前项目;没有写configuration时默认是Global的;没有写task轴时,默认也是Global的。
关于sbt的基本概念就说这么多了,希望本文能对初学者对SBT基本原理上的理解有一定的帮助,更详细的使用描述以后有空再添加吧,大家也可以参考官网上的教程,说的都很详细。