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.10.10

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.