SBT from scratch

If you use scala, chances are you already met SBT for building your program. In this presentations we introduce it starting from scratch.

SBT from scratch

What is the “Simple” Build Tool ?

Simple Build Tool is the de-facto standard build tool for the Scala world.

  • Is it really “simple”?

The name, actually, can be a bit misleading Is it really simple?

  • Actually not. No more.

The truth is: today, SBT is pretty complex. However, it still lets you do simple things in a simple way.

  • But it is extremely powerful and flexible

SBT is probably the more powerful build tool around. It features interactive execution and an unparalleled flexibility.

Download SBT

Of course, the first step to use any software is its installation.

http://scala-sbt.org

To start, we go in the website scala-sbt.org, and we download it. Depending on the operating system the procedure is different.

Installing SBT

Let’s see how to install SBT in the various operating systems.

On Windows, downloads the msi installer

On windows, the best way is just to download the prepackaged installer.

On mac, use brew install sbt

On Mac OSX, best way is to use the brew package manager. Just type the command line above in the terminal.

Download brew from brew.sh

Note you may also need to install brew from brew.sh website.

On Linux apt-get or yum install sbt

On Linux, you can install it with the appropriate package manager of your system.

Add the correct repo

Note you need to add a repository to retrieve the package. Check the website for the commands to add the correct one.

Hello, SBT world

Let’s build the simplest possible example.

Create the following files

Create the following files:

  • Hello.scala

First, a very simple scala program.

1
2
3
object Hello extends App {
println("hello")
}

It just prints “hello”.

  • build.sbt

Second, a build definition for SBT. It is just a file, named “build.sbt”, containing instructions to build your program.

1
name := "hello"

This build is so simple because
SBT knows everything needed to build the program.

  • Execute: sbt run

Now, just type SBT and ask it to run the program. The program will be compiled and executed.

SBT in practice

Let’s see the preceding instruction in practice. Here we open an editor and create the two files. Then we run the SBT command to execute the code. First, the “hello world” application, simple code to print a message. Second, the build definition, a single instruction giving a name to our program. Finally we go to the command line and type the command. You will see the build tool does some work for assembling the application. At the end, SBT runs the application which prints its output.

Project Layout

To use SBT properly we have to know and follow its conventions for source code.

Top Level

While it is possible to have just a simple file in the top level of your project, here normally there are only the main directories.

  • src
    • source code

Under SRC we place all our source code.

  • project
    • project code

Under the project directory we keep the configuration files for building the source.

  • target
    • generated output

When SBT will compile, it will place its output in the target folder.

Second Level

Now let’s see how we further split our sources.

  • src/main
    • application code

In the main folder of the sources, we place our application code. All the files here will be compiled.

  • src/test
    • test code

In a separate directory, named test, we keep the test code. This code is not shipped with the application.

  • src/resources
    • files to be included as is

Under the resources directory, we place the other files required by the application. Those files are not compiled. However are shipped with the application.

Project Layout third level

We have not finished. ALl our code can be in different languages so it needs to be compiled by different compilers.

  • src/main/scala
    • scala code

We need a scala directory to place our scala code.

  • src/main/java
    • java code

If our project includes java code, it must go under the java directory.

  • src/main/scala-2.10
    • scala code version specific

You can have also code to be compiled only with a specific version of the scala compiler, to support multiple versions.

  • src/test/scala
    • test code in scala
  • src/test/java
    • test code in java

Of course, the distinction between java and scala code applies also to tests.

Artifact configuration

Let’s see now all the parameter needed to configure the output of our project, the so-called artifact.

  • organization := "com.sciabarra"

All artifact belongs to an organization. By convention, it is often the reversed domain name of the organization. It is a critical information to locate the artifact on the internet.

  • version := "0.1"

Extremely important, and the most variable part, is the version number of our artifact. It is also a critical information for packaging.

  • scalaVersion := "2.11.6"

Scala code typically depends on the version of scala used. So we need to specify the scala version we are targetting. Leaving a default is not a wise choice.

1
2
$ sbt package
[info] Packaging demo/target/scala-2.11/hello_2.11-0.1.jar
  • Note the generated jar: hello_2.11-0.1.jar

Those configurations affects the coordinates of the generated artifact.

Dependencies

We just saw how to give a proper identity to our project. Now let’s see how we can import third parties libraries.

1
2
libraryDependencies += "org.scalatest" %% 
"scalatest" % "2.2.4" % "test"

To import a library in your project you use a declaration like this one. This code add a dependency on the ScalaTest library.

  • org.scalatest: organization name

The first part is the organization name.

  • scalatest: artifact name

The second part is the artifact name.

  • 2.2.4: version number

The third one is the version number.

  • test: configuration, optional

The last one is the configuration, which restricts the usage of the dependency and is optional.

Notes on artifact names

In the previous example there are a few things to note.

  • Implicit Scala Version
    • "org.scalatest" %% "scalatest" % "2.2.4"
    • short for % scalatest_2.11

Note the double percent sign, meaning you also add scala version to the artifact name.

  • 2.2.4-SNAPSHOT
    • use SNAPSHOT to have it reloaded all the time.

Normally a dependency is looked up only once. If it ends with “snapshot”, the lookup is repeated every time. This is useful for development.

  • "org.scalatest" %% "scalatest" % "2.2.4" % “test”

A dependency is normally usable for compilation, testing and runtime execution. You can use the configuration to restrict its usage for example only for testing.

Interactive mode

SBT is an interactive build tools. It means it provides a very rich command line interface.

Execute sbt you get a prompt

If you execute SBT, you get a prompt. In this prompt you can type a lot of commands. Here is a list of the more useful.

  • compile
    • compile your code

The primary activity of SBT is compiling your code, activated by the “compile” command.

  • run
    • execute the main class (autodetected)
    • runMain my.class execute a specific class

You can run you program with the “run” command. SBT will automatically for an executable class. If you have many classes you may use the runMain command which allows you to choose which class you want to run.

  • test
    • execute test
    • test:compile only compile tests

The test command will compile and run all your tests. Note that test must be compiled, so you can use test colon compile to compile only your tests, if you are only looking for errors.

  • reload
    • reload configuration

When you change a configuration, you do not need to stop SBT. Just type the reload command to pick the latest changes on the build definition.

  • update
    • update dependencies

If you change the definition you may have defined new dependencies. The update command will retrieve them.

Packaging and console

Let’s see some more commands.

  • package
    • create the artifact

The package command instead produces the jar, after compiling.

  • publish
    • publish the artifacts (more configuration required)

Once compiled, the package can be published to a repository. You need to configure your repository and provide also location and password. So to have this command work you need more configuration that we do not discuss here.

  • publishLocal
    • for local publishing

A simpler way is just to do a local publishing. The local publishing does not require more configuration because it is file based, but the published files can be used only by other projects in your local machine.

  • console

Scala has a console for executing interactively scala code. You can use the console command to access it, with the advantage yor code will compiled and included in the console, so you can try it interactively.

Demo Interactive SBT

Now we see in practice the interaction. As a first step I move the source file to the appropriate directory, according to the conventions.Then I update the build file adding a new dependency, in order to be able to use the test library scalatest. Using this library I can write a test, like the one you can see here. Starting SBT it will resolve the dependency and dowload it from the net, so the library can be used. Finally. I can execute the test from the command line using the command test.

Plugins

Let’s examine now how SBT can be extended using plugins.

Plugin are extensions of SBT

Plugins are extension of SBT. There are many plugins available because writing them is pretty easy. We can then say that plugins exploits the power and flexibility of SBT.

Use one adding in project/plugins.sbt

1
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

You enable a plugin adding a dependency with the addSbtPlugin in the file plugins.sbt under the project directory.

When you add plugins, they often depends on the version of sbt. So it is recommended you also specify the version of the SBT you are using.

1
sbt.version=0.13.9

Plugin version is specified adding the line below in a build.properties file, under the project directory.

now you have a new eclipse command

Each plugin provides different features. Usually a plugin extends the command line with new commands. In the case of the sbt-eclipse plugin, it makes available a command to generate eclipse configurarations for an sbt project.

Plugins and Eclipse

Here we can see how to enable a plugin, and how we use it to generate aconfiguration for editing our project with Eclipse IDE.

Continuous compilation

Typing a compile command for every change can be boring. Luckily, SBT has a feature allowing to compile automatically.

prefix ~ to monitors the source code for edits

Just prefixing any command with the tilde character will put it in continuous compilation mode. It means that any change on the source files will trigger an execution of the command.

  • ~compile - compile at any edit

In the simplest case, with this command you will compile at every save of the files you are editing.

  • ~run - run (and compile) at any edit

There are cases when you actually want to execute a commad at any changes, for example to have a server restarted. You can also do a continuous run while editing. This way your application will be re-executed whenever you change the source files.

  • ~test - test at any edits

Also you may want to do a continuos compilation when you write tests to execute them and fix the code.

concatenation of commands

SBT features execution of multiple commands in single command line.

  • ;test ;run - execute tests then run

To execute multiple commands you have to prefix each command with a semicolon. While it may look odd, this syntax has a reason.

  • ~;test ;run execute tests then run

You can prefix a sequence of commands with the tilde. This way you may have continuous compilation for a sequence of commands, execute whenever some source code changes.

Continuous Compilation

This clip is a demo of continuous compilation in action.