4

假设我正在编写一个 Scala 库 L,它依赖于某个依赖项 D,并由一个程序 P 和另一个程序 Q 使用。P 直接依赖于 D 的 3.2 版,而 Q 直接依赖于 3.3 版。

在这两个版本之间,D 的 API 被打乱,以便获得我在 L 中使用的相同函数,我必须在 L 中编写不同的导入语句。同样,P 依赖于 3.2 特定的行为,而 Q 依赖于 3.3 特定的行为。

现在,通常会发生的是,在编译 P 和 Q 时将选择 D 的最新版本,但这将导致如果 L 依赖于库的 3.3 版,则 P 中断,或者如果 L 依赖于编译 Q,则 L 在编译 Q 时中断在 D 的 3.2 版上。

理想情况下,我希望 P 和 Q 都使用相同版本的 L,因为 L 的公共 API 不会改变。这可能吗?

想到的一般方法是基于依赖解析的L的条件编译。尽管在 JVM 世界中这似乎是无法实现的,因为我们不会传递地编译项目的依赖项,而是依赖于预编译的工件。

如果 D 是 Scala 本身,我现在可以使用 SBT 执行此操作(即与不同的 Scala 版本进行交叉编译,并将特定于版本的代码存在于自己的目录中),但从依赖解析的角度来看,这是一种 hack,因为 SBT 发生了变化工件的名称以允许此交叉编译工作。

4

1 回答 1

4

您可以告诉 sbt 将依赖项处理为intransitive

libraryDependencies ++= Seq(
  "org.some.id" % "some-lib" % "1.0.foobar" intransitive()
)

会将 some-lib 添加到依赖项中,但不会遵循该 lib 的依赖项。因此,如果对其他库some-lib有依赖项,则some-other-lib不会下载。

也许更具体一点。比如说,你需要几个库都使用 SLF4J 作为日志接口。也许,一些库需要稍微不同的版本,但没有任何 API 差异。所以他们都可以使用相同的 SLF4J 版本。然后,您会将所有这些 libraryDependencies 标记为不及物,并将 SLF4J 本身添加一次作为顶级库依赖项。

libraryDependencies ++= Seq(
 "org.slf4j" % "slf4j-api" % 1.7.6,
 "com.typesage.slick" %% "slick" % "2.0.0" intransitive(),
 "com.typesafe.akka" %% "akka-slf4j" % "2.2.0" intransitive()
)

我说得有道理吗?

于 2015-07-22T17:51:55.417 回答