我正在编写一个执行监控/OpenTracing的库,并且我正在尝试使用sbt-aspectj,这样库的用户就不需要手动插装他们的代码。然而,我目前在创建代表这样一个库的sbt-project时遇到了一个问题。
我的想法是,我想要一个外部库,就像这个示例中指出的那样,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/publishLocal发布root项目,而测试项目只是被设计为包含root作为libraryDependency,这样我们就可以看到aspect-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上发布的问题
发布于 2019-12-31 10:43:09
通常,您可以从编织的外部库中排除META-INF目录。
mappings in (Compile, packageBin) := {
(mappings in (Compile, packageBin)).value
.filterNot(_._2.startsWith("META-INF/"))
}但对于akka库来说,还有另一个问题。在每个akka库中,都有一个reference.conf,其中包含所提供功能的回退配置。这也会导致像META-INF那样的冲突。但它不能像META-INF一样被排除在外,因为它们对于akka的正常工作至关重要。
如果你排除了它们,你必须在你的application.conf中提供所有需要的akka配置,或者在你的项目中提供一个合并的(而不是简单的连接) reference.conf。这不是微不足道的,而且会受到akka版本变化的影响。
另一种解决方案是分别编织和重新打包akka库,这样reference.conf就可以保存在重新打包的库中。项目布局和构建脚本会有点复杂,但如果你计划在未来升级到更新版本的akka,也会更容易维护。
https://stackoverflow.com/questions/59520762
复制相似问题