使用宏天堂并与2.12 / 2.13交叉编译

时间:2019-01-27 19:52:32

标签: sbt

从Scala 2.13开始,macro-paradise已在编译器中内联,可通过编译器标志使用:

Compile / scalacOptions += "-Ymacro-annotations"

作为参考,在早期的Scala版本中,宏天堂可通过编译器插件获得:

addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)

在针对Scala 2.12和2.13的构建中,根据Scala版本的值,有条件地添加第一个设置或第二个设置的规范方法是什么?

我想写以下内容,但不起作用:

CrossVersion.partialVersion(scalaVersion.value) match {
  case Some((2, n)) if n >= 13 => Compile / scalacOptions += "-Ymacro-annotations"
  case _ => addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)
}

它失败并出现以下错误:

error: `value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.
      CrossVersion.partialVersion(scalaVersion.value) match {
                                               ^

同时,我可以使用以下解决方法,但希望支持更简单的解决方案:

Compile / scalacOptions ++= {
  CrossVersion.partialVersion(scalaVersion.value) match {
    case Some((2, n)) if n >= 13 => "-Ymacro-annotations" :: Nil
    case _ => Nil
  }
}

libraryDependencies ++= {
  CrossVersion.partialVersion(scalaVersion.value) match {
    case Some((2, n)) if n >= 13 => Nil
    case _ => compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full) :: Nil
  }
}

2 个答案:

答案 0 :(得分:2)

如果你想写

CrossVersion.partialVersion(scalaVersion.value) match {
  case Some((2, n)) if n >= 13 => Compile / scalacOptions += "-Ymacro-annotations"
  case _ => addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" % cross CrossVersion.full)
}

一个选项像这样定义SBT custom command

def compileWithMacroParadise: Command = Command.command("compileWithMacroParadise") { state =>
  import Project._
  val extractedState = extract(state)
  val stateWithMacroParadise = CrossVersion.partialVersion(extractedState.get(scalaVersion)) match {
    case Some((2, n)) if n >= 13 => extractedState.appendWithSession(Seq(Compile / scalacOptions += "-Ymacro-annotations"), state)
    case _ => extractedState.appendWithSession(addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full), state)
  }
  val (stateAfterCompileWithMacroParadise, _) = extract(stateWithMacroParadise).runTask(Compile / compile, stateWithMacroParadise)
  stateAfterCompileWithMacroParadise
}

commands ++= Seq(compileWithMacroParadise),
addCommandAlias("compile", "compileWithMacroParadise")

sbt compile现在应该在运行stateWithMacroParadise任务之前对构建状态(compile)进行适当的修改。

答案 1 :(得分:0)

完整的示例,添加到您的projects目录

import sbt._
import sbt.Keys._

object Compiler extends AutoPlugin {
  override def trigger = allRequirements

  override def projectSettings: Seq[Def.Setting[_]] =
    Seq(
      libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match {
        case Some((2, x)) if x < 13 =>
          Seq(
            compilerPlugin(("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)),
            "org.scala-lang.modules" %% "scala-collection-compat" % "2.1.6"
          )
        case _ => Nil
      }),
      Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value) match {
        case Some((2, x)) if x >= 13 =>
          Seq("-Ymacro-annotations")
        case _ => Nil
      })
    )

}

请注意,您必须使用projectSettingsbuildSettings无法使用

"scala-collection-compat"依赖项是交叉编译2.12和2.13时通常需要的依赖项。让你做吧

import scala.jdk.CollectionConverters._

代替使用不推荐使用的scala.collection.JavaConverters