Как исключить дублирующийся класс из сборки sbt?
У нас есть ситуация, когда две зависимости имеют один и тот же класс (потому что одна из зависимостей скопировала его и включила в свой собственный источник).
Это вызывает sbt assembly
провалить свои проверки дедупликации.
Как я могу исключить класс из определенной банки?
2 ответа
Тебе необходимо mergeStrategy
, который займет один из файлов.
mergeStrategy in assembly := {
case PathList("path", "to", "your", "DuplicatedClass.class") => MergeStrategy.first
case x => (mergeStrategy in assembly).value(x)
}
Обновить
Если вы хотите обрабатывать файл в зависимости от 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)
}
Какая версия sbtassembly
вы используете? Я считаю, что я использую другую версию (0.14.2), потому что я получаю ошибку, используя use project / IncludeFromJar.scala.
При компиляции я получаю следующую ошибку:
method apply cannot override final member
def apply(args: (File, String, Seq[File])): Either[String, Seq[(File, String)]] = {
^
После дальнейшего расследования я узнал, что sbtassembly.MergeStrategy
"s apply
метод является окончательным. Следовательно, IncludeFromJar
"s apply
метод не может переопределить sbtassembly.MergeStrategy
даже с указанием override def apply
в IncludeFromJar
Спасибо:)
Возможно, немного поздно для обсуждения, но чтобы помочь другим, которые это нашли:
когда вы расширяете MergeStrategy, вы хотите переопределить метод apply с подписью:
def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]]
Метод apply, который завершается с аргументом кортежа, вызывает метод apply с разделенными параметрами, как указано выше.
Таким образом, пример становится:
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)
}