【问题标题】:Conditional setting in SBT projectSBT项目中的条件设置
【发布时间】:2019-01-02 12:27:14
【问题描述】:

我在 SBT (1.1.6) 中有一个多模块项目。

我的示例模块定义:

lazy val `example` = (project in file("example"))
  .settings(
    scalaVersion := "2.11.12",
    crossScalaVersions := Seq("2.10.7", "2.11.12"),
    libraryDependencies ++= Seq( ... )
  )

现在我的意图是禁用2.11 jar 的发布,设置:

lazy val dontPublish: Seq[Def.Setting[_]] = Seq(
  publish := {},
  publishLocal := {},
  publishM2 := {},
  publishArtifact := false,
  publishTo := None
).flatten

我可以阻止所有的情况,所以我希望一些简单的事情,比如:

lazy val `example` = (project in file("example"))
  .settings(
    scalaVersion := "2.11.12",
    crossScalaVersions := Seq("2.10.7", "2.11.12"),
    (if (scalaBinaryVersion.value == "2.11") dontPublish else Seq.empty),
    libraryDependencies ++= Seq( ... )
  )

可以工作,但是...我收到一个错误:

/path/build.sbt:371: error: `value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.
(if (scalaBinaryVersion.value == "2.11") dontPublish else Seq.empty).flatten,
^
[error] sbt.compiler.EvalException: Type error in expression

问题:

如何根据条件(例如,Scala 版本)添加设置?

【问题讨论】:

标签: scala sbt


【解决方案1】:

我最终适应了https://gist.github.com/joescii/4431cb2185eddb699dfb79b9c910e333SBT 1.1.6

我的解决方案:

val neverPublish = dontPublishIf(scalaVersion)(_ => true)

def dontPublishIf[P](key: SettingKey[P])(p: P => Boolean): Seq[Def.Setting[_]] = {
  Seq(
    //@formatter:off
    skip in publish      := p(key.value),
    skip in publishLocal := p(key.value),
    skip in publishM2    := p(key.value)
    //@formatter:on
  ) ++ dontPublishAssemblyIf(key)(p)
}

def isAssemblyArtifact(a: Artifact): Boolean =
  a.classifier.contains("assembly")

def dontPublishAssemblyIf[P](key: SettingKey[P])(p: P => Boolean): Seq[Def.Setting[_]] = {
  Seq(
    // remove added assembly artifacts and publishTasks
    //@formatter:off
    artifacts         := artifacts        .value.filterNot {       a     => p(key.value) && isAssemblyArtifact(a) },
    packagedArtifacts := packagedArtifacts.value.filterNot { case (a, _) => p(key.value) && isAssemblyArtifact(a) }
    //@formatter:on
  )
}

我很惊讶 SBT 真的这么难用,但在这次冒险中,我对它的内部有了更多的了解。

如果有人遇到类似问题,我只是发布。

【讨论】:

    【解决方案2】:

    无论如何我都不是 SBT 专家,但我最近遇到了一个类似的问题,我通过将所有不是很简单的语句从 build.sbt 移到 project/MySettings.scala 来解决这个问题。 .sbt 文件的解析规则不断让我感到困惑,但在 .scala 文件中它只是常规的 scala。所以你会有类似的东西

    object MySettings {
      val dontPublish: Seq[Def.Setting[_]] = Seq(
        publish := {},
        publishLocal := {},
        publishM2 := {},
        publishArtifact := false,
        publishTo := None
      ).flatten
    
      val maybeDontPublish = if (scalaBinaryVersion.value == "2.11") dontPublish else Seq.empty
    }
    

    然后在你的build.sbt:

    lazy val `example` = (project in file("example"))
      .settings(
        scalaVersion := "2.11.12",
        crossScalaVersions := Seq("2.10.7", "2.11.12"),
        MySettings.maybeDontPublish,
        libraryDependencies ++= Seq( ... )
      )
    

    您可能还需要将scalaVersioncrossScalaVersion 拉到MySettings.scala 中,我不完全确定,因为它们是半魔法的。或者可能将MySettings.maybeDontPublish 更改为def maybeDontPublish(scalaVersion: String): Seq[Setting]

    【讨论】:

      【解决方案3】:

      如错误所示,您只能访问任务或设置宏中的value。你可以通过添加设置skip in publish := scalaBinaryVersion.value == "2.11"来完成你想要的。

      【讨论】:

      • 其实我也想跳过publishLocalpublishM2等...有没有办法将多个设置封装到一个条件中?
      • 我不相信在一个条件下可以做到(尽管我很高兴被证明是错误的)。
      猜你喜欢
      • 1970-01-01
      • 2018-04-09
      • 2018-08-21
      • 1970-01-01
      • 2014-06-05
      • 1970-01-01
      • 2016-09-20
      • 2011-09-06
      • 2019-01-23
      相关资源
      最近更新 更多