如何在sbt 0.13中定义项目特定的设置/键

时间:2013-11-20 19:55:23

标签: scala sbt

我有一个简单的多项目,其中根聚合项目ab。根项目加载了我正在编写的插件,该插件应该可以轻松地与我们公司的构建系统集成。

lazy val a = project in file("a")

lazy val b = project in file("b")

现在,我想在插件中定义一些在根项目中没有意义的Setting,并且每个子项目可以有不同的值。但是,如果我只是将它们定义为

object P extends Plugin {
    val kind = settingKey[Kind]("App or Lib?")
    val ourResolver = settingKey[Resolver]("...")

    override def projectSettings = Seq(
        // I want this to only be defined in a and b, where `kind` is defined
        ourResolver <<= kind { k => new OurInternalResolver(k) }
    )
}

然后sbt会抱怨无法定义ourResolver,因为根项目中未定义kind

有没有办法为此设置指定范围(ourResolver),以便在除根项目之外的每个聚合项目中定义

或者我是否必须将其设为SettingKey[Option[_]]并默认将其设为None

编辑:我有很多设置,逐渐依赖kind然后依赖ourResolver等等,这些设置应该只定义在哪里(读取) :“在项目范围中,”)kind已定义。为示例代码添加了ourResolver以反映这一点。

2 个答案:

答案 0 :(得分:1)

  

但是,如果我只是将它们定义为....

设置密钥并没有什么神奇之处。密钥只是String条目与类型绑定。所以你可以按照你现在的方式定义你的密钥就好了。

  

有没有办法为此设置指定范围,以便在除根项目之外的每个聚合项目中定义设置?

设置包含以下四项内容:

  1. 范围(项目,配置,任务)
  2. 一把钥匙
  3. 依赖关系
  4. 评估自己的能力(def evaluate(Settings[Scope]): T
  5. 如果您没有另行指定,则您的设置已限定为构建定义中的特定项目。

    lazy val a = (project in file("a")).
      settings(commonSettings: _*).
      settings(
        name := "a",
        kind := Kind.App,
        libraryDependencies ++= aDeps(scalaVersion.value)
      )
    
    lazy val b = (project in file("b")).
      settings(commonSettings: _*).
      settings(
        name := "b",
        kind := Kind.Lib,
        libraryDependencies ++= bDeps(scalaVersion.value)
      )
    
    lazy val root = (project in file(".")).
      settings(commonSettings: _*).
      settings(
        name := "foo",
        publishArtifact := false
      ).
      aggregate(a, b)
    

    在上文中,kind := Kind.App设置的范围是项目a。所以这会在字面上回答你的问题。

      

    sbt会抱怨在根项目中没有定义类型。

    这部分我不清楚发生了什么。加载构建时会发生这种情况吗?或者当你在sbt shell中输入kind时会发生什么?如果您在启动时看到它可能意味着您有一个尝试依赖kind密钥的任务/设置。请勿加载设置,或重新实现设置,以免使用kind

    避免此问题的另一种方法可能是放弃使用根聚合。切换到子项目并运行任务或使用ScopeFilter构建显式聚合。

答案 1 :(得分:0)

我最终通过利用derive创建DerivedSetting的方法来实现这一目标。然后,sbt 将在定义其依赖项的每个范围内自动扩展这些设置

因此我现在可以将我的插件编写为:

object P extends Plugin {
    val kind = settingKey[Kind]("App or Lib?")
    val ourResolver = settingKey[Resolver]("...")

    def derivedSettings = Seq(
        // I want this to only be defined in a and b, where `kind` is defined
        ourResolver <<= kind { k => new OurInternalResolver(k) }
    ) map (s => Def.derive(s, trigger = _ != streams.key))

    override def projectSettings = derivedSettings ++ Seq( /* other stuff */ )
}

如果我在kinda的{​​{1}}中定义b,那么build.sbt也将最终在这些范围内定义。