How to create an SBT project with subprojects

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is a short recipe, Recipe 18.6, “How to create an SBT project with subprojects.”

Problem

You want to configure SBT to work with a main Scala project that depends on other subprojects you’re developing.

Solution

Create your subproject as a regular SBT project, but without a project subdirectory. Then, in your main project, define a project/Build.scala file that defines the dependencies between the main project and subprojects.

This is demonstrated in the following example, which I created based on the SBT Multi-Project documentation:

import sbt._
import Keys._

/**
  * based on http://www.scala-sbt.org/release/docs/Getting-Started/Multi-Project
  */
object HelloBuild extends Build {
  // aggregate: running a task on the aggregate project will also run it
  // on the aggregated projects.
  // dependsOn: a project depends on code in another project.
  // without dependsOn, you'll get a compiler error: "object bar is not a
  // member of package com.alvinalexander".
  lazy val root = Project(id = "hello",
                        base = file(".")) aggregate(foo, bar) dependsOn(foo, bar)
  // sub-project in the Foo subdirectory
  lazy val foo = Project(id = "hello-foo",
                         base = file("Foo"))
  // sub-project in the Bar subdirectory
  lazy val bar = Project(id = "hello-bar",
                         base = file("Bar"))
}

To create your own example, you can either follow the instructions in the SBT Multi-Project documentation to create a main project with subprojects, or clone my SBT Subproject Example on GitHub, which I created to help you get started quickly.

Discussion

Creating a main project with subprojects is well documented on the SBT website, and the primary glue that defines the relationships between projects is the project/Build.scala file you create in your main project.

In the example shown, my main project depends on two subprojects, which are in directories named Foo and Bar beneath my project’s main directory. I reference these projects in the following code in my main project, so it’s necessary to tell SBT about the relationship between the projects:

package com.alvinalexander.subprojecttests

import com.alvinalexander.bar._
import com.alvinalexander.foo._

object Hello extends App {
    println(Bar("I'm a Bar"))
    println(Bar("I'm a Foo"))
}

The following output from the Unix tree command shows what the directory structure for my project looks like, including the files and directories for the main project, and the two subprojects:

|-- Bar
|   |-- build.sbt
|   +-- src
|       |-- main
|       |   |-- java
|       |   |-- resources
|       |   +-- scala
|       |       +-- Bar.scala
|       +-- test
|           |-- java
|           +-- resources
|-- Foo
|   |-- build.sbt
|   +-- src
|       |-- main
|       |   |-- java
|       |   |-- resources
|       |   +-- scala
|       |       +-- Foo.scala
|       +-- test
|           |-- java
|           +-- resources
|-- build.sbt
|-- project
|   |-- Build.scala
|
+-- src
    |-- main
    |   |-- java
    |   |-- resources
    |   +-- scala
    |       +-- Hello.scala
    +-- test
        |-- java
        |-- resources
        +-- scala
            +-- HelloTest.scala

To experiment with this yourself, I encourage you to clone my GitHub project.

See Also

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.