如何从sbt程序集中排除重复的类?

时间:2014-06-23 10:12:28

标签: sbt sbt-assembly

我们的情况是两个依赖项具有完全相同的类(因为其中一个依赖项复制了它并包含在它们自己的源中)。

这导致sbt assembly无法通过重复数据删除检查。

如何从特定的jar中排除某个类?

3 个答案:

答案 0 :(得分:18)

您需要mergeStrategy,其中包含其中一个文件。

mergeStrategy in assembly := {
    case PathList("path", "to", "your", "DuplicatedClass.class") => MergeStrategy.first
    case x => (mergeStrategy in assembly).value(x)
}

更新

如果你想根据它来自的JAR来处理文件,我认为你不能使用程序集插件定义的合并策略。您可以做什么,您可以定义自己的策略。

我会改变你的状况。我认为问题应该是“如何从特定的JAR中包含一个类?”。原因是可以有两个以上的JAR具有相同的类,并且最后只能包含一个。

您可以使用AssemblyUtils.sourceOfFileForMerge来判断文件的来源。

project/IncludeFromJar.scala

import sbtassembly._
import java.io.File
import sbtassembly.Plugin.MergeStrategy

class IncludeFromJar(val jarName: String) extends MergeStrategy {

  val name = "includeFromJar"

  def apply(args: (File, String, Seq[File])): Either[String, Seq[(File, String)]] = {
    val (tmp, path, files) = args
    val includedFiles = files.flatMap { f =>
      val (source, _, _, isFromJar) = sbtassembly.AssemblyUtils.sourceOfFileForMerge(tmp, f)
      if(isFromJar && source.getName == jarName) Some(f -> path) else None
    }
    Right(includedFiles)
  }

}

build.sbt

mergeStrategy in assembly := {
    case PathList("path", "to", "your", "DuplicatedClass.class") => new IncludeFromJar("jarname.jar")
    case x => (mergeStrategy in assembly).value(x)
}

答案 1 :(得分:1)

您正在使用什么版本的sbtassembly? 我相信我使用的是其他版本(0.14.2),因为我在使用project / IncludeFromJar.scala时遇到了错误。

编译时出现以下错误:

method apply cannot override final member
def apply(args: (File, String, Seq[File])): Either[String, Seq[(File, String)]] = {
^  

在进一步调查中,我发现sbtassembly.MergeStrategy的{​​{1}}方法是最终的方法。因此,即使在apply

中指定IncludeFromJarapply的{​​{1}}方法也不能覆盖sbtassembly.MergeStrategy

谢谢:)

答案 2 :(得分:1)

讨论可能有点晚了,但是可以帮助发现它的其他人:

扩展MergeStrategy时,您想覆盖带有签名的方法:

 def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]]

以tuple参数结尾的apply方法将调用带有如上所述拆分出的参数的apply

https://github.com/sbt/sbt-assembly/blob/edd35cfbaf05c3465371b63d38fda8ac579d766c/src/main/scala/sbtassembly/MergeStrategy.scala#L19

因此示例变为:

def includeFromJar(val jarName: String): sbtassembly.MergeStrategy = new sbtassembly.MergeStrategy {

  val name = "includeFromJar"

  def apply(tmp: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]] = {
    val includedFiles = files.flatMap { f =>
      val (source, _, _, isFromJar) = sbtassembly.AssemblyUtils.sourceOfFileForMerge(tmp, f)
      if(isFromJar && source.getName == jarName) Some(f -> path) else None
    }
    Right(includedFiles)
  }
}

mergeStrategy in assembly := {
    case PathList("path", "to", "your", "DuplicatedClass.class") => includeFromJar("jarname.jar")
    case x => (mergeStrategy in assembly).value(x)
}