What it is
sbt is a build tool for Scala and Java projects, used for compiling, running, testing, packaging, and managing dependencies.
Installation
Linux
# Using SDKMAN! (recommended)
sdk install sbt
or
# Manual installation (download from sbt.io)
# Add sbt's bin directory to your PATH
macOS
# Using Homebrew
brew install sbt
or
# Using SDKMAN! (recommended)
sdk install sbt
Windows
# Using SDKMAN! (recommended)
sdk install sbt
or
# Using Chocolatey
choco install sbt
or
# Manual installation (download from sbt.io)
# Add sbt's bin directory to your PATH
Core Concepts
- Build Definition (
build.sbt): The primary build configuration file, written in Scala. It defines project settings, dependencies, and tasks. - Plugins: Extend sbt’s functionality. Common plugins include
sbt-assemblyfor fat JARs,sbt-releasefor version management, andsbt-native-packagerfor creating installers. - Tasks: Actions that sbt can perform (e.g.,
compile,test,package). Tasks can depend on other tasks. - Settings: Key-value pairs that configure the build (e.g.,
version,scalaVersion,libraryDependencies). - Scopes: Define where settings and tasks apply (e.g.,
ThisBuild,project/name,Compile,Test). - Aggregating Projects: A root project can aggregate sub-projects, allowing tasks to be run across multiple projects simultaneously.
Commands / Usage
Running sbt
# Navigate to your project directory (where build.sbt is)
cd /path/to/your/scala/project
# Start the sbt interactive shell
sbt
Once inside the sbt shell:
Common Interactive Commands
# Compile the project
compile
# Run tests
test
# Package the project (creates a JAR)
package
# Clean the project (removes compiled files)
clean
# Show project settings
show settings
# Show specific settings (e.g., scala version)
show scalaVersion
# Show dependencies
show libraryDependencies
# Run a specific Scala object with a main method
runMain com.example.MyApp
# Check for outdated dependencies
dependencyUpdates
# Update dependencies (after checking with dependencyUpdates)
# (This is typically done by editing build.sbt and re-running sbt)
# Exit sbt shell
exit
Running Commands Directly from the Shell
# Compile project without entering interactive shell
sbt compile
# Run tests
sbt test
# Package project
sbt package
# Clean project
sbt clean
# Run a specific Scala object
sbt "runMain com.example.MyApp"
# Run multiple commands
sbt clean compile test
# Execute a sequence of commands from a file
sbt ";" ++ commands.txt
# Set a specific setting for a single command
sbt "set scalaVersion := \"2.13.10\"" compile
build.sbt Configuration Examples
Project Definition
// build.sbt
name := "my-scala-app"
version := "0.1.0"
scalaVersion := "2.13.10"
Dependencies
// build.sbt
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "3.3.0",
"com.typesafe.akka" %% "akka-actor" % "2.6.19",
"org.scalatest" %% "scalatest" % "3.2.11" % Test // % Test scopes it for testing only
)
%%automatically selects the Scala binary version (e.g.,2.13).
Scala Native Packager Plugin
// build.sbt
// Requires adding the plugin in project/plugins.sbt
enablePlugins(JavaAppPackaging, DockerPlugin)
// For JavaAppPackaging
mainClass in Compile := Some("com.example.MainApp")
// For DockerPlugin
packageName in Docker := "my-scala-app"
dockerBaseImage := "openjdk:11-jdk-slim"
Assembly Plugin (Fat JAR)
// build.sbt
// Requires adding the plugin in project/plugins.sbt
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
project/plugins.sbt for Plugin Configuration
// project/plugins.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.9.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.10.0")
Common Patterns
Compiling and Packaging
sbt clean compile package
Cleans previous builds, compiles the source code, and creates a JAR file in the target/scala-2.13/ directory.
Running Tests
sbt test
Executes all tests defined in the src/test directory.
Running a Main Class
sbt "runMain com.example.MyMainClass arg1 arg2"
Executes the main method of com.example.MyMainClass with optional arguments.
Creating a Fat JAR (with sbt-assembly)
sbt assembly
Creates a single executable JAR file containing all dependencies in target/scala-2.13/.
Creating a Docker Image (with sbt-native-packager)
sbt docker:publish
Builds and publishes a Docker image to your configured Docker registry.
Checking for Dependency Updates
sbt dependencyUpdates
Lists all dependencies that have newer versions available.
Running on a Different Scala Version
sbt "++2.12.15 test"
Runs the test command using Scala version 2.12.15.
Aggregating Projects
If you have a multi-module project with a root build, you can run tasks across all modules:
sbt clean compile package
This will execute clean, compile, and package on all sub-projects.
Setting JVM Options
sbt -J-Xmx2G test
Runs the test task with a 2GB heap size.
Running sbt with a specific build definition file
sbt -sbt-boot /path/to/custom/boot.dir -sbt-script /path/to/custom/sbt.jar
Useful for testing or using specific sbt versions.
Gotchas
%%vs%: Always use%%for Scala libraries to ensure the correct Scala binary version is appended to the artifact name (e.g.,akka-actor_2.13). Use%for Java libraries.TestScoping: Dependencies marked with% Testare only available during the test compilation and execution phases. They won’t be included in the final package unless explicitly configured.- Plugin Configuration: Plugins are typically configured in
project/plugins.sbtand their settings are then used inbuild.sbt. - Caching: sbt aggressively caches downloaded artifacts and compilation results. If you suspect a stale cache, use
cleanor explore sbt’s cache directory (~/.sbt/boot/and~/.ivy2/cache/). runvsrunMain:runis a task that executes the main class defined bymainClass in Compile.runMainallows you to specify a main class explicitly, which is often more convenient.- Build Definition Reloading: When you change
build.sbtorproject/plugins.sbt, sbt will automatically detect the changes and reload the build. You’ll see a message like[info] Set current project to .... - Inter-Project Dependencies: In multi-module projects, ensure dependencies between projects are correctly declared using
dependsOninbuild.sbt. sbt clean: While useful,sbt cleandeletes everything in thetargetdirectory. Be mindful of this if you have generated files you want to keep.fork in run := true: By default,runexecutes in the same JVM as sbt. For applications requiring specific JVM settings or to avoid classpath conflicts, settingfork in run := trueinbuild.sbtwill run your application in a separate process.