如何在多项目 .sbt 构建中定义构建范围设置? [英] How to define build-scoped settings in multi-project .sbt builds?

查看:74
本文介绍了如何在多项目 .sbt 构建中定义构建范围设置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As of sbt 0.13, the recommended way to define all configuration is multi-project .sbt build definition. It is absolutely clear how to define settings for each project there; however, how one should define build-wide settings, for example, in ThisBuild or Global scopes?

使用 Scala 构建定义很清楚:我们有来自 Build trait 的 settings 键:

With Scala build definitions it is clear: we have settings key coming from Build trait:

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

现在 someKey 的值将默认为构建范围.或者,它可以直接在 .sbt 文件中定义,具有 ThisBuild 范围:

Now someKey's value will be build-scoped by default. Alternatively, it can be defined directly in .sbt file with ThisBuild scope:

someKey in ThisBuild := someValue

然而,在多项目 .sbt 构建中没有自然的地方来定义这些选项.我怀疑它们应该在具有 ThisBuild 范围的项目之一中定义:

However, there is no natural place to define these options in multi-project .sbt builds. I suspect that they should be defined in one of the projects with ThisBuild scope:

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

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

but this is very counterintuitive and not really clear: are such settings really applied globally or do they really belong to the specific project? What if I define the same key in multiple projects?

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

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

不幸的是,文档对此没有给出任何答案.

The documentation does not give any answers on this, unfortunately.

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

Note that I explicitly do not ask how to share global settings between builds or projects. I ask specifically about defining build-scoped settings.

推荐答案

好吧,我进行了一些实验并发现了以下内容.这是一个示例 build.sbt:

Well, I've performed some experiments and found out the following. Here is an example 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 控制台中看到的:

and here's what I see in SBT console:

[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 的评估顺序会影响到这一点,我已经尝试将 .aggregate(child) 添加到根项目以强制子项目要首先评估,但它似乎没有任何影响:来自子项目的全局范围的值仍然具有优先权.
  • Values defined at the topmost level in a multi-project SBT build seem to be scoped to the project build.sbt belongs to. That is, here build.sbt resides in the root directory, and so defining testKey in the file directly is the same as defining it in (project in file(".")).settings(...) clause. According to SBT output, they also take priority over those defined in .settings(...).
  • Keys in larger scopes like ThisBuild or Global seem to be able to be defined in any project, but "later" projects will then take priority. This is probably related to the order the projects are processed. I have expected that the order of evaluation of lazy vals would affect this, and I've tried adding .aggregate(child) to the root project to force the child project to be evaluated first, but it didn't seem to have any effect: globally scoped values from child project still have priority.

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

Therefore, it seems fine to define build-scoped or globally scoped values inside the root project or inside common settings list which is then used in every project. However, assigning different values to a key in build or global scope in different projects will likely lead to a weird behavior - only one of these values will take effect, and which one I don't know.

如果所有这些都在文档中得到解释,那就太好了,但目前我在那里找不到任何关于这种行为的信息.

It would be very nice if all this were explained in the documentation, but at the moment I can't find anything on this behavior there.

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

I'd gladly accept someone else's answer which would provide more insight on how SBT works in this regard.

这篇关于如何在多项目 .sbt 构建中定义构建范围设置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆