Robert Elliot
Robert Elliot

Reputation: 1512

SBT - conditionally set exportJars setting based on task

I have a mixed server side Scala / Scala.js project, built to a runnable jar. I'm using the sbt-revolver plugin to restart the main class on change of any files, and ~ fastOptJS to recompile the JS on change to the client side files.

I'd like not to restart the main class if only client side files have changed, as it's making the feedback cycle slow. I use a task I've defined called "build" to copy the jars around to where I want them (for Docker) as so:

exportJars := true
mainClass in appJVM := Some("myproject.Server")

packageOptions in (appJVM, Compile, packageBin) += ManifestAttributes( "Class-Path" -> externalDependencyClasspath.in(appJVM, Runtime).value.files.map { file => s"dependencies/${file.name}" }.mkString(" ") )

lazy val build = taskKey[Unit]("Ensures jars are in the right places for Docker")
build := {

  val packagedDir = new File(target.value, "packaged")
  IO.delete(packagedDir)
  val dependenciesDir = new File(target.value, "packaged/dependencies")
  dependenciesDir.mkdirs()

  val (_, artifactFile) = packagedArtifact.in(appJVM, Compile, packageBin).value
  Files.copy(artifactFile.toPath, new File(packagedDir, artifactFile.getName).toPath, COPY_ATTRIBUTES)

  externalDependencyClasspath.in(appJVM, Runtime, build).value.files.foreach { file =>
    Files.copy(file.toPath, new File(dependenciesDir, file.name).toPath, COPY_ATTRIBUTES)
  }
}

However, this means that when I use appJVM/reStart it actually runs the jar file, which in turn means that in order to change the client side JS the jar file has to be rebuilt and the server has to be restarted.

If I set exportJars := false then appJVM/reStart runs my project from the classes directory, so only running fastOptJS will let me see my changes without needing to restart the server.

Is there a way to conditionally set exportJars depending on whether I'm running the build task or not?

Upvotes: 1

Views: 437

Answers (2)

Robert Elliot
Robert Elliot

Reputation: 1512

My final conclusion was that if I entirely removed the exportJars setting, but made build depend on packagedArtifact.in(appJVM, Compile, packageBin) then I got the best of both worlds. reStart ran from the classes directory, so resources could be changed on the fly, but I still got a jar build that I could copy into the right place.

(This still leaves internalDependencyClasspath returning the classes dir rather than a jar - I have no solution to that other than to work around it by not using internalDependencyClasspath.)

Upvotes: 0

Robert Elliot
Robert Elliot

Reputation: 1512

Looks like it's as simple as moving setting exportJars it into my build task as so:

build := {
  exportJars := true
  ...
}

Upvotes: 0

Related Questions