Build Tools

Contributing

Integrating a new build tool

Metals uses the
Build Server Protocol
(BSP) to communicate with build tools. Any build tool that implements the
protocol should work with Metals.

There are two options for integrating Metals with a new build tool:

via Bloop: emit Bloop JSON configuration files and use
the Bloop build server. The benefit of this approach is that it is simple to
implement but has the downside that compilation happens outside of your build
tool.

via custom build server: add Build Server Protocol
support to your build tool. The benefit of this approach is that Metals
integrates directly with your build tool, reproducing the same build
environment as your current workflow. The downside of this approach is that it
most likely requires more effort compared to emitting Bloop JSON files.

Enable SemanticDB

Regardless if you use the Bloop build server or implement a custom build server,
the SemanticDB compiler
plugin is required for Metals code navigation to work. Only limited Metals
features like diagnostics and code formatting work without the SemanticDB
compiler plugin enabled.

Make sure to declare the compiler option "-P:semanticdb:sourceroot:$WORKSPACE"
where $WORKSPACE is the absolute path to the workspace root directory. By
default, the sourceroot is inferred from the working directory of the compiler
process but it's better to explicitly declare it. If the sourceroot is
misconfigured, then Metals is unable to find the SemanticDB files created by the
compiler plugin.

Recommended compiler options

We recommend you update the following compiler options when using Metals:

-Xlint: these warnings are helpful in the editor even if you don't have them
enabled in your main build. Consult scalac -Xlint:help for a full list of
available warnings.

-Xfatal-warnings: disable this setting even if you have it enabled in your
main build. Fatal warnings prevent code navigation from working when there are
warnings like 'unused import'.

Custom build server

Server discovery

Metals automatically connects to a BSP server if the workspace root directory
contains a .bsp/$name.json file. For example, a build tool named "Bill" will
have a .bsp/bill.json file with the following information.

Automated tests

The Metals repository has infrastructure for running end-to-end integration
tests with build servers. To test your build server integration, you can to
clone the repository and write custom tests under
tests/unit/src/test/scala/tests.

If there is interest, we can publish a Metals testkit module to make it
possible to write tests outside the Metals repository.

SemanticDB

As a build server, you are responsible for enabling the
SemanticDB compiler plugin.
The SemanticDB plugin is required for features like Goto Definition to work.
Diagnostics work fine without SemanticDB enabled.

Users get a warning from Metals when the build server does not enable the
SemanticDB compiler plugin. Users have an option to suppress this warning by
selecting a "Don't show again" button.

BSP endpoints

Metals requires the following BSP endpoints to be implemented by the build
server.

workspace/buildTargets: to list all the build targets in the workspace.

buildTarget/scalacOptions: to know the classpath and compiler options used
to compile the project sources.

buildTarget/sources: to know what source files map to which build targets.

buildTarget/dependencySources: to support "Goto definition" for external
libraries.

buildTarget/compile: to trigger compilation in a build target.

Additionally, Metals expects the server to send the following notifications:

buildTarget/publishDiagnostics: To report compile errors and warnings in the
editor buffer.