SBT项目中的条件设置

时间:2018-07-25 15:49:17

标签: scala sbt

我在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版本)添加设置?

3 个答案:

答案 0 :(得分:1)

如错误所示,您只能进入任务或设置宏内的value。您可以通过添加设置skip in publish := scalaBinaryVersion.value == "2.11"来完成自己的工作。

答案 1 :(得分:0)

我最终适应了https://gist.github.com/joescii/4431cb2185eddb699dfb79b9c910e333  到SBT 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 :(得分:0)

无论如何我都不是SBT专家,但是最近我遇到了类似的问题,我通过将不是很简单的语句的所有内容从build.sbt移到project/MySettings.scala来解决了这个问题。 .sbt文件的解析规则不断使我感到困惑,但是在.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]