Scala crossCompile项目中如何按scalaVersion配置依赖与插件版本
按Scala版本动态配置依赖的实现方案
报错原因
addCompilerPlugin默认接收静态依赖坐标,直接在其参数中调用.value时,脱离了sbt要求的设置/任务宏上下文,因此触发错误。libraryDependencies ++= 本身是sbt的设置赋值宏,在其右侧调用.value符合语法要求,所以之前的普通依赖配置可以正常运行。
简洁实现方式
你期望的Map格式版本映射可以按如下方式实现,无需额外定义Def.setting包装层,同时解决编译器插件的配置报错:
1. 定义版本映射表
建议优先使用Scala二进制版本作为映射键,后续升级Scala小版本无需修改映射规则:
scalaVersion := "2.11.12" crossScalaVersions := Seq("2.11.12", "2.12.14") // 可根据需求替换为全Scala版本作为键 val depVersionMap = Map( "2.11" -> Map( "circe" -> "0.12.0-M3", "kindProjector" -> "0.10.3" ), "2.12" -> Map( "circe" -> "0.14.1", "kindProjector" -> "0.13.2" ) )
2. 配置普通依赖
直接在libraryDependencies中读取映射表即可:
libraryDependencies ++= Seq( "io.circe" %% "circe-core" % depVersionMap(scalaBinaryVersion.value)("circe") )
3. 配置编译器插件
改用compilerPlugin方法标记依赖属性,放在libraryDependencies +=的设置上下文内,即可合法调用.value读取动态版本:
libraryDependencies += compilerPlugin( "org.typelevel" %% "kind-projector" % depVersionMap(scalaBinaryVersion.value)("kindProjector") )
注意事项
sbt的设置值(如scalaVersion、scalaBinaryVersion)均为惰性加载,无法在顶层静态代码(非设置/任务上下文)中读取其运行时值。所有依赖这些动态值的逻辑,都必须放在:=/+=/++=等设置赋值操作的右侧,或者Def.setting/Def.task的定义内部。
如果需要兼容未定义版本的Scala环境,可通过getOrElse增加容错处理:
depVersionMap.getOrElse( scalaBinaryVersion.value, sys.error(s"未找到Scala ${scalaBinaryVersion.value} 对应的依赖版本") )("circe")
内容的提问来源于stack exchange,提问作者Mehdi
相关产品推荐
相关产品推荐

