Extra: Using sbt to compile and test the exercises

If you want to use your own favourite text editor when solving the exercises, or simply want to know how to work with a Scala project from the command line, you can compile and test the exercise project directly with a the standard Scala build too, sbt.

What is a ‘build tool’

A software project, of which the exercises in this course are basic examples, usually have multiple source files, unit tests, and sometimes dependencies on external libraries. To manage all this, most programming projects today are set up using a build automation system.

sbt is the most commonly used such build tool specifically made for Scala.

While it is not necessary to know or use sbt directly to work on the exercises - development environments such as VS Code/Metals and IntelliJ readily imports sbt projects, and acts as interfaces to compile and test the code - it can still be useful to know how to work with the tool in special cases.

Installing sbt

  1. Install JDK 11 (for example, from adoptium.net)

  2. Follow the instructions to install sbt for your OS (macOS, Windows, Linux)

Using sbt

If you have sbt installed on your computer, you can use it to compile, test, and run a Scala project such as a course exercise. To try it out, start a terminal on your computer and change directory to the project folder you want to work with. From there, execute the following command (without the leading $, which is only present to show that this is a shell command):

$ sbt compile

You should see something like in the following; A bunch of lines starting with [info], and hopefully ending in a [success]:

[info] welcome to sbt 1.5.0 (Ubuntu Java 11.0.16)
[info] loading global plugins from /u/00/user1/unix/.sbt/1.0/plugins
[info] loading project definition from /u/00/user1/unix/Courses/A1140-assignments/A1140-scala3-r1-warmup/project
[info] loading settings for project root from build.sbt ...
[info] set current project to A1140-scala3-r1-warmup (in build file:/u/00/user1/unix/Courses/A1140-assignments/A1140-scala3-r1-warmup/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] compiling 2 Scala sources to /u/00/user1/unix/Courses/A1140-assignments/A1140-scala3-r1-warmup/target/scala-3.2.0-RC1/classes ...
[success] Total time: 4 s, completed 17 Aug 2022, 12:44:44

This means that the Scala project compiled successfully. Of course, if you would have syntax errors in your program, these would be printed and the compilation unsuccessful. (If you see a message saying something like Command not found: sbt, then sbt may not be properly installed on your system.)

There were two parts of the command, first sbt which is the name of the program we want to run in the terminal, and then compile which is the task we wish sbt to perform for us.

If you know that you will giving many commands (for example repeatedly compiling or testing) it is useful to start up a dedicated sbt console. To do this, run sbt without specifying a task for it:

$ sbt

The terminal will show some more [info] and the prompt will change somewhat. Now you can tell sbt to compile, test, or run directly. For example (without the leading >, which is used to indicate that this is an sbt prompt):

> compile

To exit the sbt command line and get back to the system terminal, press Ctrl-d.

Useful sbt commands include:

  • compile to compile the project, as we have seen.

  • test to first compile and then (if successful) run all unit tests in the project. Results are printed to the console.

  • console to start a Scala console in the project (exit by pressing Ctrl-d).

Interpreting output

If a compile succeeds, sbt will tell you so using [info] and [success] lines in the terminal output. For example:

[info] compiling 1 Scala source to /tmp/A1140-scala3-r1-warmup/target/scala-3.1.3/classes ...
[success] Total time: 1 s, completed

On the other hand, if there are errors in the code, sbt will have [error] lines in its output. For example, in the following we are trying to use an undefined symbol:

[info] compiling 1 Scala source to /tmp/A1140-scala3-r1-warmup/target/scala-3.1.3/classes ...
[error] -- [E006] Not Found Error: /tmp/A1140-scala3-r1-warmup/src/main/scala/warmup/package.scala:64:11
[error] 64 |  for x <- v do
[error]    |           ^
[error]    |           Not found: v
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] one error found
[error] (Compile / compileIncremental) Compilation failed

You can easily see in which file the error occurs (package.scala), and on which line (64). The compilation error also includes the code line in question and the error message.

Watching files

Another feature, useful while developing, having sbt ‘watch’ the files in a project and execute a task every time one of them changes. This is done by prefixing the task with a ~. So, for example:

> ~ test

will automatically try to compile and test the project every time an associated file is saved.

You can of course do this from the terminal command line, but then you will need to put the command in quotes, e.g. sbt "~ test". (Otherwise the ~ may be interpreted as something else by the system terminal.)

To stop watching a project, press Ctrl-d, as usual.