sksamuel
sksamuel

Reputation: 16387

SBT run task after all subprojects

I want to write a task that is run after all subproject tasks are complete.

Eg, if I do

sbt a b then after task a is complete on ALL subprojects I want to execute task b. I don't want to do (a b) on each project.

Is that possible?

In fact, I'll take it so that I modify the build.sbt directly. I don't necessarily have to specify it at the command line.

Upvotes: 2

Views: 1414

Answers (1)

Eugene Yokota
Eugene Yokota

Reputation: 95664

I wrote a blog post on the subject: sequencing tasks with sbt-sequential.

addCommandAlias

Here's an example. We'll define a custom task a in sub1 and sub2 and b in root. The simplest way to achieve sequential execution is using addCommandAlias, so we'll just do that.

lazy val a = taskKey[Unit]("a")
lazy val b = taskKey[Unit]("b")

lazy val root = (project in file(".")).
  aggregate(sub1, sub2).
  settings(addCommandAlias("ab", ";a;b"): _*).
  settings(
    b := {
      println("b")
    }
  )

lazy val sub1 = (project in file("sub1")).
  settings(a := println("a - sub1"))

lazy val sub2 = (project in file("sub2")).
  settings(a := println("a - sub2"))

You can run this from shell as sbt ab.

$ sbt ab
[info] Loading global plugins from ...
[info] Loading project definition from ...
[info] Set current project to root (in build ...)
a - sub2
a - sub1
[success] Total time: 0 s, completed Nov 22, 2014 8:36:18 PM
b
[success] Total time: 0 s, completed Nov 22, 2014 8:36:18 PM

Def.taskDyn

Here's another example. This time using Def.taskDyn, which is also featured in the blog post. I'm constructing a ScopeFilter from the aggregate and then I'm dispatching task a to them.

lazy val a = taskKey[File]("a")
lazy val b = taskKey[Seq[File]]("b")

lazy val root = (project in file(".")).
  aggregate(sub1, sub2).
  settings(
    b := (Def.taskDyn {
      val proj = thisProject.value
      val filter = ScopeFilter(inProjects(proj.aggregate: _*))
      Def.task {
        val allValues = a.all(filter).value
        println(allValues.mkString(","))
        allValues
      }
    }).value
  )

lazy val sub1 = (project in file("sub1")).
  settings(a := new File("a"))

lazy val sub2 = (project in file("sub2")).
  settings(a := new File("b"))

You can run this from shell as sbt b.

$ sbt b
[info] Loading global plugins from ...
[info] Loading project definition from ...
[info] Set current project to root (in build ...)
a,b
[success] Total time: 0 s, completed Nov 23, 2014 9:42:16 PM

Upvotes: 1

Related Questions