1. Defining a dynamic task with Def.taskDyn

Defining a dynamic task with Def.taskDyn 

If sequential task is not enough, another step up is the dynamic task. Unlike Def.task which expects you to return pure value A, with a Def.taskDyn you return a task sbt.Def.Initialize[sbt.Task[A]] which the task engine can continue the rest of the computation with.

Let’s try implementing a custom task called compilecheck that runs Compile / compile and then Compile / scalastyle task added by scalastyle-sbt-plugin.

project/build.properties 

sbt.version=1.9.8

project/style.sbt 

addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")

build.sbt v1 

lazy val compilecheck = taskKey[sbt.inc.Analysis]("compile and then scalastyle")

lazy val root = (project in file("."))
  .settings(
    compilecheck := (Def.taskDyn {
      val c = (Compile / compile).value
      Def.task {
        val x = (Compile / scalastyle).toTask("").value
        c
      }
    }).value
  )

Now we have the same thing as the sequential task, except we can now return the result c from the first task.

build.sbt v2 

If we can return the same return type as Compile / compile, might actually rewire the key to our dynamic task.

lazy val root = (project in file("."))
  .settings(
    Compile / compile := (Def.taskDyn {
      val c = (Compile / compile).value
      Def.task {
        val x = (Compile / scalastyle).toTask("").value
        c
      }
    }).value
  )

Now we can actually call Compile / compile from the shell and make it do what we want it to do.