通常在一個工程中構(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
項目聚合了項目util
和core
,編譯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é))
注意:在聚合過程中聚合是并行處理的,所以被聚合的項目時沒有先后順序的
在源代碼層級一個項目可能會依賴另一個項目,可以通過 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)
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.sbt
中 hello-bar/*:version
被定義在hello/bar/build.sbt
中 hello/*: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)前項目下運行,所以沒有必要在根項目中編譯,可以單獨編譯一個子項目。
.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