我正在使用SBT 0.13。我遇到了一个问题,以下玩具示例展示了这个问题:
lazy val nativeOne = TaskKey[Unit]( "nativeOne", "One" )
lazy val nativeTwo = TaskKey[Unit]( "nativeTwo", "Two" )
lazy val testProj = Project(
id = "testProj",
base = file( "." ),
settings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.10.2",
nativeOne :=
{
println( "Native one"
},
nativeTwo :=
{
if ( true )
{
println( "Native two" )
}
else
{
val n1 = nativeOne.value
}
}
)
)
如果我进入sbt并运行nativeTwo
:
> nativeTwo
Native one
Native two
为什么会这样?为什么评估false
分支?是不允许在TaskKeys中进行分支?
答案 0 :(得分:6)
在sbt 所有依赖项是在任务运行之前并行计算的。如果你要构建一个你所拥有的图表,那就是:
nativeOne
^
|
nativeTwo
您要做的是订购任务。在sbt中,我们尝试促进返回其他任务直接使用的结果的任务,因此.value
。这样做不是直接运行任务,而是说“给我这个其他任务的结果”。
理解sbt语法的最佳方式是scala-async项目的模仿。您的代码类似于以下异步代码:
nativeOne = async {
println( "Native one")
}
nativeTwo = async {
if(true) println("Native Two")
else await(nativeOne)
}
在那里,你只是说“等待价值,如果它还没有计算出来,那就更明显了。”
如果你想有选择地执行一个任务,你需要在sbt的Task[_]
层执行此操作,这有点冗长。我们正在使用“动态任务”。这是选择在运行时实际运行哪些任务的那个。
因此,您需要使用Def.taskDyn
方法,该方法允许您按照定义的顺序组合任务。您将使用toTask
的{{1}}方法自行处理任务。这不是处理任务产生的值。这是一个例子TaskKey
:
build.sbt
然后在sbt控制台中:
val taskOne = taskKey[Int]("test")
val taskTwo = taskKey[Int]("test2")
val taskThree = taskKey[Int]("test3")
val switchEm = settingKey[Boolean]("switch 'em")
switchEm := true
taskOne := { println("taskOne"); 1 }
taskTwo := { println("taskTwo"); 2 }
taskThree := Def.taskDyn({
if(switchEm.value) taskTwo.toTask
else taskOne.toTask
}).value
另请注意,您不会在inspect命令中看到更正的依赖项,因为依赖项是动态添加的:
> reload
[info] Loading project definition from /home/jsuereth/projects/sbt/test-projects/project
[info] Set current project to test-projects (in build file:/home/jsuereth/projects/sbt/test-projects/)
> taskThree
2