为什么"set"无法为自定义SettingKey赋值我可以在sbt shell中"显示"?

Set*_*sue 10 scala sbt

以下是一个0.13.1带有自定义设置和值的sbt 项目:

% pwd
/Users/tisue/myproj
% ls
build.sbt
% cat build.sbt
val foo = settingKey[String]("This is a custom setting")

foo := "bar"
% sbt
[info] Set current project to myproj (in build file:/Users/tisue/myproj/)
> show foo
[info] bar
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但现在:

> set foo := "qux"
<set>:1: error: not found: value foo
foo := "qux"
^
[error] Type error in expression
Run Code Online (Sandbox Code Playgroud)

这不应该工作吗?

我部分明白这里出了什么问题; set评估Scala表达式,该表达式显然是在val foo不在范围内的上下文中编译的.

但是我希望从文件中编译foo时确保范围的魔力,当在shell中编译相同的东西时也会有效.foo := ....sbt

Eug*_*ota 8

自版本0.13.6(2014-09-12)起,这不再是限制(#1059/#1456)


原始答案 - 适用于任何使用sbt 0.13.0 - 0.13.5的项目

事实证明,0.13.0的变化清楚地表明这是一种预期的行为:

所有定义都是在设置之前编译的,但将定义放在一起可能是最佳实践.目前,定义的可见性仅限于定义的.sbt文件.此时,它们consoleProjectset命令或命令中也不可见.在项目中使用Scala文件/在所有.sbt文件中查看可见性.

有了这个,你应该能够在project/Build.scala如下定义之后共享设置:

import sbt._
import Keys._

object HelloBuild extends Build {
  lazy val foo = settingKey[String]("This is a custom setting")

  foo := "Build.scala"
}
Run Code Online (Sandbox Code Playgroud)

build.sbt

scalaVersion := "2.10.4-RC1"

foo := "build.sbt"
Run Code Online (Sandbox Code Playgroud)

然后,在sbt shell中:

[sbt-0-13-1]> foo
[info] build.sbt
[sbt-0-13-1]> set foo := "shell"
[info] Defining *:foo
[info] The new value will be used by no settings or tasks.
[info] Reapplying settings...
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
[sbt-0-13-1]> foo
[info] shell
Run Code Online (Sandbox Code Playgroud)