scala - 覆盖 sbt 依赖解析机制(并防止 jar hell)

标签 scala dependencies sbt dependency-management

我们有一个大型的多项目,其中有许多我们使用 sbt 构建的模块。事实证明,我们有很多关于打包不需要的 jar 的问题。作为处理该问题的第一步,我们创建了一个已用工件的“全局 map ”,其定义如下:

project/Build.scala:

type PartialFunction2[-T1,-T2,+R] = PartialFunction[Tuple2[T1,T2],R]

lazy val dependenciesManager = settingKey[PartialFunction2[String, String, ModuleID]]("a setting containing versions for dependencies. if we only use it to declare dependencies, we can avoid a lot of version collisions.")

build.sbt 根目录:

dependenciesManager in Global := {
  case ("ch.qos.logback","logback-classic")  => "ch.qos.logback" % "logback-classic" % "1.1.1"
  case ("com.typesafe","config")             => "com.typesafe" % "config" % "1.2.0"
  case ("com.typesafe","scalalogging-slf4j") => "com.typesafe" %% "scalalogging-slf4j" % "1.1.0"
  case ("com.typesafe.akka",art)             => "com.typesafe.akka" %% art % "2.2.4"
  case ("com.typesafe.play", art)            => "com.typesafe.play" %% art % "2.2.3"
  ...
}

这允许我们在任何模块自己的 build.sbt 文件中使用以下语法:

libraryDependencies <++= (dependenciesManager)(dm => Seq(
  dm("com.typesafe.akka","akka-cluster"),
  dm("com.typesafe.akka","akka-contrib"),
  dm("com.typesafe.play","play"),
  dm("ch.qos.logback","logback-classic")
))

其中没有提到依赖版本。 但是,由于传递依赖仍然会导致问题,它只解决了部分问题。

所以我在想,如果我能以某种方式定义一个像上面那样的依赖关系映射,sbt 的解析机制将“通过它”并且它可能会改变所要求的依赖关系。

例如,假设我正在使用 logbackslf4j-api,我不想要 log4j 的传递依赖或commons-logging 被添加到类路径中,而是像 jcl-over-slf4j 这样的桥。像上面那样的 map 可以解决这个问题。 此外,不会加载不同的版本。以及任何可能已更改其名称的工件(例如 google-collections 现在称为 guavaorg.jboss.netty 已更改的 groupID到 io.netty) 将不是问题。

当然,只要给定的依赖项不是所要求的,就应该在屏幕上打印一条警告,并且无论何时添加新的依赖项,用户都应该手动将它添加到 map 中,并包含所有不存在的传递依赖项yet(否则会抛出匹配错误)

所以我的问题是,是否有可能实现类似的目标? 如果是,怎么办?

目前关于如何解决这个问题的想法:

  • 修改 ivyReport 任务或 update 任务:据我了解,sbt 创建了一个 IvyReport xml 文件,根据这个文件, ivy 获取请求的工件。我想以某种方式修改 update任务或生成的报告,因此传递依赖项将是我想要的,而不是最初获取的依赖项。
  • 使用类似于我们已有的解决方案:仅将映射中的所有 ModuleID 标记为 intransitive(),但是(以某种方式)获取它们的依赖项,并获取它们(在映射到想要的工件之后)

最佳答案

我没用过,但你可以试试sbt-one-log并可能将其用作您要解决的其他问题的起点。

关于scala - 覆盖 sbt 依赖解析机制(并防止 jar hell),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23739836/

相关文章:

scala - Akka IO 应用占用 100% CPU

java - 使用ScalaCheck生成没有构造函数参数的对象

javascript - node.js TypeError : path must be absolute or specify root to res. sendFile [无法解析JSON]

scala - org.apache.arrow 的 sbt-assembly 重复数据删除错误

sbt - 当构建中没有定义默认值时,在命令行上设置设置值?

用于删除所有未使用代码的 Scala 工具

scala - 使用sbt-assembly将供应商信息添加到MANIFEST.MF

java - 从 Gradle 导入项目时 IntelliJ 中的依赖项错误

android - 即使targeSdkVersoin的版本与24相同,Gradle appcompat-v7也会出现错误?

scala - 如何证明Scala中的爆炸原理(ex falso sequitur quodlibet)?