访问当前作用域下的SBT设置

访问当前作用域下的SBT设置,sbt,Sbt,我在试图理解sbt中的范围概念时遇到了一个问题。我希望任务在特定范围下运行,并且能够访问范围设置,即 构建.sbt name := "Superapp" name in Test := "Testapp" val printScopedKey = TaskKey[Unit]("psk", "Print Scoped Key") printScopedKey := println("***** [APP NAME] " + name.value) 我预计会出现以下情况: > test

我在试图理解sbt中的范围概念时遇到了一个问题。我希望任务在特定范围下运行,并且能够访问范围设置,即

构建.sbt

name := "Superapp"

name in Test := "Testapp"

val printScopedKey = TaskKey[Unit]("psk", "Print Scoped Key")

printScopedKey := println("***** [APP NAME] " + name.value)
我预计会出现以下情况:

> test:psk
> ***** [APP NAME] Testapp
> test:psk
> ***** [APP NAME] Testapp
而不是实际的:

> ***** [APP NAME] Superapp

我如何在sbt中做到这一点?这可能吗?

谢谢你的提问!我起初以为我知道答案,后来才意识到答案并不那么简单。我不得不四处寻找解决办法

我使用sbt0.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
我发现解决方案可以归结为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
加载构建文件时,sbt将自动知道当您执行
psk
时,它的依赖项是编译中的
name
,而
test:psk
依赖于测试中的
name
。很聪明

> 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
使用
inspect
深入挖掘。了解它在引擎盖下的工作原理总是非常有用的(一旦你开始使用正确的工具,比如
inspect
),这并不难理解

没有在
Test
配置中实际定义
psk
任务,sbt将首先在
Global
配置中查找
psk
任务,然后按照项目的
configurations
顺序,默认情况下是
Seq(编译、运行时、测试、提供、可选)

因此,下面(以及@Jacek Laskowski的答案)描述了如何将任务定义到多个作用域中,而无需代码重复。设置的范围可以分为三个轴(项目、配置和任务)。项目部分没有发挥太多的作用,因此我们将在这里讨论配置和任务

建议将特定于任务的设置范围限定为任务,以鼓励重用密钥。例如:

程序集中的测试:={} 在上面的
test
中,键的作用域是
assembly
任务,用于控制在创建胖JAR之前运行的测试。您可以定义一个“任务生成器”方法,该方法将接受一个键,并围绕该键创建一个设置图:

def assemblyTask(key:TaskKey[File]):初始化[Task[File]]=def.Task{
val t=(在键中测试).value
val s=(键中的流)。值
程序集((键中的outputPath).value,(键中的assemblyOption).value,
(键中的packageOptions).value,(键中的assembledMappings).value,
s、 缓存目录(s.log)
}
我使用它来定义
assembly
packageScala
,以及
packageDependency
任务

lazy val baseAssemblySettings:Seq[sbt.Def.Setting[\u]]=Seq(
assembly:=assembly.assemblyTask(assembly).value,
packageScala:=Assembly.assemblyTask(packageScala).value,
....
)
到目前为止,
baseAssemblySettings
是配置中立的

如果我想在
Compile
Test
等配置中对其进行范围限定,我会调用
inConfig(conf)(settings)
,如下所示:

lazy val assemblySettings: Seq[sbt.Def.Setting[_]] =
  inConfig(Compile)(baseAssemblySettings) ++
  inConfig(Test)(baseAssemblySettings)
现在您有了多个配置中的多个任务图