如何在多项目.sbt构建中定义构建范围设置?

时间:2015-10-29 14:36:53

标签: scala sbt

从sbt 0.13开始,定义所有配置的推荐方法是multi-project .sbt build definition。绝对清楚如何为那里的每个项目定义设置;但是,如何定义构建范围的设置,例如,在ThisBuildGlobal范围内?

使用Scala构建定义很明显:我们有来自settings特征的Build密钥:

object MyBuild extends Build {
  override lazy val settings = super.settings ++ Seq(
    someKey := someValue
  )
}

现在someKey的值默认为build-scoped。或者,可以使用.sbt范围直接在ThisBuild文件中定义它:

someKey in ThisBuild := someValue

但是,在多项目.sbt版本中没有自然的位置来定义这些选项。我怀疑它们应该在ThisBuild范围的一个项目中定义:

val someProject = project
  .settings(someKey in ThisBuild := someValue)

但这非常违反直觉并且不是很清楚:这些设置是否真的适用于全球,还是属于特定项目?如果我在多个项目中定义相同的密钥怎么办?

val project1 = project.settings(someKey in ThisBuild := someValue1)

val project2 = project.settings(someKey in ThisBuild := someValue2)

遗憾的是,文档没有给出任何答案。

请注意,我明确地询问如何在构建或项目之间共享全局设置。我问具体关于定义构建范围的设置。

1 个答案:

答案 0 :(得分:3)

嗯,我已经进行了一些实验并发现了以下内容。以下是build.sbt示例:

val testKey = settingKey[String]("A key for test")

testKey := "value in build.sbt"
testKey in ThisBuild := "build-scoped value in build.sbt"
testKey in Global := "global value in build.sbt"

lazy val root = (project in file("."))
  .settings(
    testKey := "value in root project",
    testKey in ThisBuild := "build-scoped value in root project",
    testKey in Global := "global value in root project"
  )

lazy val child = project
  .settings(
    testKey := "value in child",
    testKey in ThisBuild := "build-scoped value in child project",
    testKey in Global := "global value in child project"
  )

以及我在SBT控制台中看到的内容:

[info] Set current project to root (in build file:/private/tmp/sbtt/)
> inspect testKey
[info] Setting: java.lang.String = value in build.sbt
[info] Description:
[info]  A key for test
[info] Provided by:
[info]  {file:/private/tmp/sbtt/}root/*:testKey
[info] Defined at:
[info]  /private/tmp/sbtt/build.sbt:4
[info] Delegates:
[info]  root/*:testKey
[info]  {.}/*:testKey
[info]  */*:testKey
[info] Related:
[info]  */*:testKey
[info]  {.}/*:testKey
[info]  child/*:testKey
> testKey
[info] value in build.sbt
> root/testKey
[info] value in build.sbt
> child/testKey
[info] value in child
> {.}/testKey
[info] global value in child
> reload
[info] Loading global plugins from /Users/netvl/.sbt/0.13/plugins
[info] Set current project to root (in build file:/private/tmp/sbtt/)
> testKey
[info] value in build.sbt
> root/testKey
[info] value in build.sbt
> child/testKey
[info] value in child
> {.}/testKey
[info] build-scoped value in child project
> */testKey
[info] global value in child project

所以,结论如下。

  • 多项目SBT构建中最顶层定义的值似乎是作为build.sbt所属项目的范围。也就是说,这里build.sbt驻留在根目录中,因此直接在文件中定义testKey与在(project in file(".")).settings(...)子句中定义它是相同的。根据SBT输出,它们也优先于.settings(...)中定义的那些。
  • ThisBuildGlobal等较大范围内的键似乎可以在任何项目中定义,但是"稍后"然后项目将优先考虑。这可能与项目的处理顺序有关。我预计lazy val s的评估顺序会影响这一点,我已经尝试将.aggregate(child)添加到根项目中以强制首先评估子项目,但它没有#&# 39; t似乎有任何影响:来自子项目的全局范围值仍然具有优先权。

因此,在根项目或公共设置列表中定义构建范围或全局范围的值似乎很好,然后在每个项目中使用它们。但是,在不同项目中为构建或全局范围中的键分配不同的值可能会导致奇怪的行为 - 这些值中只有一个会生效,而我不知道哪个值。

如果在文档中解释了所有这些,那将是非常好的,但目前我无法在此处找到任何关于此行为的内容。

我很乐意接受别人的回答,这将提供更多有关SBT如何在这方面工作的见解。