我正在编写一个进行监视/ 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
发布root/publishLocal
项目,而测试项目仅设计为将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
通常,您可以从编织的外部库中排除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,则项目布局和构建脚本会稍微复杂一些,但也更易于维护。