> !
History commands:
!! Execute the last command again
!: Show all previous commands
!:n Show the last n commands
!n Execute the command with index n, as shown by the !: command
!-n Execute the nth command before this one
!string Execute the most recent command starting with 'string'
!?string Execute the most recent command containing 'string'
>

Get a list of tasks available from you SBT configuration file:

> tasks
This is a list of tasks defined for the current project.
It does not list the scopes the tasks are defined in; use the 'inspect' command for that.
Tasks produce values. Use the 'show' command to run the task and print the resulting value.
clean Deletes files produced by the build, such as generated sources, ...
compile Compiles sources.
...
update Resolves and optionally retrieves dependencies, producing a report.
More tasks may be viewed by increasing verbosity. See 'help tasks'.

One of the most interesting features in SBT is the continuous mode, to automatically recompile or run the tests whenever you save a source file. This is especially useful to run tests in the background when coding. All you have to do is to precede your task with “~”:

TaskKey[T]: the value is executed every time the task is run. The task could have side effects, such as writing files on disk

InputKey[T]:A TaskKey[T] with command line arguments

Beware, a TaskKey is always run only once per execution. SBT will look for all the dependencies and will deduplicate identical tasks. Therefore, you can not describe a task with the following algorithm:

call clean task

generate classes from sources

call clean task again

The classes generated in the second step will not be cleaned because the clean task has already been run in step 1.

The last important thing to understand how SBT works is the Scope. In the Map generated by the SBT execution, the key is not formed by the name but by the name + the scope. This allows you to have multiple values for the same key.

There are 3 scopes:

Project: The value name has a different value depending on the sub-project

Configuration: The value is different depending on if you are using a test or compilation configuration.

Task: The value is different depending on the task where it is declared

How to describe a build?

There are 3 ways to describe a SBT build:

A bare .sbt build definition

A multi-project .sbt build definition

A .scala build definition

The .scala build definitions are placed in a project sub-directory. This directory is itself a new SBT project with the Scala source code necessary for the build. The build and application sources are then well separated. If you want to turn your Scala build sources into a SBT plugin, you already have a separated SBT project!

In this post, we will not use the .scala build definition but we will use the project sub-directory to write tasks code and a build.sbt file in the project’s root to describe the build.

The build.sbt can have two versions, depending on if you are using it for a simple project or multiple projects.

A SBT build definition is just a list of Setting definitions processed to transform the Map. When you work with a simple project, without extending any feature, Keys are SettingKey[T] by default.

Dependency management

There are two ways to deal with dependencies in SBT.

Unmanaged mode

The unmanaged – or manual – mode just requires dropping JAR files in the lib directory and they will be automatically added to the classpath by convention. Using scopes, you can have a separate directory for tests. We will not elaborate on this, but who still uses manual dependencies?

Managed mode

In this mode you add values to the libraryDependencies key which is of type SettingKey[Seq[ModuleID]]. Therefore, your dependency declaration needs to be of type ModuleID, which is greatly simplified thanks to the DSL in build.sbt:

To manage libraries, SBT uses Ivy under the hood. Therefore, it is possible to use dynamic version declaration. For example, you can declare a 2.2+ version to automatically upgrade to fixes on the 2.2.x version of your dependency.

Scala / SBT options

Compiling for multiple scala versions:

scalaVersion := "2.11.4" // Scala version for the project
crossScalaVersions := Seq( "2.10.4", "2.11.0")
// The project will be built for each declared version if you precede a task with “+”
> + compile
[…]
> + package

Another very useful option to deal with different SBT versions installed in each developer local environment is the possibility to specify the SBT version to use. For this, you need to create a build.properties file in the project directory:

// No matter the SBT version installed, 0.13.9 will be downloaded and used for the build
sbt.version=0.13.9

Conclusion

SBT is a powerful tool to describe your build and manage your dependencies.

Understanding the key-value model behind the scenes and its immutable nature can help debugging and also writing plugins.

SBT is the de facto standard tool for Scala projects and we encourage you to use it.

Ippon Technologies is an international consulting firm that specializes in Agile Development, Big Data and
DevOps / Cloud.
Our 300+ highly skilled consultants are located in the US, France and Australia. Ippon technologies has a $32
million
revenue and a 20% annual growth rate.

Newsletter

For our news update, subscribe to our newsletter! You can unsubscribe anytime.

Recent Posts

We are IPPON

Proud of our passion for technology and expertise in information systems, we partner with our clients to deliver innovative solutions for their strategic projects.
Through communication, curiosity and team spirit, we offer the best solutions to our customers.