我在尝试理解sbt中的范围概念时遇到了问题.我希望在特定范围内运行任务,并且能够访问范围设置,即
build.sbt
name := "Superapp"
name in Test := "Testapp"
val printScopedKey = TaskKey[Unit]("psk", "Print Scoped Key")
printScopedKey := println("***** [APP NAME] " + name.value)
Run Code Online (Sandbox Code Playgroud)
我期待以下内容:
> test:psk
> ***** [APP NAME] Testapp
Run Code Online (Sandbox Code Playgroud)
而不是实际的:
> ***** [APP NAME] Superapp
Run Code Online (Sandbox Code Playgroud)
我怎么能在sbt做到这一点?这甚至可能吗?
OP写道:"我期待以下内容:"
> test:psk
> ***** [APP NAME] Testapp
Run Code Online (Sandbox Code Playgroud)
如果没有psk在Test配置中实际定义任务,sbt将psk首先在Global配置中查找任务,然后configurations按项目的顺序查找,默认情况下是Seq(Compile, Runtime, Test, Provided, Optional).
因此,以下(以及@Jacek Laskowski的回答)描述了如何在没有代码重复的情况下将任务定义到多个范围中.设置可以在三个轴(项目,配置和任务)中确定范围.项目部分没有发挥作用,所以我们将在这里讨论配置和任务.
建议将特定于任务的设置限定为任务,以鼓励重用密钥.例如:
test in assembly := {}
Run Code Online (Sandbox Code Playgroud)
在上面的test键的范围是assembly任务来控制在创建胖JAR之前运行的测试.您可以定义一个"任务生成器"方法,该方法将获取一个键并创建一个围绕它的设置图:
def assemblyTask(key: TaskKey[File]): Initialize[Task[File]] = Def.task {
val t = (test in key).value
val s = (streams in key).value
Assembly((outputPath in key).value, (assemblyOption in key).value,
(packageOptions in key).value, (assembledMappings in key).value,
s.cacheDirectory, s.log)
}
Run Code Online (Sandbox Code Playgroud)
我用它来定义assembly,packageScala和packageDependency任务.
lazy val baseAssemblySettings: Seq[sbt.Def.Setting[_]] = Seq(
assembly := Assembly.assemblyTask(assembly).value,
packageScala := Assembly.assemblyTask(packageScala).value,
....
)
Run Code Online (Sandbox Code Playgroud)
到目前为止baseAssemblySettings,配置中立.
如果我想在像Compile和的配置范围内Test,我会这样称呼inConfig(conf)(settings):
lazy val assemblySettings: Seq[sbt.Def.Setting[_]] =
inConfig(Compile)(baseAssemblySettings) ++
inConfig(Test)(baseAssemblySettings)
Run Code Online (Sandbox Code Playgroud)
现在,您有多个配置中的多个任务图.
谢谢你的提问!我最初以为我知道答案,然后意识到这并不是那么简单.我不得不四处寻找解决方案.
我使用sbt 0.13.2-RC1.
> about
[info] This is sbt 0.13.2-RC1
[info] The current project is {file:/C:/dev/sandbox/0.13.2/}root-0-13-2 0.1-SNAPSHOT
[info] The current project is built against Scala 2.11.0-RC3
[info] Available Plugins: org.sbtidea.SbtIdeaPlugin, de.johoop.jacoco4sbt.JacocoPlugin, com.timushev.sbt.updates.UpdatesPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.3
Run Code Online (Sandbox Code Playgroud)
我找到了Mark Harrah对sbt邮件列表中类似问题的回答的解决方案,归结为build.sbt中的以下更改:
scalaVersion := "2.11.0-RC3"
name := "Superapp"
name in Test := "Testapp"
name in Runtime := "Runtimeapp"
lazy val psk = taskKey[Unit]("Print Scoped Key")
val pskSetting = psk := println("***** [APP NAME] " + name.value)
// https://groups.google.com/d/msg/simple-build-tool/A87FFV4Sw4k/KPtygikQvogJ
val myPsks = Seq(Compile, Test, Runtime) flatMap { conf =>
inConfig(conf)( Seq(pskSetting) )
}
myPsks
Run Code Online (Sandbox Code Playgroud)
当构建文件被加载时,sbt将自动知道当你执行psk它的依赖name in Compile时test:psk依赖于name in Test.很聪明.
> psk
***** [APP NAME] Superapp
[success] Total time: 0 s, completed 2014-03-26 21:27:37
> test:psk
***** [APP NAME] Testapp
[success] Total time: 0 s, completed 2014-03-26 21:27:41
> runtime:psk
***** [APP NAME] Runtimeapp
[success] Total time: 0 s, completed 2014-03-26 21:27:44
Run Code Online (Sandbox Code Playgroud)
使用inspect进行深入分析.知道它是如何在引擎盖下工作总是非常有用(一旦开始使用正确的工具,这并不难理解inspect).