【发布时间】:2017-12-16 01:13:54
【问题描述】:
我在 Scala 中使用了一个库 A,它依赖于另一个库 Z 的 x.11 版本。
现在,我也在使用一个库 B,它依赖于 Z 的 x.31 版本。
这会导致编译错误,因为我们将有两个版本的库 Z,如何在 scala 的 sbt 中同时使用库 A 和 B?有没有办法指定呢。
【问题讨论】:
-
您可能会为此使用阴影:asyncified.io/2016/04/07/…
我在 Scala 中使用了一个库 A,它依赖于另一个库 Z 的 x.11 版本。
现在,我也在使用一个库 B,它依赖于 Z 的 x.31 版本。
这会导致编译错误,因为我们将有两个版本的库 Z,如何在 scala 的 sbt 中同时使用库 A 和 B?有没有办法指定呢。
【问题讨论】:
如果用较新版本完全替换一个依赖项恰好可行,则 Sparko 的解决方案有效。但是,情况并非总是如此。
如果您想在 sbt-assembly 生成的 uber-jar 中包含两个版本的库,则需要使用着色。请参阅 this post 了解什么是着色以及与之相关的一些缺点的概述。
在 sbt-assembly 的文档 here 中介绍了阴影,但如果你和我一样,他们解释它的方式会让你比开始时更加困惑。有一篇很好的博文,Spark, Uber Jars and Shading with sbt-assembly (waybackmachine link),有助于揭开它的神秘面纱。以下是相关部分:
我可以遮盖我的类型安全配置版本,给它一个不同的 名称以便 Spark 不会在版本之间混淆。我赶紧去了 到我的 build.sbt 文件中,并添加以下代码:
程序集中的assemblyShadeRules := Seq(
ShadeRule.rename("com.typesafe.config.**" -> "my_conf.@1") .inLibrary("com.typesafe" % "config" % "1.3.0") .inProject)根据文档,这应该将任何类放在 com.typesafe.config 在新包 my_conf 下。
对于您的情况,解决方案是将这样的内容添加到您的 build.sbt 文件中:
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("com.somecompany.**" -> "my_conf.@1")
.inLibrary("com.somecompany" % "libraryZ" % "0.11")
.inProject
)
【讨论】:
com.somecompany.** 是否应该引用库 A?
在 sbt 中,库之间的冲突是使用冲突管理器配置的。默认情况下,会选择最新版本,但也可以在您的 .sbt 文件中覆盖:
conflictManager := ConflictManager.strict
如果您使用的是 sbt 0.13.6 或更高版本,当您的依赖项之间的二进制版本不兼容时,您会收到警告。在这种情况下,您可以在 sbt 文件中为特定库配置覆盖:
dependencyOverrides += "org.raman" % "Z" % "x.11"
这将强制Z 的解析版本为x.11,但不会直接引入依赖。
【讨论】: