Создание библиотеки aspectJ с использованием sbt-aspect

Я в процессе написания библиотеки, которая выполняет мониторинг /OpenTracing, и я пытаюсь использовать sbt-aspectj, чтобы пользователям библиотеки не нужно было вручную инструментировать свой код. Однако в настоящее время у меня возникает проблема с созданием sbt-проекта, представляющего такую ​​библиотеку.

Идея состоит в том, что мне нужна внешняя библиотека, как указано в этом примере здесь https://github.com/sbt/sbt-aspectj/tree/master/src/sbt-test/weave/external, однако эта внешняя библиотека зависит от внешняя зависимость (т.е.akka-actors). В основном я пытаюсь объединить https://github.com/sbt/sbt-aspectj/tree/master/src/sbt-test/weave/external и https://github.com/sbt/sbt-aspectj/tree/master/src/sbt-test/weave/jar. Я создал здесь образец проекта https://github.com/mdedetrich/sbt-aspectj-issue, чтобы указать на проблему, с которой я столкнулся, однако ниже приведен соответствующий образец

lazy val root = (project in file("."))
  .enablePlugins(SbtAspectj)
  .settings(
    name := RootName,
    version := Version,
    // add akka-actor as an aspectj input (find it in the update report)
//    aspectjInputs in Aspectj ++= update.value.matching(
//      moduleFilter(organization = "com.typesafe.akka", name = "akka-actor*")),
    // replace the original akka-actor jar with the instrumented classes in runtime
//    fullClasspath in Runtime := aspectjUseInstrumentedClasses(Runtime).value,
    // only compile the aspects (no weaving)
    aspectjCompileOnly in Aspectj := true,
    // ignore warnings (we don't have the target classes at this point)
    aspectjLintProperties in Aspectj += "invalidAbsoluteTypeName = ignore",
    // replace regular products with compiled aspects
    products in Compile ++= (products in Aspectj).value,
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-actor" % akkaVersion
    )
  )

lazy val test = (project in file("test"))
  .enablePlugins(SbtAspectj)
  .settings(
    aspectjBinaries in Aspectj ++= update.value.matching(
      moduleFilter(organization = Organization, name = s"$RootName*")),
    aspectjInputs in Aspectj ++= update.value.matching(
      moduleFilter(organization = "com.typesafe.akka", name = "akka-actor*")),
    fullClasspath in Runtime := aspectjUseInstrumentedClasses(Runtime).value,
    // weave this project's classes
    aspectjInputs in Aspectj += (aspectjCompiledClasses in Aspectj).value,
    products in Compile := (products in Aspectj).value,
    products in Runtime := (products in Compile).value,
    libraryDependencies ++= Seq(
      Organization %% RootName % Version
    )
  )

Идея в том, что мы публикуем root проект с использованием root/publishLocal и тестовый проект просто предназначен для включения root как libraryDependency так что мы можем видеть, правильно ли работает аспект-j.

Проблема проста в том, что я не могу заставить ее работать. Текущий код на https://github.com/mdedetrich/sbt-aspectj-issue публикуется сroot/publishLocal (не уверен, что это правильно), но когда я тогда сделаю test/run Я понял это

[info] Weaving 2 inputs with 1 AspectJ binary to /home/mdedetrich/github/sbt-aspectj-issue/test/target/scala-2.13/aspectj/classes...
[error] stack trace is suppressed; run last test / Compile / packageBin for the full output
[error] (test / Compile / packageBin) java.util.zip.ZipException: duplicate entry: META-INF/MANIFEST.MF
[error] Total time: 1 s, completed Dec 29, 2019 4:31:27 PM
sbt:sbt-aspectj-issue> 

Кажется, проблема с дублированием akka-actorзаписи. Я пробовал переключать различные записи вbuild.sbt но не удалось заставить его работать.

РЕДАКТИРОВАТЬ: это также было опубликовано как проблема github здесь https://github.com/sbt/sbt-aspectj/issues/44

1 ответ

Как правило, вы можете исключить META-INF каталоги из внешних библиотек сотканы.

mappings in (Compile, packageBin) := {
    (mappings in (Compile, packageBin)).value
        .filterNot(_._2.startsWith("META-INF/"))
}

Но для библиотек акка есть другая проблема. В каждой библиотеке akka естьreference.conf, который содержит резервную конфигурацию для предоставленных функций. Это также приведет к конфликтам, таким какMETA-INFсделал. Но его нельзя просто исключить, какMETA-INF, потому что они необходимы для правильной работы акка.

Если вы исключите их, вам нужно будет предоставить все необходимые конфигурации akka в вашем application.conf, или объединенный (а не просто объединенный) reference.confв вашем проекте. Это нетривиально и зависит от версии акка.

Другим решением было бы переплетать и переупаковывать библиотеки akka по отдельности, поэтому reference.confможно хранить в переупакованных библиотеках. Макет проекта и сценарий сборки будут немного сложнее, но их будет легче поддерживать, если вы планируете перейти на более новые версии akka в будущем.

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