Создание библиотеки 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 в будущем.