State 是 sbt 中所有可用信息的入口点。关键方法是
definedCommands: Seq[Command]
返回所有已注册的 Command 定义remainingCommands: List[Exec]
返回要运行的剩余命令attributes: AttributeMap
包含通用数据。命令的操作部分执行工作并转换 State
。以下部分讨论 State => State
转换。如前所述,命令通常也会处理解析后的值:(State, T) => State
。
Command 可以修改当前注册的命令或要执行的命令。这在操作部分通过转换提供给命令的(不可变)State 来完成。注册额外功能命令的函数可能如下所示
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
s 以及来自 .sbt 和 .scala 文件的原始永久设置(分别为 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
有一些便捷的重载,可用于仅指定所需的范围轴。有关 in
和设置接口的其他部分的定义位置,请参阅 Structure.scala。一些示例
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
s。
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
,该任务将计数器属性设置为某个值。