2
votes

I need a piece of code using SBT, possibly internals, which acquires the full classpath of an SBT project without invoking a compilation. Normally I would use "Runtime / fullClasspath", but that needs the project to be compiled first. Is there any way to get the fullClasspath without triggering a compile? I thought the build.sbt alone determined the classpath, and compilation (in theory) isn't necessary.

I asked on the SBT gitter channel, and there it was also mentioned to use dependencyClasspath. dependencyClasspath doesn't require compilation of the root project, but it does require compilation of all the dependents. So that doesn't solve it yet for me. I'm looking for the complete classpath required to running the root project, without compiling its constituents.

I'm interested in any way to work around this, so if there are any farfetched workarounds, those are welcome too.

An example of what I have now:

Global / printMainClasspath := {
    val paths = (rootProject / fullClasspath).value
    val joinedPaths = paths
        .map(_.data)
        .mkString(pathSeparator)
    println(joinedPaths)
}

This works partially, it creates a task "printMainClasspath" which prints the full classpath. But if I call it in the sbt shell, it compiles the code first. I'd like the classpath to be printed without invoking a full compile of the project. Ideally, only all build.sbt's of all constituent projects are compiled. Is there a way?

1
Why not compiling?cchantep
We want the classpath to be available for some external component of our project. So we export the classpath to a file regularly. Since exporting the classpath compiles the code, the classpath is not exported if the code contains errors. If we can remove compilation from that loop, the classpath can be exported regularly and quietly in the background. (Assumption: the classpath is defined/well-formed even if our scala files in src/ contain errors)bobismijnnaam
Really look like X/Ycchantep
Possibly, our approach is also used to work around sbt slowness, specifically, the start time of sbt. Vague ideas/thoughts are also welcomebobismijnnaam

1 Answers

1
votes
val dryClasspath = taskKey[Seq[File]]("dryClasspath")

dryClasspath := {
  val data = settingsData.value
  val thisProj = thisProjectRef.value
  val allProjects = thisProj +: buildDependencies.value.classpathTransitiveRefs(thisProj)
  val classDirs = allProjects.flatMap(p => (p / Runtime / classDirectory).get(data))
  val externalJars = (Runtime / externalDependencyClasspath).value.map(_.data)
  classDirs ++ externalJars
}