SBT Multi-Project Build with dynamic external projects?

build, playframework-2.0, sbt, scala

Solution

We tried a few approaches, but the only one we could get to work and that didn't feel like an incomprehensible/unmaintainable hack was to add an `implicit class` that adds a method to `Project` that can add a dependency either locally or as an artifact.

Pseudo-code outline of the implementation:

implicit class RichProject(val project: Project) extends AnyVal {

  def withSpecDependencies(moduleIds: ModuleID*): Project = {
    // Read the spec.json file that tells us which modules are on the local file system
    val localModuleIds = loadSpec(project.base / "spec.json")

    // Partition the passed in moduleIds into those that are local and those to be downloaded as artifacts
    val (localModules, artifactModules) = moduleIds.partition(localModuleIds.contains)
    val localClasspathDependencies = toClasspathDependencies(localModules)

    project
      .dependsOn(localClasspathDependencies: _*)
      .settings(libraryDependencies ++= artifactDependencies)
  }
}

The usage pattern in an actual SBT build is pretty simple:

val foo = Project("foo", file("foo")).withSpecDependencies(
  "com.foo" % "bar" % "1.0.0",
  "org.foo" % "bar" % "2.0.0"  
)

Problem

Let's say we have an SBT project `bar` with a dependency on some artifact `foo`: ``` val bar = Project('bar', file('.')).settings( libraryDependencies += "com.foo" % "foo" % "1.0.0" ) ``` However, in certain cases, I want to checkout the source of `foo` and have SBT load the source from my file system instead of the published artifact; that way, I could make local changes to `foo` and immediately test them with `bar` without having to publish anything. ``` val foo = Project('foo', file('foo')) val bar = Project('bar', file('.')).dependsOn(foo) ``` We have a `spec.json` file in the root folder of `bar` that already specifies if `foo` should be used from source or as an artifact. Is there any way to setup my build to read this file and add `dependsOn` or `libraryDependencies` based on the value in `spec.json`? ' It's easy enough to do this for `libraryDependencies`: ``` val bar = Project('bar', file('.')).settings( libraryDependencies ++= if (containsFoo(baseDirectory.value / "spec.json")) { Seq() } else { Seq("com.foo" % "foo" % "1.0.0") } ) ``` However, we can't find any way to set do anything "dynamic" in `dependsOn`, such as reading the `baseDirectory` `SettingKey`.

Original source

Related problems