Как я могу принудительно использовать класс из определенного jar-файла и исключить тот же класс другого jar-файла в build.sbt?

У меня два asm зависимости, которые имеют одинаковые имена классов и структуры проекта, включенные в разные зависимости. Хотя эти библиотеки имеют одинаковую структуру проекта, они имеют разные координаты Maven. Поэтому переопределение зависимости не будет работать.

Одна из моих зависимостей (jnr-ffi) использует org.objectweb.asm.ClassVisitor учебный класс. В "org.objectweb" % "asm" % "3.3.1", org.objectweb.asm.ClassVisitor Интерфейс, и это выдает ошибку. Мне нужно использовать "org.ow2.asm" % "asm" % "5.0.3" Реализация org.objectweb.asm.ClassVisitor потому что это фактический класс. Банки обеих реализаций загружаются в ~/.ivy2/cache, К сожалению, тот, который мне нужен, не используется, учитывая мои стратегии слияния.

Выдается следующая ошибка:

Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.ClassVisitor, but class was expected
at jnr.ffi.provider.jffi.AsmLibraryLoader.generateInterfaceImpl(AsmLibraryLoader.java:104)
at jnr.ffi.provider.jffi.AsmLibraryLoader.loadLibrary(AsmLibraryLoader.java:89)
at jnr.ffi.provider.jffi.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:43)
at jnr.ffi.LibraryLoader.load(LibraryLoader.java:325)
at jnr.unixsocket.Native.<clinit>(Native.java:80)
at jnr.unixsocket.UnixSocketChannel.<init>(UnixSocketChannel.java:101)
at jnr.unixsocket.UnixSocketChannel.open(UnixSocketChannel.java:65)

я использую sbt 0,13,5 и sbt assembly 0.14.2 .

Я пытался исключить "org.objectweb" % "asm" % "3.3.1", Это не сработало:

libraryDependencies ++= Seq(. . .).map(_.exclude("org.objectweb" % "asm" % "3.3.1"))

Я также попытался использовать следующие стратегии слияния

    assemblyMergeStrategy in assembly := {
      case PathList("asm-3.2.jar") => MergeStrategy.discard
      case PathList(ps @ _*) if ps.last endsWith ".asm-3.2.jar" => MergeStrategy.discard
      case PathList("asm-5.0.3.jar") => MergeStrategy.first
      case PathList(ps @ _*) if ps.last endsWith ".asm-5.0.3.jar" => MergeStrategy.first
      case PathList("META-INF", xs @ _*) => MergeStrategy.discard
      case x => MergeStrategy.first
    }

Я также пытался исключить банку:

    assemblyExcludedJars in assembly := {
      val cp = (fullClasspath in assembly).value
      cp filter {_.data.getName == "asm-3.2.jar"}
    }

Я также пытался реализовать собственную стратегию слияния project/IncludeFromJar.scala из "Как можно исключить дублирующийся класс из сборки sbt?", Но IncludeFromJar.scala не скомпилируется, и я верю, потому что я использую неправильную версию sbt assembly для их примера.

case PathList("org", "objectweb", "asm", "ClassVisitor.class") => new IncludeFromJar("asm-5.0.3.jar")

Отсюда вопрос: как я могу принудительно использовать класс из определенного jar-файла и исключить тот же класс другого jar-файла в build.sbt?

0 ответов

Недавно я столкнулся с подобной проблемой. Решение, которое я нашел, заключалось в использовании затенения зависимостей для сборки. Вот настройки, которые я использовал в своемbuild.sbt файл.

assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("org.objectweb.asm.**" -> "asm503.@1").inLibrary(
    "org.ow2.asm" % "asm" % "5.0.3"
  ).inLibrary(
    "org.ow2.asm" % "asm-tree" % "5.0.3"
  ).inLibrary(
    "org.ow2.asm" % "asm-analysis" % "5.0.3"
  ).inLibrary(
    "org.ow2.asm" % "asm-commons" % "5.0.3"
  ).inLibrary(
    "org.ow2.asm" % "asm-util" % "5.0.3"
  ).inLibrary(
    "com.github.jnr" % "jnr-ffi" % "2.1.9"
  ).inProject // For your own code
)

В .inProject заявление также затеняет ваш собственный импорт (при необходимости).

Я знаю, что тема старая, но это может кому-то помочь.

Другие вопросы по тегам