Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequencing and overriding tasks in SBT

Quick summary: I'm trying to wait in the top-level project for all SBT submodules to build, then remove their target directories. Top-level application aggregates all submodules, they won't be deployed separately but only as a bundle with classpath dependencies, while duplicated libraries in submodules blow up the size of the whole package and the slug goes over Heroku limit.

Technically, I'm trying to actually use this - I'm trying to add a 'cleanup' task that would run after stage. The solution from link above doesn't seem to work for me (Play 2.4, SBT 0.13.5), the error says it better than I can:

build.sbt:50: error: reference to stage is ambiguous;
it is imported twice in the same scope by
import _root_.com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport._
and import $52e59eb09172b3222f9e._
stage := {

Assuming I have my cleanup task:

val stageCleanupTask = taskKey[Unit]("Clean after stage task")

stageCleanupTask := {
  val log = streams.value.log
  if (sys.env.getOrElse("POST_STAGE_CLEAN", "false").equals("true")) {
    log.info("Cleaning submodules' target directories")
    sbt.IO.delete(baseDirectory.value / "modules" / "a" / "target")
    sbt.IO.delete(baseDirectory.value / "modules" / "b" / "target")
    sbt.IO.delete(baseDirectory.value / "modules" / "c" / "target")
  }
}

and I'm tring to override stage:

stage := {
  val f = (stage in Universal).value
  stageCleanupTask.value
  f
}

It seems to be simply wrong, since both tasks run concurrently. SBT doesn't really make it easy either, I didn't find much in the official documentation, so I was just playing around:

  • stage.flatMap expects a function that returns a Task[U], but stageCleanupTask is a TaskKey[T], and .value doesn't work outside of very specific areas, so composition via something similar to stage <<= stage.flatMap(f => stageCleanupTask.map(_ => f)) seems to be out of the question.

  • dependsOn could only work as stage <<= stage dependsOn stageCleanupTask, which is the exact opposite of the dependency chain I want. stageCleanupTask should depend on stage, but the types won't match (Task[Unit] vs Task[File])

  • I was trying to experiment with composition inside overriden stage, as in:

    stage := {
        (stage in Universal).map(f => /*follow up*/ f).value
    }
    

    but that usually just slaps me in the face with illegal dynamic dependency or illegal dynamic reference

What would be the preferred way of sequencing SBT tasks?

like image 889
Patryk Ćwiek Avatar asked Jan 17 '16 17:01

Patryk Ćwiek


1 Answers

See http://www.scala-sbt.org/0.13/docs/Howto-Sequencing.html for how to sequence tasks.

So something like:

stage in Universal := Def.sequential(
  stage in Universal,
  stageCleanupTask
)
like image 65
Dale Wijnand Avatar answered Sep 30 '22 23:09

Dale Wijnand