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