范围在sbt中很重要。我完全没问题。但是也有委托规则允许您构建设置的分层结构。我想用它来为更具体的规则带来额外的设置。
import sbt._
import Keys._
object TestBuild extends Build {
val sourceExample = settingKey[Seq[String]]("example source for setting dependency")
val targetExample = settingKey[Seq[String]]("example of a dependent setting")
override lazy val settings = super.settings ++ Seq (
sourceExample := Seq("base"),
targetExample := "extended" +: sourceExample.value,
sourceExample in Test += "testing"
)
}
该示例为我提供了意外的输出:
> show compile:sourceExample
[info] List(base)
> show test:sourceExample
[info] List(base, testing)
> show compile:targetExample
[info] List(extended, base)
> show test:targetExample
[info] List(extended, base)
我希望test:targetExample
为List(extended, base, testing)
而不是List(extended, base)
。一旦我得到结果,我立即弄清楚为什么它如图所示。 test:targetExample
*:targetExample
代表libraryDependencies in Test
计算的值,但不是在嵌套范围内计算它的规则。
这种行为给我编写自己的插件带来了两个困难。作为插件开发人员,我有额外的工作要在每个范围内定义相同的规则。我必须记住内部任务的范围定义,才能正确地将其用作用户。
如何克服这种不便?我想在 call-by-name 语义中引入设置,而不是按值调用。什么技巧可能适用于它?
P.S。使用% test
时,trait A { lazy val x : Int = 5 }
trait B extends A { lazy val y : Int = x * 2}
trait C extends A { override lazy val x : Int = 3 }
看起来更简洁。
我应该清楚地表明,我完全理解sbt正如文档中描述的那样导出值。它起着创作者的作用。
但我为什么要服从规则呢?我看到他们完全违反直觉。 Sbt引入了实际工作的继承语义,与过去定义的方式不同。当你写
(new B with C).y
你希望name->value
是6,而不是10.知道它实际上是10允许你正确使用这种继承,但是你希望找到更常规的方法来实现继承。您甚至可以根据{{1}}字典编写自己的实现。并且您可以根据编程的第十条规则继续进行。
所以我正在寻找一种能够根据常见语言带来继承语义的黑客。作为一个起点,我建议编写command来扫描所有设置,并明确地将它们从父母推送到孩子。并且每次sbt运行时自动调用此命令。
但对我来说这似乎太脏了,所以如果有更多优雅的方式来实现类似的语义,我很好奇。
答案 0 :(得分:0)
"错误" 值的原因是targetExample
取决于sourceExample
范围内的Compile
,如下所示:
targetExample := "extended" +: sourceExample.value
如果它使用sourceExample
范围内的Test
值,请使用in Test
明确表达您的意愿,如下所示:
targetExample := "extended" +: (sourceExample in Test).value
使用inspect
了解依赖关系链。
顺便说一句,我强烈建议使用build.sbt
文件进行这样一个简单的构建定义。
答案 1 :(得分:0)
您可以使用默认设置,并按Plugins Best Practices - Playing nice with configurations中所述的不同配置重复使用。我相信,这应该给你一个类似于你正在寻找的语义。
您可以定义基本设置并在不同配置中重复使用。
import sbt._
import Keys._
object TestBuild extends Build {
val sourceExample = settingKey[Seq[String]]("example source for setting dependency")
val targetExample = settingKey[Seq[String]]("example of a dependent setting")
override lazy val settings = super.settings ++
inConfig(Compile)(basePluginSettings) ++
inConfig(Test)(basePluginSettings ++ Seq(
sourceExample += "testing" // we are already "in Test" here
))
lazy val basePluginSettings: Seq[Setting[_]] = Seq (
sourceExample := Seq("base"),
targetExample := "extended" +: sourceExample.value
)
}
PS。既然你正在谈论编写你的插件,你可能还想看看编写sbt插件的新方法,即AutoPlugin,因为旧的机制现在是deprecated。