sbtsubproject

How to get the list of subprojects dynamically in sbt 0.13


How can I programmatically (in build.sbt) find all the subprojects of the current root project in sbt 0.13? (I have not tried Project.componentProjects yet, because it's new in sbt 1.0).

lazy val root = (project in file(".") ... )

val myTask = taskKey[Unit]("some description")

myTask := {
  val masterRoot = baseDirectory.value
  // This does not work
  // val subProjects: Seq[ProjectReference] = root.aggregate
  // So I tried to specify the subproject list explicitly; still does not work
  val subProjects = Seq[Project](subPrj1)
  subProjects.foreach { subproject =>
    // All of this works if the "subproject" is hard-coded to "subPrj1"
    val subprojectTarget = target.in(subproject).value / "classes"
    val cp = (dependencyClasspath in(subproject, Compile, compile)).value
  }
}

Got these errors:

build.sbt: error: Illegal dynamic reference: subproject
    val subprojectTarget = target.in(subproject).value / "classes"
                                     ^
build.sbt: error: Illegal dynamic reference: subproject
    val cp = (dependencyClasspath in(subproject, Compile, compile)).value

Solution

  • You can access a list of all subprojects via buildStructure.value.allProjectRefs.

    The other part is of your problem is an aweful issue that I've also faced quite often. I was able to work around such problems by first creating a List[Task[A] and then using a recursive function to lift it into a Task[List[A]].

    def flattenTasks[A](tasks: Seq[Def.Initialize[Task[A]]]): Def.Initialize[Task[List[A]]] =
      tasks.toList match {
        case Nil => Def.task { Nil }
        case x :: xs => Def.taskDyn {
          flattenTasks(xs) map (x.value :: _)
        }
      }
    
    myTask := {
      val classDirectories: List[File] = Def.taskDyn {
        flattenTasks {
          for (project ← buildStructure.value.allProjectRefs)
            yield Def.task { (target in project).value / "classes" }
        }
      }.value
    }
    

    I've used this approach e.g. here: utility methods actual usage