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
没有具体的值,那么将在委托下列出的范围中按顺序搜索,直到找到定义的值。