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