State 是 sbt 中所有可用資訊的進入點。主要方法為
definedCommands: Seq[Command]
傳回所有已註冊的 Command 定義remainingCommands: List[Exec]
傳回要執行的剩餘命令attributes: AttributeMap
包含通用資料。命令的動作部分執行工作並轉換 State
。以下章節討論 State => State
轉換。如先前所述,命令通常也會處理剖析的值:(State, T) => State
。
Command 可以修改目前已註冊的命令或要執行的命令。這是透過在動作部分轉換提供給命令的(不可變)State 來完成。註冊額外 power 命令的函式可能如下所示
val powerCommands: Seq[Command] = ...
val addPower: State => State =
(state: State) =>
state.copy(definedCommands =
(state.definedCommands ++ powerCommands).distinct
)
這會取得目前的命令,附加新的命令,並捨棄重複項。或者,State 有一個方便的方法可以執行上述操作
val addPower2 = (state: State) => state ++ powerCommands
一些修改要執行的剩餘命令的函式範例
val appendCommand: State => State =
(state: State) =>
state.copy(remainingCommands = state.remainingCommands :+ "cleanup")
val insertCommand: State => State =
(state: State) =>
state.copy(remainingCommands = "next-command" +: state.remainingCommands)
第一個會新增一個命令,該命令會在所有目前指定的命令執行後執行。第二個會插入一個命令,該命令會接著執行。剩餘的命令將在插入的命令完成後執行。
若要指出命令已失敗且不應繼續執行,請傳回 state.fail
。
(state: State) => {
val success: Boolean = ...
if(success) state else state.fail
}
專案相關資訊儲存在 attributes
中。通常,命令不會直接存取此資訊,而是會使用方便的方法來擷取最有用的資訊
val state: State
val extracted: Extracted = Project.extract(state)
import extracted._
Extracted 提供
currentRef
)structure.data
)Setting
和原始的永久設定(分別為 session.append 和 session.original)所有專案資料都儲存在 structure.data
中,其類型為 sbt.Settings[Scope]
。通常,會以下列方式取得 T
類型資訊
val key: SettingKey[T]
val scope: Scope
val value: Option[T] = key in scope get structure.data
在此,SettingKey[T]
通常從 Keys 取得,並且與用來定義 .sbt
檔案中的設定的類型相同。 Scope 選擇要取得金鑰的作用域。可以使用 in
的便利多載來僅指定所需的作用域軸。請參閱 Structure.scala,以瞭解定義 in
和設定介面其他部分的位置。一些範例
import Keys._
val extracted: Extracted
import extracted._
// get name of current project
val nameOpt: Option[String] = (currentRef / name).get(structure.data)
// get the package options for the `Test/packageSrc` task or Nil if none are defined
val pkgOpts: Seq[PackageOption] = (currentRef / Test / packageSrc / packageOptions).get(structure.data).getOrElse(Nil)
BuildStructure 包含有關建置和專案關係的資訊。主要成員為
units: Map[URI, LoadedBuildUnit]
root: URI
URI
識別建置,而 root
識別載入的初始建置。 LoadedBuildUnit 提供有關單一建置的資訊。LoadedBuildUnit
的主要成員為
// Defines the base directory for the build
localBase: File
// maps the project ID to the Project definition
defined: Map[String, ResolvedProject]
ResolvedProject 具有與 project/Build.scala
中使用的 Project
相同的資訊,只是 ProjectReferences 會解析為 ProjectRef
。
sbt 中的類別路徑類型為 Seq[Attributed[File]]
。這允許將任意資訊標記到類別路徑項目。sbt 目前使用此功能將 Analysis
與項目建立關聯。這就是它管理多專案增量重新編譯所需資訊的方式。它也會將 ModuleID 和 Artifact 與受管理項目(透過依賴管理取得的項目)建立關聯。當您只需要底層的 Seq[File]
時,請使用 files
val attributedClasspath: Seq[Attribute[File]] = ...
val classpath: Seq[File] = attributedClasspath.files
從 命令(不是從另一個任務)執行特定專案任務並取得其結果會很有用。例如,IDE 相關命令可能想要從專案取得類別路徑,或者任務可能會分析編譯的結果。相關方法為 Project.runTask
,其簽名如下
def runTask[T](taskKey: ScopedKey[Task[T]], state: State,
checkCycles: Boolean = false): Option[(State, Result[T])]
例如,
val eval: State => State = (state: State) => {
// This selects the main 'compile' task for the current project.
// The value produced by 'compile' is of type inc.Analysis,
// which contains information about the compiled code.
val taskKey = Compile / Keys.compile
// Evaluate the task
// None if the key is not defined
// Some(Inc) if the task does not complete successfully (Inc for incomplete)
// Some(Value(v)) with the resulting value
val result: Option[(State, Result[inc.Analysis])] = Project.runTask(taskKey, state)
// handle the result
result match
{
case None => // Key wasn't defined.
case Some((newState, Inc(inc))) => // error detail, inc is of type Incomplete, use Incomplete.show(inc.tpe) to get an error message
case Some((newState, Value(v))) => // do something with v: inc.Analysis
}
}
若要取得特定專案的測試類別路徑,請使用此金鑰
val projectRef: ProjectRef = ...
val taskKey: Task[Seq[Attributed[File]]] =
(projectRef / Test / Keys.fullClasspath)
若要從任務存取目前的 State,請使用 state
任務作為輸入。例如,
myTask := ... state.value ...
也可以在任務中更新 sbt 狀態。若要執行此操作,任務必須傳回類型 StateTransform
。狀態會在任務評估完成時轉換。StateTransform
是透過一個函式從 State => State
建構,該函式接受 State
的先前值,並產生新的狀態。例如
import complete.DefaultParsers._
val counter = AttributeKey[Int]("counter")
val setCounter = inputKey[StateTransform]("Set the value of the counter attribute")
setCounter := {
val count = (Space ~> IntBasic).parsed
StateTransform(_.put(counter, count))
}
建立輸入任務 setCounter
,該任務會將計數器屬性設定為某個值。