Scala SBT Build Tool
SBT (Scala Build Tool) is the standard build tool for Scala projects. It compiles your code, runs tests, manages library dependencies, packages your application, and provides an interactive shell for running tasks. Every real Scala project uses SBT or a compatible alternative like Mill.
Project Structure
my-project/
├── build.sbt ← project definition (name, version, deps)
├── project/
│ ├── build.properties ← SBT version
│ └── plugins.sbt ← SBT plugins
└── src/
├── main/
│ ├── scala/ ← your Scala source files
│ └── resources/ ← config files, assets
└── test/
├── scala/ ← test files
└── resources/ ← test resources
build.sbt — The Project File
// build.sbt
name := "my-scala-app"
version := "1.0.0"
scalaVersion := "3.3.1"
// Add library dependencies
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-core" % "2.10.0",
"io.circe" %% "circe-core" % "0.14.6",
"org.scalatest" %% "scalatest" % "3.2.17" % Test
)
// Compiler options
scalacOptions ++= Seq(
"-deprecation", // warn on deprecated APIs
"-feature", // warn on advanced features
"-unchecked" // warn on unchecked type patterns
)
Common SBT Commands
Command What it does
─────────────── ─────────────────────────────────────────────
compile Compile all source files
run Compile and run the main class
test Compile and run all tests
clean Delete compiled files
reload Reload build.sbt after changes
console Open Scala REPL with project classpath loaded
package Create a JAR file
assembly Create a fat JAR with all dependencies
update Download all declared dependencies
~compile Watch for changes and auto-recompile
~run Watch and auto-run on every change
~test Watch and auto-test on every change
Running SBT
// Start SBT interactive shell
$ sbt
// In the SBT shell:
sbt> compile
sbt> run
sbt> test
sbt> exit
// Or run a single command
$ sbt compile
$ sbt run
$ sbt "runMain com.example.MyApp"
Multiple Modules (Multi-project Build)
// build.sbt for a multi-project setup
lazy val common = project
.in(file("common"))
.settings(
name := "common",
scalaVersion := "3.3.1"
)
lazy val api = project
.in(file("api"))
.dependsOn(common)
.settings(
name := "api",
scalaVersion := "3.3.1",
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.5.0"
)
lazy val root = project
.in(file("."))
.aggregate(common, api)
root (aggregates all)
├── common (shared utilities)
│ shared by
└── api (depends on common)
project/build.properties
// Set the SBT version your project requires
sbt.version=1.9.7
project/plugins.sbt — Adding Plugins
// Common plugins
// Create a fat JAR with all dependencies
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.5")
// Generate code coverage reports
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9")
// Format Scala code automatically
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
// Native Scala packaging
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.16")
Dependency Scopes
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-core" % "2.10.0", // all scopes
"org.scalatest" %% "scalatest" % "3.2.17" % Test, // test only
"ch.qos.logback" % "logback-classic" % "1.4.7" % Runtime // runtime only
)
No scope → available in compile, test, run
% Test → only in test compilation and execution
% Runtime → only at runtime (not at compile time)
% Provided → available at compile time, NOT bundled in JAR
Running a Specific Main Class
// In build.sbt — set the default main class
mainClass := Some("com.example.Main")
// Or specify when running
$ sbt "runMain com.example.ServerApp"
$ sbt "runMain com.example.BatchJob"
SBT Console — REPL with Dependencies
$ sbt console
// Inside SBT console — all project classes and dependencies available
scala> import cats.syntax.all._
scala> import com.example.MyService
scala> val result = MyService.compute(42)
Useful SBT Settings
// build.sbt
// Fork a new JVM for run (useful for server apps)
fork := true
// Pass JVM arguments
javaOptions ++= Seq("-Xmx2g", "-Xms512m")
// Show full stack traces in test failures
testOptions += Tests.Argument("-oF")
// Aggregate test results across sub-projects
Test / aggregate := true
The %% vs % Difference
// %% appends Scala version automatically
"org.typelevel" %% "cats-core" % "2.10.0"
// becomes: "org.typelevel" % "cats-core_3" % "2.10.0" (for Scala 3)
// or: "org.typelevel" % "cats-core_2.13" % "2.10.0" (for Scala 2.13)
// % uses the exact artifact name (for Java libraries)
"com.google.guava" % "guava" % "32.1.3-jre"
// Java libraries have no Scala version suffix
SBT is more than a build tool — it is the foundation of the entire Scala development workflow. Every plugin, deployment pipeline, and CI system integrates through SBT. Understanding its project structure and basic commands is essential before working on any real Scala project.
