覆盖sbt依赖解析机制(并防止jar地狱)

时间:2014-05-19 14:02:28

标签: scala dependencies sbt dependency-management

我们有一个大型多项目,我们使用sbt构建了许多模块。事实证明,我们有很多关于被包装的不需要的罐子的问题。作为解决问题的第一步,我们创建了一个全球地图"使用过的工件的定义如下:

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.")
root中的

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的解析机制会经历它&#34;通过它&#34;它可能会改变所要求的依赖性。

例如,让我们说logbackslf4j-api一起使用,我想要log4j或{{1}的传递依赖要添加到类路径中,而是添加到commons-logging之类的桥。像上面这样的地图可以解决这个问题。 另外,不会加载不同的版本。以及任何可能已更改其名称的工件(如jcl-over-slf4j,现在称为google-collectionsguava groupID已更改为org.jboss.netty)赢得了&#39;是一个问题。

当然,只要给出的依赖关系不是所要求的依赖关系,就应该在屏幕上打印一个警告,并且每当添加新的依赖关系时,用户都应该手动将其添加到地图中并具有所有它的传递依赖关系。还没有(或者会引发匹配错误)

所以我的问题是,有可能实现这样的目标吗? 如果是这样,怎么样?

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

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

1 个答案:

答案 0 :(得分:0)

我从未使用它,但您可以试用sbt-one-log,也许可以将它作为您尝试解决的其他事情的起点。