鍍金池/ 教程/ 物聯(lián)網(wǎng)/ 多項目構(gòu)建
目錄結(jié)構(gòu)
Linux 平臺安裝 SBT
總結(jié)
安裝 SBT
簡單例子:Hello World
多項目構(gòu)建
作用域
配置文件 .sbt
Lib 庫依賴
運行 SBT
Windows 平臺安裝 SBT
插件使用
Mac 平臺安裝 SBT
配置文件 .scala
配置參數(shù)的方法
手動安裝 SBT
自定義配置和任務(wù)

多項目構(gòu)建

多項目

通常在一個工程中構(gòu)建多個項目間會有關(guān)聯(lián),尤其是它們都依賴一個項目時可以很容易的更新項目

在一個工程中每個子項目都會有自己的源代碼目錄、生成各自的jar包當(dāng)執(zhí)行 package 時.

一個項目通過申明一個 Project 類型的懶值來定義,例如:

lazy val util = project

lazy val core = project

這個變量值名稱將被用來當(dāng)做 Project Id 和項目的根目錄名稱,這個ID將用來在命令行中引用項目,利用方法in 可以修改默認的項目根目錄。例如, 以下是更加明確的申明項目:

lazy val util = project.in(file("util"))

lazy val core = project in file("core")

項目間依賴

在一個工程中一個項目完全可能依賴另一個項目,經(jīng)常有兩種依賴方式:聚合和classpath

項目聚合

聚合的意思是當(dāng)運行一個任務(wù)在一個項目中,其通過聚合方式依賴的項目也會執(zhí)行,例如:

lazy val root = (project in file(".")).
  aggregate(util, core)

lazy val util = project

lazy val core = project

在上面的例子中,root項目聚合了項目utilcore,編譯root項目將看到三個項目被編譯。

在項目聚合過程中,以root項目為例,是可以控制任務(wù)維度作用域的配置的,例如,可以控制在執(zhí)行update這個任務(wù)時不進行聚合:

lazy val root = (project in file(".")).
  aggregate(util, core).
  settings(
    aggregate in update := false
  )

[...]

aggregate in update 表示在update這個任務(wù)維度作用域中aggregate的配置。(具體可參考作用域章節(jié))

注意:在聚合過程中聚合是并行處理的,所以被聚合的項目時沒有先后順序的

classpath 依賴

在源代碼層級一個項目可能會依賴另一個項目,可以通過 dependsOn 方法添加依賴關(guān)系,例如,core項目需要在classpath中指定util項目,可以這樣定義core項目:

lazy val core = project.dependsOn(util)

這樣就可以在core項目中調(diào)用util項目的方法, 當(dāng)編譯的時候會有編譯順序,util必須在core之前編譯, 如果依賴多個項目,可以給dependsOn方法指定多個參數(shù),例如,dependsOn(bar, baz)

配置維度作用域的 classpath 依賴

foo dependsOn(bar) 表示foo在Compile這個配置維度作用域下依賴在配置維度作用域為Compile下的bar項目,確切的寫法應(yīng)該為:dependsOn(bar % "compile->compile"), 在"compile->compile"中的->表示項目間的依賴關(guān)系,所以"test->compile"可以表示為在Test配置維度作用域下的foo依賴Compile配置維度作用域下的bar

省略"->config"這部分隱含意思為"->compile", 所以dependsOn(bar % "test")意思是在Test配置維度作用域下的foo依賴Compile配置維度作用域下的bar

可以聲明為"test->test",意思為在Test配置維度作用域下項目依賴,例如,在src/test/scala目錄的公共類庫可以在src/test/scala源代碼中使用。

針對一個依賴關(guān)系可以配置多個配置維度的作用域,用分號分隔,例如:dependsOn(bar % "test->test;compile->compile")

默認根項目

如果一個項目沒有在工程根目錄下定義,sbt將創(chuàng)建一個聚合整個工程子項目的默認項目。

由于項目hello-foo 定義了base = file("foo"),項目目錄為子目錄foo, 源代碼可以直接放到foo目錄中,類似foo/Foo.scala或放到src/main/scala,如果是采用sbt工程構(gòu)建標(biāo)準目錄,foo目錄下還包括工程構(gòu)建定義文件。

在foo目錄下的任何.sbt文件將被合并在一起,并且定義的配置項屬于項目維度hello-foo作用域。

在hello工程中允許子項目配置不同的版本,可以在配置文件:hello/build.sbt, hello/foo/build.sbt, 和hello/bar/build.sbt中配置不同版本,現(xiàn)在在交互模式下執(zhí)行show version將看到如下信息:

> show version
[info] hello-foo/*:version
[info]  0.7
[info] hello-bar/*:version
[info]  0.9
[info] hello/*:version
[info]  0.5

hello-foo/*:version被定義在hello/foo/build.sbthello-bar/*:version被定義在hello/bar/build.sbthello/*:version被定義在hello/build.sbt

每個version是不同的項目維度作用域,但是這三個build.sbt部分配置是相同的

每個項目的配置都在自己項目目錄下的 .sbt 文件中配置,其實對于上述配置有更簡單的方法,那就是配置到 .scala 文件中,列舉出項目和對應(yīng)的項目根目錄

你會發(fā)現(xiàn)將多個項目按順序定義在 .scala 配置文件中會比單獨定義在各自的目錄下更加清晰,不過這個自己決定。

不允許定義一個子目錄為project的目錄,foo/project/Build.scala將會被忽略

交互模式下操作項目

在sbt的交互模式下,使用命令projects 列舉出該工程的所有項目,命令project <projectname>可以切換當(dāng)前項目。當(dāng)運行一個任務(wù)的時候(比如compile)將在當(dāng)前項目下運行,所以沒有必要在根項目中編譯,可以單獨編譯一個子項目。

配置代碼復(fù)用

.sbt 配置文件中的定義在多個 .sbt 中是相互不可見的,為了是多個.sbt間復(fù)用配置,可以在根目錄的project目錄下定義一個或多個 .scala 的文件,這個目錄其實也是一個sbt工程,只不過這個的作用是工程構(gòu)建。

例如:

<root>/project/Common.scala:

import sbt._
import Keys._

object Common {
  def text = "org.example"
}

在.sbt中可以直接調(diào)用:

<root>/build.sbt:

organization := Common.text