sbt 的核心是新的組態系統,旨在實現廣泛的自訂。此頁面的目標是解釋組態系統背後的通用模型,以及如何使用它。入門指南(請參閱.sbt 檔案)描述如何定義設定;此頁面描述如何與它們互動,以及如何在命令列中探索它們。
設定或任務的完整限定參考看起來像這樣
{<build-uri>}<project-id>/config:intask::key
這個「作用域金鑰」參考由 last
和 inspect
等命令使用,以及在選取要執行的任務時使用。通常剖析器只需要 key
;其餘的可選部分會選取作用域。這些可選部分會個別稱為作用域軸。在上述描述中,{<build-uri>}
和 <project-id>/
會指定專案軸,config:
是組態軸,而 intask
是任務特定軸。未指定的元件會被視為目前的專案(專案軸)或自動偵測(組態和任務軸)。星號 (*
) 用於明確參考 Global
內容,例如 */*:key
。
在未指定組態的情況下(也就是省略 config:
部分時),如果金鑰定義在 Global
中,則會選取該組態。否則,會選取定義金鑰的第一個組態,其中順序由專案定義的 configurations
成員決定。預設情況下,此順序為 compile, test, ...
例如,在 /home/user/sample/
中的建置中,於專案 root
中執行時,下列項目相等
> compile
> Compile/compile
> root/compile
> root/Compile/compile
> {file:/home/user/sample/}root/Compile/compile
另一個範例是,run
本身指的是 Compile/run
,因為沒有全域 run
任務,且搜尋的第一個組態 compile
定義了 run
。因此,若要參考 Test
組態的 run
任務,則必須指定組態軸,例如 Test/run
。其他一些需要明確 Test/
軸的範例如下
> Test/consoleQuick
> Test/console
> Test/doc
> Test/package
某些設定是針對每個任務定義的。當在相同組態(例如 compile
或 test
)中有數個相關任務時,會使用此功能,例如 package
、packageSrc
和 packageDoc
。對於封裝任務,其設定是要封裝的檔案、要使用的選項,以及要產生的輸出檔案。每個封裝任務應該能夠針對這些設定有不同的值。
這會使用任務軸來完成,該軸會選取要套用設定的任務。例如,下列項目會列印不同封裝任務的輸出 jar。
> package::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/demo_2.8.1-0.1.jar
> packageSrc::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/demo_2.8.1-0.1-src.jar
> packageDoc::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/demo_2.8.1-0.1-doc.jar
> test:package::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/root_2.8.1-0.1-test.jar
請注意,單個冒號 :
後面會跟著組態軸,而雙冒號 ::
後面會跟著任務軸。
本節討論 inspect
命令,此命令對於探索設定之間的關聯性很有用。例如,可以使用它來判斷應該修改哪個設定才能影響另一個設定。
inspect
提供的第一條資訊是任務的類型,或是設定的值和類型。輸出中的下列區段會標記為「提供者」。這會顯示設定定義的實際作用域。例如,
> inspect libraryDependencies
[info] Setting: scala.collection.Seq[sbt.ModuleID] = List(org.scalaz:scalaz-core:6.0-SNAPSHOT, org.scala-tools.testing:scalacheck:1.8:test)
[info] Provided by:
[info] {file:/home/user/sample/}root/*:libraryDependencies
...
這表示 libraryDependencies
已在全域組態 (*:
) 的目前專案 ({file:/home/user/sample/}root
) 上定義。對於像 update
這樣的任務,輸出看起來像這樣
> inspect update
[info] Task: sbt.UpdateReport
[info] Provided by:
[info] {file:/home/user/sample/}root/*:update
...
inspect
輸出的「相關」區段會列出金鑰的所有定義。例如,
> inspect compile
...
[info] Related:
[info] test:compile
這表示除了要求的 Compile/compile
任務之外,還有一個 Test/compile
任務。
正向相依性會顯示用於定義設定(或任務)的其他設定(或任務)。反向相依性則反向運作,顯示什麼使用給定的設定。inspect
會根據要求的相依性或實際相依性提供此資訊。要求的相依性是設定直接指定的相依性。實際設定是這些相依性解析成的設定。下列章節將更詳細地說明此區別。
舉例來說,我們將查看 console
> inspect console
...
[info] Dependencies:
[info] Compile / console / initialCommands
[info] Compile / console / streams
[info] Compile / console / compilers
[info] Compile / console / cleanupCommands
[info] Compile / console / taskTemporaryDirectory
[info] Compile / console / scalaInstance
[info] Compile / console / scalacOptions
[info] Compile / console / fullClasspath
...
這會顯示 console
任務的輸入。我們可以看到它從 Compile / console / fullClasspath
和 Compile / console / scalacOptions
取得其類別路徑和選項。因此,inspect
命令提供的資訊可協助尋找要變更的正確設定。金鑰(如 console
和 fullClasspath
)的慣例是,Scala 識別碼是駝峰式大小寫,而字串表示法是小寫並以破折號分隔。組態的 Scala 識別碼為大寫,以區分 compile
和 test
等任務。例如,我們可以從先前的範例推斷出如何在 Scala 直譯器啟動時新增要執行的程式碼
> set Compile / console / initialCommands := "import mypackage._"
> console
...
import mypackage._
...
inspect
顯示 console
使用設定 Compile / console / initialCommands
。將 initialCommands
字串轉譯為 Scala 識別碼,可得出 initialCommands
。compile
表示這是主要原始碼。console /
表示設定是 console
特有的。因此,我們可以在 console
任務上設定初始命令,而不會影響 consoleQuick
任務(例如)。
inspect actual <scoped-key>
會顯示使用的實際相依性。這很有用,因為委派表示相依性可能來自要求的作用域以外的作用域。使用 inspect actual
,我們可以確切看到哪個作用域正在為設定提供值。結合 inspect actual
和簡單的 inspect
,我們可以查看會影響設定的作用域範圍。返回「要求的相依性」中的範例,
> inspect actual console
...
[info] Dependencies:
[info] Compile / console / streams
[info] Global / taskTemporaryDirectory
[info] scalaInstance
[info] Compile / scalacOptions
[info] Global / initialCommands
[info] Global / cleanupCommands
[info] Compile / fullClasspath
[info] console / compilers
...
對於 initialCommands
,我們看到它來自全域作用域 (Global
)。將此與 inspect console
中的相關輸出合併
Compile / console / initialCommands
我們知道我們可以將 initialCommands
設定為與全域作用域一樣通用,與目前專案的 console
任務作用域一樣特定,或介於兩者之間的任何設定。這表示例如,我們可以為整個專案設定 initialCommands
,並且會影響 console
> set initialCommands := "import mypackage._"
...
我們可能想要在這裡設定它的原因是,其他主控台任務現在將使用此值。我們可以查看 inspect actual
的反向相依性輸出,以了解哪些任務使用我們的新設定
> inspect actual initialCommands
...
[info] Reverse dependencies:
[info] Compile / console
[info] Test / console
[info] consoleProject
[info] Test / consoleQuick
[info] Compile / consoleQuick
...
我們現在知道,在整個專案上設定 initialCommands
會影響該專案中所有組態的所有主控台任務。如果我們不希望初始命令應用於 consoleProject
,因為它沒有我們專案的類別路徑可用,我們可以使用更具體的任務軸
> set console / initialCommands := "import mypackage._"
> set consoleQuick / initialCommands := "import mypackage._"`
或組態軸。
> set Compile/ initialCommands := "import mypackage._"
> set Test / initialCommands := "import mypackage._"
下一部分描述「委派」區段,其中顯示了範圍的委派鏈。
一個設定具有一個鍵和一個範圍。如果範圍 A 沒有定義該鍵的值,則範圍 A 中對某個鍵的請求可能會委派給另一個範圍。委派鏈是明確定義的,並顯示在 inspect
命令的「委派」區段中。「委派」區段顯示當請求的鍵沒有定義值時,搜尋範圍的順序。
舉例來說,再次考慮 console
的初始命令。
> inspect console/initialCommands
...
[info] Delegates:
[info] console / initialCommands
[info] initialCommands
[info] ThisBuild / console / initialCommands
[info] ThisBuild / initialCommands
[info] Zero / console / initialCommands
[info] Global / initialCommands
...
這表示如果沒有針對 console/initialCommands
的特定值,則會依序列出「委派」下的範圍,直到找到定義的值。