Scala with Bloop and Metals

Afsal Thaj
6 min readMar 22, 2020

Sbt

I hope we all are much familiar with building, compiling and running Scala applications with SBT.

Developers now write SBT plugins relatively quickly, especially to standardise builds across hundreds of applications in the organisation. For instance, packaging docker, fetching org-artifactory credentials, common entry scripts etc.

IMO, it is simple enough, because all we need to know is Scala and there isn’t actually a need of learning the entire SBT reference manual.

These days, I try to avoid a shell script / separate docker-compose.yml /other-language orchestrations alongside my Scala app.
I think most of them is just another new sbt task, hence, scala all the way.

I am also pretty sure, a large number of sbt plugins in open source has also made our life easy, and integrates well with things like docker, avro, git and so on and so forth.

However, not everyone is convinced yet, especially for one single reason: Speed!

Has SBT become faster these days ?

Although latest versions in SBT (as I write this, it’s 1.3.x release), is much faster than the old versions, it seems it hasn’t convinced the developers yet, especially those who have already moved from SBT to Maven (or Gradle) 1–2 years before.

Let’s learn a few technologies that exist before you decide that “SBT is not the way to go”.

I am not trying to do a performance comparison here by the way. Please try out my instructions and see if you are experiencing any positive outcomes and let me know.

Bloop

Bloop is a scala build server, built to compile run, test and run Scala fast. No point re-writing what’s in this website https://scalacenter.github.io/bloop/.

But a few quick questions and answers which you might be interested:

  • Is this an alternative to SBT ? No
  • Is this an alternative to any other build tools ? No
  • Seems like it can work together with SBT, and with other IDEs ? Yes

However, before you switch your mindsets to using Bloop through IDEs such as vs-code+metals and IntelliJ (and thereby learning it), let’s use bloop directly and get a better understanding.

We skip theory here intentionally, and let’s straight away install bloop.

Bloop Installation

To install bloop:

curl -L https://github.com/scalacenter/bloop/releases/download/v1.4.0-RC1/install.py | python

EDIT: New stable versions of bloop available. To download the latest

brew install scalacenter/bloop/bloop

Refer https://scalacenter.github.io/bloop/setup#homebrew

For nix users, it is:

$ nix-channel --add https://nixos.org/channels/nixos-unstable 
$ nixos-unstable
$ nix-channel --update nix-env -iA nixos-unstable.bloop
$ systemctl --user start bloop

Let’s start the bloop server

bloop server

Configure sbt project to work with Bloop

Almost all of you reading this blog, will have a scala project with you in your laptop. A simple scala code will have the following directory structure.

- build.sbt
- src/main/scala
- project/build.properties

It should be a SBT project. If possible, change the SBT to some recent versions (I am using 1.3.x )

In project/plugins.sbt, add the following

addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.4.0-RC1")

Now, within your projects root directory, run

$ cd myProject
$ sbt bloopInstall

In bloop, an sbt project is represented as a pair of (sbt project, sbt configuration) and it's written to a configuration directory. The default location of this directory in your workspace is .bloop/ (you may want to add .bloop/ to your .gitignore file).

Test sbt-bloop configuration

Make sure you are in the project root directory (hence cd myProject)

$ cd myProject
$ bloop projects

This should return the name of your project (in this case, myProject)

Let’s compile

$ cd myProject
$ bloop compile myProject

If your sbt project is multi-module project, bloop projects will return all your modules. Example

$ git clone https://github.com/zio/zio-config
$ cd zio-config
$ bloop projects
docs
docs-test
root
root-test
zio-config
zio-config-examples
zio-config-examples-test
zio-config-magnolia
zio-config-magnolia-test
zio-config-propertyTree
zio-config-propertyTree-test
zio-config-refined
zio-config-refined-test
zio-config-test
zio-config-typesafe
zio-config-typesafe-test
$ bloop compile zio-config

Now trust me, this is much much faster than sbt compile especially in larger projects.

Let’s try other commands

There is a decent amount of bloop commands that makes things easier for us.

$ bloop compile myProject
$ bloop run myProject //runs the only main class
$ bloop run -m com.thaj.MyMain //similar to sbt runMain command
$ bloop test myProject

All of these instructions are running faster compared to corresponding sbt tasks in my experience.

Why this set up ?

I believe, a large number of developers use intellij/other-IDEs with SBT, however rely on terminal to run sbt run or sbt compile for a variety of reasons. For them, by this time, the compile/test/run of the scala app is much faster already with Bloop !

For those who want to know what Metals (explained below) does under the hood, the above set up is a good learning too.

Metals: IDE integration with Bloop

For those who love IDEs, and just want to run things from IDE, this section is for you. Here we talk about metals which you can install into IDE/text-editors.

Metals is a Scala language server with rich IDE features. The IDE features are scala focussed, and for the same reason it seems to be better than intellij presentation layer which can give false errors (the annoying red marks while my code still compiles ! that thing..) for your scala code.

Before we explain installation, keep a note that, if you are installing +using metals, you don’t need to do any of the above steps such as bloop server, adding sbt-bloopplugin, or run sbt bloopInstall manually. Metals does that for you automatically.

Long story short, for anyone who didn’t like the manual life cycle management of your project with bloop, all you need is Metals.

1. Open your vs code2. Go to marketplace, and search for Metals and then install3. Open a scala project with a proper build.sbt

Once you are done with this set up, it should come up with a pop up asking to start importing the build. This implies, metals detected your scala project and is ready to start building it.

If that doesn't work for you, explicitly do Metals: Import build . This is available in vs-code commands through Command + shift + p (if Mac), and that should start building your project.

More details are here (including troubleshooting), and it is super straight forward.
https://scalameta.org/metals/docs/editors/vscode.html

Metals & Bloop

As mentioned before, Metals will automatically start bloop server under the hood. We can test this by trying to run bloop server again, and it will throw an error saying it is already running.

The server runs continuously. Metals also automatically does sbt bloopInstall every-time you change your build configurations.

If metals stop working for some reason, well, you already know the details of bloop and how to communicate with it.

Trying bloop commands from terminal

All your bloop commands should work from the terminal while vs-code+metals is open. Sometimes, explicit sbt bloopInstall and explicit bloop compile can be much faster than Metals: Import Build , if you are in a hurry.

Hence, consider metals as an abstraction to everything what we did before + fantastic IDE features that you need.

For those who are used to intellij keystrokes, you can install intellij keystrokes as a plugin to vs-code.

Why not Intellij + Bloop ?

Intellij’s presentation layer can be sometimes confusing, especially if you are writing GADTs in Scala, though it rarely happens.

If you are trying to have bloop features with intellij, consider this link: https://scalacenter.github.io/bloop/docs/ides/intellij

Summary

  1. Why Bloop ? Bloop focusses on faster compilation of scala projects, while still delegating packaging tasks to build tools such as sbt.
  2. Why Vs code + Metals ? Easy set up, and you get the advantage of faster compilation of bloop automatically, with a better IDE experience.

Keep a note:

1. Metals can also work with maven and gradle. However, I didn’t bother trying after I got some decent speed with Metals+sbt.
2. I am looking forward to sharing my experience with Metals + Mill (https://github.com/lihaoyi/mill)

Hope it was helpful for you. Thanks!

--

--

Afsal Thaj

A software engineer, traveller, fitness trainer, hiker, skydiver and I write at times. https://twitter.com/afsalt2