通常在一個(gè)工程中構(gòu)建多個(gè)項(xiàng)目間會(huì)有關(guān)聯(lián),尤其是它們都依賴一個(gè)項(xiàng)目時(shí)可以很容易的更新項(xiàng)目
在一個(gè)工程中每個(gè)子項(xiàng)目都會(huì)有自己的源代碼目錄、生成各自的jar包當(dāng)執(zhí)行 package 時(shí).
一個(gè)項(xiàng)目通過(guò)申明一個(gè) Project 類(lèi)型的懶值來(lái)定義,例如:
lazy val util = project
lazy val core = project
這個(gè)變量值名稱將被用來(lái)當(dāng)做 Project Id 和項(xiàng)目的根目錄名稱,這個(gè)ID將用來(lái)在命令行中引用項(xiàng)目,利用方法in 可以修改默認(rèn)的項(xiàng)目根目錄。例如, 以下是更加明確的申明項(xiàng)目:
lazy val util = project.in(file("util"))
lazy val core = project in file("core")
在一個(gè)工程中一個(gè)項(xiàng)目完全可能依賴另一個(gè)項(xiàng)目,經(jīng)常有兩種依賴方式:聚合和classpath
聚合的意思是當(dāng)運(yùn)行一個(gè)任務(wù)在一個(gè)項(xiàng)目中,其通過(guò)聚合方式依賴的項(xiàng)目也會(huì)執(zhí)行,例如:
lazy val root = (project in file(".")).
aggregate(util, core)
lazy val util = project
lazy val core = project
在上面的例子中,root項(xiàng)目聚合了項(xiàng)目util和core,編譯root項(xiàng)目將看到三個(gè)項(xiàng)目被編譯。
在項(xiàng)目聚合過(guò)程中,以root項(xiàng)目為例,是可以控制任務(wù)維度作用域的配置的,例如,可以控制在執(zhí)行update這個(gè)任務(wù)時(shí)不進(jìn)行聚合:
lazy val root = (project in file(".")).
aggregate(util, core).
settings(
aggregate in update := false
)
[...]
aggregate in update 表示在update這個(gè)任務(wù)維度作用域中aggregate的配置。(具體可參考作用域章節(jié))
注意:在聚合過(guò)程中聚合是并行處理的,所以被聚合的項(xiàng)目時(shí)沒(méi)有先后順序的
在源代碼層級(jí)一個(gè)項(xiàng)目可能會(huì)依賴另一個(gè)項(xiàng)目,可以通過(guò) dependsOn 方法添加依賴關(guān)系,例如,core項(xiàng)目需要在classpath中指定util項(xiàng)目,可以這樣定義core項(xiàng)目:
lazy val core = project.dependsOn(util)
這樣就可以在core項(xiàng)目中調(diào)用util項(xiàng)目的方法, 當(dāng)編譯的時(shí)候會(huì)有編譯順序,util必須在core之前編譯, 如果依賴多個(gè)項(xiàng)目,可以給dependsOn方法指定多個(gè)參數(shù),例如,dependsOn(bar, baz)
foo dependsOn(bar) 表示foo在Compile這個(gè)配置維度作用域下依賴在配置維度作用域?yàn)?code>Compile下的bar項(xiàng)目,確切的寫(xiě)法應(yīng)該為:dependsOn(bar % "compile->compile"), 在"compile->compile"中的->表示項(xiàng)目間的依賴關(guān)系,所以"test->compile"可以表示為在Test配置維度作用域下的foo依賴Compile配置維度作用域下的bar
省略"->config"這部分隱含意思為"->compile", 所以dependsOn(bar % "test")意思是在Test配置維度作用域下的foo依賴Compile配置維度作用域下的bar
可以聲明為"test->test",意思為在Test配置維度作用域下項(xiàng)目依賴,例如,在src/test/scala目錄的公共類(lèi)庫(kù)可以在src/test/scala源代碼中使用。
針對(duì)一個(gè)依賴關(guān)系可以配置多個(gè)配置維度的作用域,用分號(hào)分隔,例如:dependsOn(bar % "test->test;compile->compile")
如果一個(gè)項(xiàng)目沒(méi)有在工程根目錄下定義,sbt將創(chuàng)建一個(gè)聚合整個(gè)工程子項(xiàng)目的默認(rèn)項(xiàng)目。
由于項(xiàng)目hello-foo 定義了base = file("foo"),項(xiàng)目目錄為子目錄foo, 源代碼可以直接放到foo目錄中,類(lèi)似foo/Foo.scala或放到src/main/scala,如果是采用sbt工程構(gòu)建標(biāo)準(zhǔn)目錄,foo目錄下還包括工程構(gòu)建定義文件。
在foo目錄下的任何.sbt文件將被合并在一起,并且定義的配置項(xiàng)屬于項(xiàng)目維度hello-foo作用域。
在hello工程中允許子項(xiàng)目配置不同的版本,可以在配置文件: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中
每個(gè)version是不同的項(xiàng)目維度作用域,但是這三個(gè)build.sbt部分配置是相同的
每個(gè)項(xiàng)目的配置都在自己項(xiàng)目目錄下的 .sbt 文件中配置,其實(shí)對(duì)于上述配置有更簡(jiǎn)單的方法,那就是配置到 .scala 文件中,列舉出項(xiàng)目和對(duì)應(yīng)的項(xiàng)目根目錄
你會(huì)發(fā)現(xiàn)將多個(gè)項(xiàng)目按順序定義在 .scala 配置文件中會(huì)比單獨(dú)定義在各自的目錄下更加清晰,不過(guò)這個(gè)自己決定。
不允許定義一個(gè)子目錄為project的目錄,foo/project/Build.scala將會(huì)被忽略
在sbt的交互模式下,使用命令projects 列舉出該工程的所有項(xiàng)目,命令project <projectname>可以切換當(dāng)前項(xiàng)目。當(dāng)運(yùn)行一個(gè)任務(wù)的時(shí)候(比如compile)將在當(dāng)前項(xiàng)目下運(yùn)行,所以沒(méi)有必要在根項(xiàng)目中編譯,可以單獨(dú)編譯一個(gè)子項(xiàng)目。
.sbt 配置文件中的定義在多個(gè) .sbt 中是相互不可見(jiàn)的,為了是多個(gè).sbt間復(fù)用配置,可以在根目錄的project目錄下定義一個(gè)或多個(gè) .scala 的文件,這個(gè)目錄其實(shí)也是一個(gè)sbt工程,只不過(guò)這個(gè)的作用是工程構(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