如何在sbt中为自定义Scala编译器插件配置依赖?
这个问题我之前也碰到过——编译器插件是运行在Scala编译器的进程里的,你加到libraryDependencies里的Kryo只会被你的插件项目本身使用,并不会被自动加入到编译器的类路径中,所以才会出现NoClassDefFoundError。给你两个靠谱的解决方案:
方案1:把Kryo打包进插件的Fat Jar里
这种方法最省心,让插件自己包含所有依赖,目标项目不用额外配置依赖。步骤如下:
- 先在插件项目的
project/plugins.sbt里添加sbt-assembly插件,用来构建Fat Jar:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0")
- 回到插件项目的顶层
build.sbt,添加assembly的配置:
lazy val root = (project in file(".")) .settings( // 保留你原来的配置 libraryDependencies ++= commonDependencies, Test / parallelExecution := false, // 配置assembly的合并策略,避免META-INF文件冲突 assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case _ => MergeStrategy.first }, // 可选:自定义Fat Jar的名称,方便识别 assemblyJarName in assembly := s"${name.value}-${version.value}-assembly.jar" )
- 运行
sbt assembly构建Fat Jar,之后把这个Jar作为编译器插件引入到目标项目里就行(如果发布到maven仓库,直接引用这个带依赖的Jar版本也可以)。
方案2:在目标项目里手动把Kryo加到编译器类路径
如果你不想打包Fat Jar,也可以在使用插件的目标项目里,手动把Kryo的依赖加入编译器的类路径:
// 先添加你的编译器插件 addCompilerPlugin("你的插件groupId" %% "你的插件artifactId" % "插件版本") // 添加Kryo依赖 libraryDependencies += "com.esotericsoftware" % "kryo" % "5.0.0-RC9" // 把Kryo Jar加入编译器的类路径 scalacOptions ++= { // 从编译类路径中找到Kryo的Jar文件 val kryoJar = (updateClasspath in Compile).value.find(_.getName.contains("kryo-5.0.0-RC9")).get Seq(s"-J-cp:${kryoJar.getAbsolutePath}") }
或者用更简洁的方式,借助sbt的scalacPluginClasspath:
libraryDependencies += "com.esotericsoftware" % "kryo" % "5.0.0-RC9" scalacPluginClasspath ++= (dependencyClasspath in Compile).value.filter(_.getName.contains("kryo"))
最后再提醒一句:开发插件的时候,Kryo的依赖要保持Compile范围,这样你的插件代码才能正常编译。核心问题就是编译器插件的运行环境是Scala编译器进程,它的类路径和普通应用的类路径是分开的,所以得单独处理依赖~
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

