SBT安装
mac os可以利用homebrew进行安装:
brew install sbt
其他操作系统安装,略 ...
SBT约定的目录结构
build.sbt
src/
main/
resources/ #数据文件
scala/ #scala源文件
java/ #java源文件
test/
resources/ #数据文件
scala/ #scala测试源文件
java/ #java测试源文件
lib #jar文件
project
build.properties
plugins.sbt
以上只是稍微完整的sbt工程目录结构,虽然并不是每一部分都必须,但是最好遵守约定。
现在,手动构建工程目录结构(scala相关),命令如下:
touch build.sbt
mkdir -p src/main/resources src/main/scala src/test/resources/ src/test/scala/ lib/ project/
touch project/build.properties project/plugins.sbt
大多数项目需要一些手动设置。基本的构建设置都放在项目根目录的 build.sbt 文件里。 例如,如果你的项目放在 hello 下,在 hello/build.sbt 中可以这样写:
lazy val root = (project in file(".")).
settings(
name := "hello",
version := "1.0",
scalaVersion := "2.11.7"
)
如果你准备将你的项目打包成一个 jar 包,在 build.sbt 中至少要写上 name 和 version。
可以通过创建 project/build.properties 文件强制指定一个版本的 sbt。在这个文件里,编写如下内容来强制使用 0.13.8:
sbt.version=0.13.8
sbt 在不同的 release 版本中是 99% 兼容的。但是在 project/build.properties 文件中设置 sbt 的版本仍然能避免一些潜在的混淆。
.sbt构建定义
构建定义有三种风格。
- 多工程 .sbt 构建定义
- bare .sbt 构建定义
- .scala 构建定义
本文讨论最新的多工程.sbt 构建定义,它结合了两种老风格的优点,并且适用于所有情况。此外,构建定义可以包含以.scala结尾的文件,位于基目录的project/文件夹下,来定义常用的函数和值。
将多个相关的项目定义在一个构建中是很有用的,尤其是如果它们依赖另一个,而且你倾向于一起修改它们。每个子项目在构建中都有它们自己的源文件夹,当打包时生成各自的 jar 文件,而且通常和其他的项目一样运转。
下面,我们构建一个子项目,位于hw目录下:
目录结构build.sbt:
lazy val common_settings = Seq(
organization := "com.demo",
version := "0.0.0",
scalaVersion := "2.11.7"
)
lazy val hw = (project in file("hw")).settings(common_settings: _*).settings(
name := "hello"
)
现在我们可以在一处修改version,当重新加载构建时,将在各个子项目相应更新。
project/build.properties:
sbt.version=0.13.8
hw/src/main/scala/hw/Hello.scala
package hw
object Hello {
def hello () = {
println("hello world");
}
}
依赖
构建中的项目完全可以彼此独立,但是通常情况下它们会有依赖上的一些相关性。有两种类型的依赖:aggregate 和 classpath。
Aggregation
Aggregation 意味着在 aggregate 项目上执行一个 task 也会在 aggregated 的项目执行。例如,
lazy val root = (project in file(".")).aggregate(util, core)
lazy val util = project ...
lazy val core = project ...
在上面的例子中,root 项目聚合了util和core。像例子中一样,随着有两个子项目的情况下启动 sbt,然后尝试编译。你应该会看到全部的三个项目都被编译了。
在进行聚合的项目中,像这个例子中的 root 项目一样,你可以按 task 来控制聚合。例如,为了避免聚合update task:
lazy val root = (project in file(".")).
aggregate(util, core).
settings(
aggregate in update := false
)
[...]
Classpath 依赖
一个项目可能依赖另一个项目的代码。这是通过添加 dependsOn 方法来实现的。例如,如果 core 在 classpath 中需要 util,你将这样定义 core:
lazy val core = project.dependsOn(util)
现在 core 中的代码可以使用 util 的类。在编译时也会在两个项目之间创建顺序;在编译 core 之前,util 必须被更新和编译过。
为了依赖多个项目,像这样 dependsOn(bar, baz) 给 dependsOn 多个参数。
默认的 root 项目
如果在构建中根目录没有定义项目,sbt 会在构建中创建一个默认的项目并将其他项目也聚合起来。继续我们刚才创建的hw例子,因为 hw 项目定义了 base = file("hw"),它将会被包含在 hw 子目录中。它的源文件可以直接放在 hw 下,像 hw/Hw.scala,或者在 hw/src/main/scala 中。通常 sbt 的目录结构应用在hw目录下除了构建定义文件。hw 中的任何 .sbt 文件,比如说 hw/build.sbt,将会和整个构建合并,但是在 hw 项目的 scope 中。
如果你的的整个项目都在根目录中,尝试在 build.sbt,hw/build.sbt 中定义一个不同的版本(version := "0.6")。 现在在 sbt 的命令行中执行 show version。你应该得到这样的信息(随着你定义的任何版本):
> show version
[info] xxx/*:version
[info] 0.7
[info] xxx/*:version
[info] 0.9
每个项目的设置都可以放该项目基目录下的.sbt文件中,在子项目中,你不能有项目的子目录或者project/*.scala 文件。foo/project/Build.scala 将会被忽略。
交互式引导项目
在 sbt 的命令行中,输入 projects 列出你的项目,执行 project <projectname> 可以选择当前项目。当你执行 task 像 compile,它会在当前项目上执行。 所以你没有必要去编译 root 项目,你可以只编译子项目。
你可以通过显示的指定项目 ID 在另一个项目上执行一个 task,例如 subProjectID/compile。
详细代码位于github项目:https://github.com/tskshy/scala-demo.git
网友评论