This is a study note of the sbt build tool. It is based on the sbt Reference Manual and the book of sbt in Action

1. Introdcution

sbt stands for “simple build tool”. It provides a parallel execution engine and configuration system that run Scala build scripts. sbt is an interactive tools built upon a set of consistent concepts.

The project/build.properties file defines the sbt version such as sbt.version=1.3.3. The build.sbt is the build setting for the project.

sbt provides a set of predefined tasks including clean, compile, run, test etc. Use tasks to see the list of tasks. sbt uses many settings to run its tasks, use settings to see the list of settings. Typing a setting name displays the current setting. For example, type scalaSource gives the source directory for Scala source code, usually it is the src/main/scala folder in the current project. the target shows the folder of generated files.

2. Key Concepts

Setings

A setting consists of three parts: a key, an initialization, and an operator that associate the key and initialization. An initialization is a Scala expression that can produce a value. Use key.value method to access a setting’s value. There are three operators to create a setting:

  • :=: reset a new value
  • +=: appends a value to the seqence in a key
  • ++=: appends a seqence of values to the sequence in a key

sbt provides % method to create a ModuleID instance like "groupId" % "artifactId" % "version".

Tasks

A task runs whenever you request its value. To create a new task, first create a new key that store the value of an operation. Then create a setting that bind the operation to this task key. Here the := is constructing a function that will compute the value fo the task key. By separating the computation (operation) from the setting, sbt allows parallel execution.

Following are commonly used tasks:

SBT Command Purpose Notes and Dependencies
update Resolves and caches library dependencies No dependencies
compile Compiles applicationon sources Depends on update
run Runs application in development mode, continuously recompiles
on demand Depends on compile
console Starts an interactive Scala prompt Depends on compile
test:compile Compiles all unit tests Depends on compile
test Compiles and runs all unit tests Depends on test:compile
testOnly foo.Bar Compiles and runs unit tests defined in the class foo.Bar Depends on test:compile
clean Deletes temporary build files under \${projecthome}/target No dependencies

Configurations and Subprojects

Configurations are namespaces for keys and settings. sbt has the following default configurations:

  • Compile: settings and values used to compile the main project and generate production artifacts.
  • Test: used to compile and run unit testing.
  • Runtime: used to run project within sbt.
  • IntegrationTest: used to run tests against production artifacts.
  • ThisBuild: the last configuration if a key cannot be found in a configuration. it is the current build, can be used in all configurations and subprojects.

For example, the task defined at sources in Compile collects the source files to be compiled for production artifacts.

Namepsace scope is defined by project, configuration and task.

Subprojects are namespaces for keys and settings.

By default, sbt runs unprefiex settings/tasks against all projects. sbt auotmatically generates a root pojrect that is responsible for aggregating the other objects.

In sbt, the whole build is a key / initialization pairing (setting) of projects. some settings contains “repeatable” blocks of code, called Tasks.

Plugins

Plugins are external libraries. sbt reads the .sbt and .scala files in /project to build definitions used in the root .sbt files. A plugin is a jar that contains settings and tasks. Usually include a plugin in project/plugins.sbt as the following example:

1
2
3
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.5.0")

resolvers += "sonatype-releases" at "https://oss.sonatype.org/content/repositories/releases/"

Unlike the normal dependencies, the %% in addSbtPlugin appends both a Scala version and a sbt version to the name. The Scala version is the version used by the current sbt, not the project being built.

The above code also includes an extra resolver because the plugin isn’t published to the standard set of repositories that sbt knows about by default.

The Default Build

Compile

Compilation requires soruce files, libraries and configuration options. sbt uses convention over configuration.

Sources include unmanaged and managed (generated from the build). the unmanaged sources are discovered by convention and are managed manually. sbt creates and track the managed sources. The sources are defined by baseDriectory, sourceDirectory, scalaSource etc. Use sbt command show scalaSource to find the default Scala source directory. There is a resource task to collect resources, either unmanaged or managed, that should be available at runtime. Use show resourceDirectory to check the default resource directory.

Additionally, there are test sources and test resources defined in a test configuration. use show test:scalaSource to see the test directory.

Library Dependency

There are internal dependencies (among projects) and external dependencies. External dependencies include unmanged dependencies (in the lib/ directory) and managed dependencies. The update task is responsible to resovle extenal dependencies.

The sbt comes with built-in repositories such as Maven Central, Typesafe release and sbt community release. Addtional repository is specified using resolver += ....

Use libraryDependencies to specify library dependencies. For Java library, the ModuleID format is "organization" % "artifactId" % "version". For Scala library, the ModuleID use "organization" %% "artifactId" % "version" to automatically append Scala version.

By default, all dependencies are put onto the default configuration, used for both running an compiling all code. To add a configuration such as test, just add it to the ModuleID: "organization" %% "artifactId" % "version" % "test".