Search code examples
sbtaspectjsbt-native-packagersbt-aspectj

sbt aspectj with native packager


I'm attempting to use the sbt-aspectj plugin with the sbt native packager and am running into an issue where the associated -javaagent path to the aspectj load time weaver jar references an ivy cache location rather than something packaged.

That is, after running sbt stage, executing the staged application via bash -x target/universal/stage/bin/myapp/ results in this javaagent:

exec java -javaagent:/home/myuser/.ivy2/cache/org.aspectj/aspectjweaver/jars/aspectjweaver-1.8.10.jar -cp /home/myuser/myproject/target/universal/stage/lib/org.aspectj.aspectjweaver-1.8.10.jar:/home/myuser/myproject/target/universal/stage/lib/otherlibs.jar myorg.MyMainApp args

My target platform is Heroku where the artifacts are built before being effectively 'pushed' out to individual 'dynos' (very analogous to a docker setup). The issue here is that the resulting -javaagent path was valid on the machine in which the 'staged' deployable was built, but will not exist where it's ultimately run.

How can one configure the sbt-aspectj plugin to reference a packaged lib rather than one from the ivy cache?


Current configuration:

project/plugins.sbt:

addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.5")

build.sbt (selected parts):

import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
  aspectjSettings,
  javaOptions in Runtime ++= { AspectjKeys.weaverOptions in Aspectj }.value,
  // see: https://github.com/sbt/sbt-native-packager/issues/598#issuecomment-111584866
  javaOptions in Universal ++= { AspectjKeys.weaverOptions in Aspectj }.value
    .map { "-J" + _ },
  fork in run := true
)

Update

I've tried several approaches including pulling the relevant output for javaOptions from existing mappings, but the result is a cyclical dependency error thrown by sbt.

I have something that technically solves my problem but feels unsatisfactory. As of now, I'm including an aspectjweaver dependency directly and using the sbt-native-packager concept of bashScriptExtraDefines to append an appropriate javaagent:

updated build.sbt:

import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
  aspectjSettings,
  bashScriptExtraDefines += scriptClasspath.value
    .filter(_.contains("aspectjweaver"))
    .headOption
    .map("addJava -javaagent:${lib_dir}/" + _)
    .getOrElse(""),
  fork in run := true
)

Solution

  • I actually solved this by using the sbt-javaagent plugin to adding agents to the runtime