Published 2013-09-19.
Last modified 2019-11-05.
Time to read: 10 minutes.
This lecture discusses SBT tasks and settings.
This lecture discusses the functionality provided by sbt on macOS, Linux and WSL.
The native Windows installer places a file called sbt.bat
script in C:\Program Files (x86)\sbt\bin
.
The Windows sbt.bat
script does not support the features I describe in this section.
That’s fine, because you would never use native Windows to develop Scala code, right?
sbt Script
Sbt
is actually a Java jar that is normally launched by a bash
script called sbt
.
To discover where the bash
script resides, type:
$ which sbt /usr/bin/sbt
You can discover the command-line arguments that the sbt
bash script supports using the -h
option.
$ sbt -h
Usage: sbt [options]
-h | -help print this message
-v | -verbose this runner is chattier
-d | -debug set sbt log level to debug
-no-colors disable ANSI color codes
-sbt-create start sbt even if current directory contains no sbt project
-sbt-dir <path> path to global settings/plugins directory (default: ~/.sbt)
-sbt-boot <path> path to shared boot directory (default: ~/.sbt/boot in 0.11 series)
-ivy <path> path to local Ivy repository (default: ~/.ivy2)
-mem <integer> set memory options (default: 1024, which is -Xms1024m -Xmx1024m -XX:ReservedCodeCacheSize=128m -XX:MaxMetaspaceSize=256m)
-no-share use all local caches; no sharing
-no-global uses global caches, but does not use global ~/.sbt directory.
-jvm-debug <port> Turn on JVM debugging, open at the given port.
-batch Disable interactive mode
# sbt version (default: from project/build.properties if present, else latest release)
-sbt-version <version> use the specified version of sbt
-sbt-jar <path> use the specified jar as the sbt launcher
-sbt-rc use an RC version of sbt
-sbt-snapshot use a snapshot version of sbt
# java version (default: java from PATH, currently java version "1.8.0_201")
-java-home <path> alternate JAVA_HOME
# jvm options and output control
JAVA_OPTS environment variable, if unset uses ""
.jvmopts if this file exists in the current directory, its contents
are appended to JAVA_OPTS
SBT_OPTS environment variable, if unset uses ""
.sbtopts if this file exists in the current directory, its contents
are prepended to the runner args
/etc/sbt/sbtopts if this file exists, it is prepended to the runner args
-Dkey=val pass -Dkey=val directly to the java runtime
-J-X pass option -X directly to the java runtime
(-J is stripped)
-S-X add -X to sbt’s scalacOptions (-S is stripped)
In the case of duplicated or conflicting options, the order above
shows precedence: JAVA_OPTS lowest, command line options highest.
If this is the first time you run SBT, there will be a long pause while it downloads the entire known universe.
Two command-line options are worthy of special mention: -jvm-debug
and -mem
.
Enabling Remote Debugging
You can enable remote debugging on any JVM program, using a JVM option similar to this.
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9999
The sbt
script has a handy command-line option, -jvm-debug
, which does the same thing.
To use it, just specify the port.
$ sbt -jvm-debug 9999 run
The sbt script will launch your Scala program and you can attach a debugger to it if the program gives you time to do so before it finishes.
If you want the debugger to pause while you attach a debugger, you need to specify the long form, with suspend=y
,
and preface the options with -J
.
$ sbt -JXrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999 run
Here is a variant that saves all output to a file called output.txt
.
$ sbt -no-colors -J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999 run &> output.txt
Allocating Memory
The -mem
option allocates the total amount of memory specified according to logic present in sbt-launch.bash
,
a bash script invoked by sbt
.
Thus if you have 2G of memory for your Scala program, specify -mem 2G
and the memory will be allocated properly.
SBT Command Line Tasks
Following are commonly used command-line tasks. Here is a more complete list. Here is an index of common methods, types, and values you might find in an sbt build definition.
- clean
- Deletes files produced by the build, such as generated sources, compiled classes, and task caches.
It does not remove all compiled artifacts.
Here is deeper clean:
Shell$ rm -rf target/*
- compile
- Compiles sources; automatically runs
update
first. - ~compile
- Continuously compiles sources each time a file changes.
- console
- Starts the Scala interpreter with the project dependencies, compiled code and
resources
on the classpath. - doc
- Generates Scaladoc for
src/main
intotarget/api/index.html
. See alsotest:doc
. - help command*
- Displays help message or prints detailed help on requested commands.
- offline
- Configures SBT to work without a network connection where possible.
- project
- Selects a specific SBT project in an SBT project that has multiple subprojects
- run
- Runs a main class; compiles if necessary.
Currently does not detect Java classes with static void
main()
methods. However, you can type the following to see all Java and Scala entry points:
Shell$ sbt ’show discoveredMainClasses’
- ~run
- Runs a main class, recompiling each time you change a file.
Currently does not detect Java classes with static void
main()
methods. - runMain
-
Runs a main class, passing along arguments provided on the command line.
This task can also be specified as
run-main
. For example:
Shell$ sbt ’runMain com.micronautics.akka.dispatch.futureScala.Zip’
Shell$ sbt "runMain com.micronautics.akka.dispatch.futureScala.Zip"
- test
- Executes all tests that are not marked with
ignore
. - ~testQuick
- Like test, but uses incremental compiler to only run test classes that are affected by your latest change.
This task can also be specified as
~test-quick
. - testOnly
- Executes tests in one test class.
This task can also be specified as
test-only
. For example:
Shell$ sbt ’testOnly com.blah.MyTest’
Shell$ sbt "testOnly com.blah.MyTest"
- update
- Download binary dependencies, including transitive dependencies. If your project uses dependencies that are snapshots, the most recent versions are downloaded.
- updateClassifiers
- Download sources and Javadoc for all project dependencies
- updateSbtClassifiers
- Download sources and Javadoc for all meta-project dependencies
Do You Commute to Work?
If you commute to work and would like to learn Scala or do Scala programming with your laptop, but you don’t have a WiFi connection while en route, here is the magic incantation that you should type before leaving:
$ git pull
$ sbt ";update ;updateClassifiers ;set offline:=true"
When you get to the office, type:
$ sbt ";set offline:=false"
Playing with SBT Console
The SBT console is a REPL that provides your entire project, including dependencies, on the classpath
.
This allows you to manually invoke the code in your project in an interactive session, providing that your code compiles.
The courseNotes
directory in the git repository provided with this course contains a sample project.
Start by cloning the repository.
$ cd ~/myScalaProjects
$ git clone https://scalaStudent@bitbucket.org/mslinn/course_scala_intro_code.git
Now change to the courseNotes/
directory.
$ cd course_scala_intro_code/courseNotes
The dependencies are specified in build.sbt
like this.
libraryDependencies ++= Seq( "org.specs2" %% "specs2-core" % "4.5.1" % Test withSources(), "org.specs2" %% "specs2-junit" % "4.5.1" % Test withSources(), "org.scalatest" %% "scalatest" % "3.1.0-SNAP9" % Test withSources(), "junit" % "junit" % "4.12" % Test // Scala IDE requires this; IntelliJ IDEA does not )
Also notice the initialCommands
section in the same build.sbt
file that specifies
the command executed when sbt console
, sbt consoleQuick
,
but not the sbt consoleProject tasks
are executed.
initialCommands in console := """ import java.io.File import scala.language.postfixOps import java.net.URL import scala.util.control.NoStackTrace import scala.util.{Try,Success,Failure} """.stripMargin
The courseNotes/
project defines several classes in the com.micronautics.scalaIntro
package,
including one called ScalaClass3
.
Let’s use the SBT console
to play with that class.
The first time you run that command it might take a long time to download many jars.
$ sbt console [info] Loading settings for project global-plugins from idea.sbt ... [info] Loading global plugins from /home/mslinn/.sbt/1.0/plugins [info] Loading settings for project coursenotes-build from build.sbt ... [info] Loading project definition from /mnt/c/course_scala_intro_code/courseNotes/project [info] Updating ProjectRef(uri("file:/mnt/c/course_scala_intro_code/courseNotes/project/"), "coursenotes-build")... [info] Done updating. [info] Loading settings for project coursenotes from build.sbt ... [info] Set current project to intro-scala-course (in build file:/mnt/c/course_scala_intro_code/courseNotes/) [info] Updating ... [info] Done updating. [info] Compiling 43 Scala sources and 2 Java sources to /mnt/c/course_scala_intro_code/courseNotes/target/scala-2.12/classes ... [warn] /mnt/c/course_scala_intro_code/courseNotes/src/main/scala/TypeHierarchy.scala:37:66: fruitless type test: a value of type DogHog.Dog cannot also be a DogHog.Hog [warn] println(s"Should a dog be compared to a hog? ${dog.isInstanceOf[Hog]}") [warn] ^ [warn] /mnt/c/course_scala_intro_code/courseNotes/src/main/scala/CaseClasses.scala:32:98: comparing case class values of types CaseClasses2.Dog and CaseClasses2.Hog using `==’ will always yield false [warn] println(s"Comparing ${dog1.name} with ${hog.name} even though we should not do so gives: ${dog1==hog}") [warn] ^ [warn] /mnt/c/course_scala_intro_code/courseNotes/src/main/scala/CaseClasses.scala:84:39: comparing case class values of types StdMethods.Frog9a and StdMethods.Frog9c using `==’ will always yield false [warn] println(s"frog9a == frog9c=${frog9a == frog9c}") [warn] ^ [warn] there were three feature warnings; re-run with -feature for details [warn] four warnings found [info] Done compiling. [info] Starting scala interpreter... Welcome to Scala 2.12.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_201). Type in expressions for evaluation. Or try :help.
scala> import com.micronautics.scalaIntro._ import com.micronautics.scalaIntro._
scala> val sc3 = new ScalaClass3(1, 2.0) sc3: com.micronautics.scalaJava.ScalaClass3 = prop1=01; prop2=2.0; prop3=02; prop4=6.0
SBT Console Help
SBT console has its own command set, which you can view from the SBT console by typing :help
, like this:
scala> :help All commands can be abbreviated, e.g., :he instead of :help. :completions <string> output completions for the given string :edit <id>|<line> edit history :help [command] print this summary or command-specific help :history [num] show the history (optional num is commands to show) :h? <string> search the history :imports [name name ...] show import history, identifying sources of names :implicits [-v] show the implicits in scope :javap <path|class> disassemble a file or class name :line <id>|<line> place line(s) at the end of history :load <path> interpret lines in a file :paste [-raw] [path] enter paste mode or paste a file :power enable power user mode :quit exit the interpreter :replay [options] reset the repl and replay all previous commands :require <path> add a jar to the classpath :reset [options] reset the repl to its initial state, forgetting all session entries :save <path> save replayable session to a file :sh <command line> run a shell command (result is implicitly => List[String]) :settings <options> update compiler options, if possible; see reset :silent disable/enable automatic printing of results :type [-v] <expr> display the type of an expression without evaluating it :kind [-v] <type> display the kind of a type. see also :help kind :warnings show the suppressed warnings from the most recent line which had any
Persisting, Restoring and Resetting REPL Sessions
The :save
and :load
commands are especially useful.
You can use them to save and reload your Scala REPL or sbt console
sessions,
including definitions you create on the fly for classes, traits, methods and variables.
Only your command input is saved; the output is not saved.
Because the REPL session file is stored in plain text, you can use any text editor to modify the commands.
Let’s first try out these commands using the Scala REPL.
$ scala Welcome to Scala 2.13.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_201). Type in expressions for evaluation. Or try :help.
scala> val hi = "hi " hi: String = "hi "
scala> hi * 3 res0: String = "hi hi hi "
scala> res0.toUpperCase res1: String = "HI HI HI "
scala> :save hi.repl
scala> :quit
Now lets look at the file we just created, hi.repl
.
I use the convention that the .repl
filetype is for SBT repl sessions, but that is not required.
$ cat hi.repl val hi = "hi " hi * 3 res0.toUpperCase
We can start a new REPL session and load the file containing the saved REPL session.
$ scala Welcome to Scala 2.13.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_201). Type in expressions for evaluation. Or try :help.
scala> :load hi.repl Loading hi... hi: String = "hi " res2: String = "hi hi hi " res3: String = "HI HI HI "
The :reset
commant initializes REPL to its default state, and flushes the history.
scala> :reset Resetting interpreter state. Forgetting this session history:
val hi = "hi " hi * 3 res0.toUpperCase
Forgetting all expression results and named terms: $intp, hi
scala> :load hi.repl Loading hi.repl... hi: String = "hi " res0: String = "hi hi hi " res1: String = "HI HI HI "
SBT console supports the :save
, :load
and :reset
commands just the same.
$ sbt console ...snip ... Welcome to Scala 2.13.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_201). Type in expressions for evaluation. Or try :help.
scala> val hi = "hi " hi: String = "hi "
scala> hi * 3 res0: String = "hi hi hi "
scala> res0.toUpperCase res1: String = "HI HI HI "
scala> :save "hi.repl"
scala> :reset Resetting interpreter state. Forgetting this session history:
val hi = "hi " hi * 3 res0.toUpperCase
Forgetting all expression results and named terms: $intp, hi
scala> :load hi.repl Loading hi.repl... hi: String = "hi " res0: String = "hi hi hi " res1: String = "HI HI HI "
scala>
Exercise – Experiment
Now you can experiment live with your partially complete code base! Try the tab completion feature.
Managing Conflicting Dependencies
This section was largely made obsolete by Scala 3. If you still use Scala 2, then you will need this information. Otherwise, skip this section.
It is possible that transitive dependencies originating from various explicitly specified dependencies might have conflicting versions.
If that happens, you will see a message something like this whenever sbt update
is run.
Remember that sbt compile
first invokes sbt update
, and sbt run
first invokes sbt compile
.
[warn] Multiple dependencies with the same organization/name but different versions. To avoid conflict, pick one version: [warn] * org.apache.httpcomponents:httpclient:(4.2.1, 4.3.6) [warn] There may be incompatibilities among your library dependencies. [warn] Here are some of the libraries that were evicted: [warn] * com.github.nscala-time:nscala-time_2.10:2.0.0 -> 2.4.0

If you ignore this problem, and run your program, don’t be surprised if you see a runtime error message like:
Exception: Attempt to invoke virtual method
.
This happens because a method implemented in one version of the transitive dependency was invoked but the other
version of the dependency was present in the classpath.
There are two three ways of handling problems like this: ConflictManager
, force()
and exclude()
.
Only use force()
or exclude()
, not both.
Use ConflictManager
This was released October 2019:
ConflictManager
.
To use it in an SBT project, add the following to project/plugins.sbt
.
// See https://www.scala-lang.org/2019/10/17/dependency-management.html#static-analysis-checks addSbtPlugin("ch.epfl.scala" % "sbt-missinglink" % "0.2.0")
// See https://get-coursier.io/docs/sbt-coursier addSbtPlugin("io.get-coursier" % "sbt-coursier" % "2.0.0-RC4")
Add this to build.sbt
:
versionReconciliation += "*" % "*" % "semver"
Then type the following at a command prompt:
$ sbt update
Use force()
You can force SBT to use a specific version of a dependency by explicitly declaring the version that you need,
along with the force()
option.
"org.apache.httpcomponents" % "httpclient" % "4.3.6" withSources() force()
The force()
option has the result that only the version of the dependency that you request is included,
and no other versions that might be otherwise brought in as transitive dependencies will be used.
Be aware that if you force a version of a transitive dependency,
you might need to force all the other transitive dependencies of the dependency that referenced it.
Use exclude()
Instead of using force()
, it is generally considered better form to explicitly exclude transitive
dependencies in relation to the explicit dependencies that bring them in.
However, force()
can be easier to use than exclude()
,
especially when only one transitive dependency was brought in by an explicit dependency,
and you just want to force that one dependency’s version.
For example, the nscala-time
dependency brings in the joda-time
dependency.
The following tells SBT to include nscala-time
v2.4.0, but not the version of joda-time
\
that it normally brings along as a transitive dependency.
The exclude()
option merely suppresses the transitive dependency, unlike force()
,
which ensures that only a specific version of a dependency be used, even if other versions might otherwise have
been included as transitive dependencies.
"com.github.nscala-time" %% "nscala-time" % "2.4.0" exclude("joda-time", "joda-time")
Handy Settings
These SBT settings naturally require SBT, so they do not work in a Scala REPL started with the scala
command.
Cross-Version Support For Scala Sources
If your project has code that only works on a specific version of Scala,
place it in a specially named branch of the src/main/
directory.
For example, if you have code specific to each of Scala 2.13.0-RC1, 2.11.x and 2.12.x,
put your code in directories called src/main/scala-<scalaBinaryVersion>/
.
src/ main/ scala/ anotherPackage/ X.scala scala-2.13.0-RC1/ SomethingMagic.scala my/ package/ Blah2_10.scala scala-2.11/ SomethingMagic.scala my/ package/ CodeForScala2_11.scala scala-2.12/ SomethingMagic.scala anotherPackage/ X.scala
Notice that a version of SomethingMagic.scala
is provided for each of Scala 2.13.0-RC1 and 2.11 and 2.12,
but the other files are not.
There is no requirement that a unique version of a file exist for each Scala version.
This feature is enabled when the SBT crossPaths
setting is true
, which is the default.
Normally you would only specify this setting in build.sbt
if you wish to disable it, like this.
crossPaths := false
When this setting is enabled, sbt includes src/main/scala-<scalaBinaryVersion>/
to the SBT
Compile
scope addition to src/main/scala
.
scala
BinaryVersion
is for major Scala versions only; for example,
both Scala 2.11.5 and Scala 2.11.8 both resolve to the same directory:
src/main/scala-2.11
.
Clear Screen
You can clear the screen when running SBT at any time by pressing Ctrl-L. That works pretty well, but if you want this to happen each time a build starts you have options.
The SBT Global Setup lecture discussed how .sbtrc
could be used to define SBT command aliases that cleared the screen each time an update or compilation was triggered.
Here is a better way, using the
sbt.Watched
object which will cause any triggered SBT command such as ~update
,
~compile
or ~run
to first clear the screen.
There are two ways to work with sbt.Watched
.
-
You can specify this setting for any SBT project by typing the following in response to an SBT prompt:
Shell
$ sbt [info] Loading settings for project global-plugins from idea.sbt ... [info] Loading global plugins from /home/mslinn/.sbt/1.0/plugins [info] Loading settings for project coursenotes-build from build.sbt ... [info] Loading project definition from /mnt/c/course_scala_intro_code/courseNotes/project [info] Loading settings for project coursenotes from build.sbt ... [info] Set current project to intro-scala-course (in build file:/mnt/c/course_scala_intro_code/courseNotes/) [info] sbt server started at local:///home/mslinn/.sbt/1.0/server/5fe9d8e8b553e8f095e1/sock
>set triggeredMessage in ThisBuild := Watched.clearWhenTriggered [info] Defining {.}/*:triggeredMessage [info] The new value will be used by *:watch [info] Reapplying settings... [info] Set current project to IntroScalaCourse (in build file:/var/work/course_scala_intermediate_code/courseNotes/)
> ~compile // screen automatically clears prior to compilation -
You can permanently apply this setting to a project by adding the following to your
build.sbt
file:build.sbt fragmenttriggeredMessage in ThisBuild := Watched.clearWhenTriggered
Now whenever you type the following, the screen will be cleared each time a changed file triggers the recompilation and rerunning of the project.
Shell$ sbt ~run
Thebuild.sbt
file for the courseNotes project already has this line in it, but it is commented out. Why don’t you uncomment it and see if you like this feature?
Control-C Trap
By default, when you run
or test
an application from SBT and type CTRL-C your program is terminated and SBT exits.
The following setting installs a Control-C trap, which causes your program to stop without exiting SBT.
Again, there are two ways to use it.
-
You can specify this setting for any SBT project by typing the following in response to an SBT prompt:
Shell
$ sbt [info] Loading settings for project global-plugins from idea.sbt ... [info] Loading global plugins from /home/mslinn/.sbt/1.0/plugins [info] Loading settings for project coursenotes-build from build.sbt ... [info] Loading project definition from /mnt/c/course_scala_intro_code/courseNotes/project [info] Loading settings for project coursenotes from build.sbt ... [info] Set current project to intro-scala-course (in build file:/mnt/c/course_scala_intro_code/courseNotes/) [info] sbt server started at local:///home/mslinn/.sbt/1.0/server/5fe9d8e8b553e8f095e1/sock
> set cancelable in Global := true [info] Defining */*:cancelable [info] The new value will be used by */*:taskCancelStrategy [info] Reapplying settings... [info] Set current project to IntroScalaCourse (in build file:/var/work/course_scala_intermediate_code/courseNotes/)
> run // Typing Control-C after run causes the program to stop without exiting SBT - You can permanently apply this setting to a project by adding the following to your
build.sbt
file:cancelable in Global := true
Handy One-Liners
Some of these one-liners are inspired by the
SBT manual,
which can be a bit hard to read.
I used the courseNotes
project to generate this output.
History Commands
Rerun the last command with !!
, show the command history with !:
and display information about all the history-related commands with !
.
$ sbt [info] Loading settings for project global-plugins from idea.sbt ... [info] Loading global plugins from /home/mslinn/.sbt/1.0/plugins [info] Loading settings for project coursenotes-build from build.sbt ... [info] Loading project definition from /mnt/c/course_scala_intro_code/courseNotes/project [info] Loading settings for project coursenotes from build.sbt ... [info] Set current project to intro-scala-course (in build file:/mnt/c/course_scala_intro_code/courseNotes/) [info] sbt server started at local:///home/mslinn/.sbt/1.0/server/5fe9d8e8b553e8f095e1/sock > ! History commands: !! Execute the last command again !: Show all previous commands !:n Show the last n commands !n Execute the command with index n, as shown by the !: command !-n Execute the nth command before this one !string Execute the most recent command starting with ’string’ !?string Execute the most recent command containing ’string’
Get Basic Information About an SBT Project
$ sbt about ...lots of output ... [info] This is sbt 1.2.8 [info] The current project is ProjectRef(uri("file:/mnt/c/course_scala_intro_code/courseNotes/"), "coursenotes") 2.12.8 [info] The current project is built against Scala 2.12.8 [info] Available Plugins [info] - com.orrsella.sbtsublime.SublimePlugin [info] - com.typesafe.sbteclipse.plugin.EclipsePlugin [info] - sbt.ScriptedPlugin [info] - sbt.plugins.CorePlugin [info] - sbt.plugins.Giter8TemplatePlugin [info] - sbt.plugins.IvyPlugin [info] - sbt.plugins.JUnitXmlReportPlugin [info] - sbt.plugins.JvmPlugin [info] - sbt.plugins.SbtPlugin [info] sbt, sbt plugins, and build definitions are using Scala 2.12.7 %}
Examine the Classpath Used For Compilation
You can’t see it in the courseNotes
project because it does not have any dependencies.
Here is output from another project.
$ sbt "show compile:dependencyClasspath" ...lots of output ... [info] * Attributed(/opt/activator-dist-1.3.6/repository/org.scala-lang/scala-library/2.11.7/jars/scala-library.jar)
Examine the Classpath Used for Unit Tests
Unit tests require a lot of dependencies.
$ sbt "show test:dependencyClasspath" ... lots of output ... [info] * Attributed(/mnt/c/course_scala_intro_code/courseNotes/target/scala-2.12/classes) [info] * Attributed(/home/mslinn/.ivy2/cache/org.specs2/specs2-junit_2.12/jars/specs2-junit_2.12-4.5.1.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scalatest/scalatest_2.12/jars/scalatest_2.12-3.1.0-SNAP9.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.specs2/specs2-core_2.12/jars/specs2-core_2.12-4.5.1.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/junit/junit/jars/junit-4.12.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.1.0-SNAP9.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scala-sbt/test-interface/jars/test-interface-1.0.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.specs2/specs2-matcher_2.12/jars/specs2-matcher_2.12-4.5.1.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.hamcrest/hamcrest-core/jars/hamcrest-core-1.3.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.specs2/specs2-common_2.12/jars/specs2-common_2.12-4.5.1.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.2.0.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12/bundles/scala-parser-combinators_2.12-1.1.1.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.8.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.specs2/specs2-fp_2.12/jars/specs2-fp_2.12-4.5.1.jar) [info] * Attributed(/home/mslinn/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.8.jar) [success] Total time: 1 s, completed Apr 26, 2019 10:54:19 AM %}
List Main Classes
This does not show Java main classes, unfortunately. This list is alphabetically sorted.
$ sbt "show compile:discoveredMainClasses" ...lots of output... [info] * AbstractSealed1 [info] * AbstractSealed2 [info] * Aliases [info] * Animals7 [info] * Animals8 [info] * Auxiliary [info] * Bicycle [info] * BlendedEnums [info] * BoldlyGo [info] * CaseClasses1 [info] * CaseClasses2 [info] * CaseClasses3 [info] * Closures [info] * ComplexCase [info] * DogHog [info] * EitherDemo1 [info] * EitherDemo2 [info] * ExtendJavaSet [info] * Extractor [info] * Extractors1 [info] * Extractors2 [info] * Extractors3 [info] * Fib [info] * Fib3 [info] * Fib4 [info] * FibBad1 [info] * FibBad2 [info] * FibCheck [info] * FibMem [info] * FibWhile [info] * FormattedStringSamples [info] * Fun [info] * Fun2 [info] * Fun3 [info] * GetSetDemo1 [info] * GetSetDemo2 [info] * HeirGround [info] * ImplementedTrait [info] * JavaEnum [info] * LazyEval [info] * LazyEvalLevel1 [info] * MaybeDog2 [info] * MultipleParamLists [info] * OperatorOverload [info] * OptionDemo1 [info] * OptionDemo2 [info] * PMQuiz [info] * PackageDemo [info] * PatMatch1 [info] * PatMatch2 [info] * PatMatch3 [info] * PatMatch4 [info] * PatMatch5 [info] * PatMatch6 [info] * PureTrait [info] * Quine [info] * ScalaEnum [info] * ScalaEnumCase [info] * SealedDemo [info] * StdMethods [info] * TimedDemo [info] * TryCatch [info] * TryCatch2 [info] * TryCatch3 [info] * TryCatch4 [info] * TryCatch5 [info] * TryDemo [info] * TupleDemo [info] * Tweeters [info] * TypeWidening1 [info] * TypeWidening2 [info] * Uniform1 [info] * Uniform2 [info] * VarArgsJava [info] * Wallflower [info] * WhichTrait [info] * WithFun [info] * YodaHeIs [info] * animals.Animals1 [info] * animals.Animals2 [info] * animals.Animals3 [info] * animals.Animals4 [info] * animals.Animals5 [info] * animals.Animals6 [info] * animals.Anonymous1 [info] * animals.Anonymous2 [info] * animals.Anonymous3 [info] * animals.ConcreteClasses [info] * animals.VarArgsScala [info] * com.micronautics.scalaIntro.VisibleMain [info] * solutions.Birds1 [info] * solutions.Birds2 [info] * solutions.Emotions [info] * solutions.Extractor [info] * solutions.Fact [info] * solutions.Fact1 [info] * solutions.FactLoop [info] * solutions.FactMem [info] * solutions.FunSel [info] * solutions.Hello [info] * solutions.PatMatch101a [info] * solutions.TryCatchFinally [info] * solutions.TupleAnswer [info] * solutions.Unapply [info] * solutions.Unapply2 [info] * solutions.WordSearch [success] Total time: 1 s, completed Apr 26, 2019 10:55:10 AM
To run a specific entry point from the list, like Tweeters
, type.
$ sbt "runMain Tweeters"
If you prefer to select the entry point to run from a numbered list, type.
$ sbt run
List Unit Test Classes
$ sbt "show test:definedTestNames" ... lots of output ... [info] Compiling 4 Scala sources to /mnt/c/course_scala_intro_code/courseNotes/target/scala-2.12/test-classes ... [info] Done compiling. [info] * TestScalaTest [info] * solutions.Specs2Solution [info] * Specs2Demo [info] * solutions.ScalaTestSolution [success] Total time: 7 s, completed Apr 26, 2019 10:56:56 AM
To run a specific unit test from the list, like ScalaTestDemo
, type.
$ sbt "testOnly ScalaTestDemo"
If you prefer to run all the unit tests, type.
$ sbt test
Run All Tests In a Specific Subproject
If you have an SBT project that contains multiple subprojects,
you can switch between the subprojects using the project
task.
Here is the transcript of a project I am working on.
One test passes, one test fails.
$ sbt [info] Loading global plugins from /home/mslinn/.sbt/0.13/plugins [info] Loading project definition from /var/work/experiments/play/play25multiproject/project [info] Set current project to root (in build file:/var/work/experiments/play/play25multiproject/) [root] $ projectTAB / common nonPlay root serviceA serviceB {file:/var/work/experiments/play/play25multiproject/} [root] $ project common [info] Set current project to common (in build file:/var/work/experiments/play/play25multiproject/) [common] $ test [info] CommonSpec: [info] Common [info] - should send 404 on a bad request [info] - should render the index page *** FAILED *** [info] 404 was not equal to 200 (CommonSpec.scala:21) [info] ScalaTest [info] Run completed in 1 second, 243 milliseconds. [info] Total number of tests run: 2 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 1, failed 1, canceled 0, ignored 0, pending 0 [info] *** 1 TEST FAILED *** [error] Failed: Total 2, Failed 1, Errors 0, Passed 1 [error] Failed tests: [error] controllers.common.CommonSpec [error] (common/test:test) sbt.TestsFailedException: Tests unsuccessful [error] Total time: 7 s, completed Jul 24, 2016 3:29:00 PM
Here is one way to express this in one line. Note that the semicolon provides a newline character.
$ sbt "; project common; test"
Of course, if you want to run all the common
project’s tests each time a source file or resource in
that project is modified, preface the command with a tilde (~).
$ sbt ~"; project common; test"
Alternative Syntax
Here is an alternative syntax for specifying a project, followed by an SBT task to perform. I again specify the common project should have all tests run.
$ sbt common/test
You can also use this alternative syntax to supply runtime arguments for a specific SBT project:
$ sbt common/run arg1 arg2
Use a Specific Compiler
The ++
task sets the compiler.
To use it from the command line:
$ sbt "++2.13.0! compile"
$ sbt "++2.13.0-RC1! compile"
$ sbt "++2.12.8! compile"
$ sbt "++2.11.12! compile"
$ sbt "++2.10.6! compile"
To use the ++
task from the SBT prompt:
$ sbt > ++2.13.0! [info] Forcing Scala version to 2.13.0 on all projects. [info] Reapplying settings... [info] Set current project to mslinn (in build file:/home/mslinn/work/) > compile
Exploring Direct and Transitive Dependencies
Each dependency that you specify can itself have dependencies – these secondary dependencies are termed transitive dependencies.
For example, NScala-Time
has a transitive dependency on Joda-Time.
You can examine the direct and transitive dependencies after an SBT update
task is run, or another SBT task
runs that invokes update
.
Once this happens, SBT generates reports in target/resolution-cache/reports/
.
There is a separate report for each scope (including internal/private SBT scopes).
The reports are named organization-projectId_scalaVersion-scope.xml
.
For example, a project called test
by the organization com.micronautics
would have a report
for the Compile
scope called com.micronautics-test_2.11-compile.xml
.
The courseNotes
project does not have any runtime dependencies, so lets look at another project I wrote,
awslib
, which has a more complex build.sbt
.
$ git clone https://github.com/mslinn/awslib_scala Cloning into ’awslib_scala’... remote: Counting objects: 1467, done. remote: Compressing objects: 100% (4/4), done. remote: Total 1467 (delta 4), reused 4 (delta 4), pack-reused 1459 Receiving objects: 100% (1467/1467), 427.50 KiB | 0 bytes/s, done. Resolving deltas: 100% (568/568), done. Checking connectivity... done.
$ cd awslib_scala
$ sbt update
This handy one-line command ignores files with sources
in their name, and lists the remaining files of interest.
The file ending with runtime.xml
is the one you are most likely to be interested in.
$ (cd target/resolution-cache/reports; find . -name ’*.xml’ -not -name ’*$sources*’) ./com.micronautics-awslib_scala_2.10-provided.xml ./com.micronautics-awslib_scala_2.10-sources.xml ./com.micronautics-awslib_scala_2.10-docs.xml ./com.micronautics-awslib_scala_2.11-test-internal.xml ./com.micronautics-awslib_scala_2.11-optional.xml ./com.micronautics-awslib_scala_2.10-test-internal.xml ./com.micronautics-awslib_scala_2.11-compile.xml ./org.scala-sbt.temp-temp-module-750703454be73072ce64f1c215ff85550284ae5b-component.xml ./com.micronautics-awslib_scala_2.11-scala-tool.xml ./com.micronautics-awslib_scala_2.11-runtime.xml ./com.micronautics-awslib_scala_2.11-sources.xml ./com.micronautics-awslib_scala_2.11-pom.xml ./com.micronautics-awslib_scala_2.11-provided.xml ./com.micronautics-awslib_scala_2.10-scala-tool.xml ./com.micronautics-awslib_scala_2.11-runtime-internal.xml ./com.micronautics-awslib_scala_2.10-test.xml ./com.micronautics-awslib_scala_2.10-runtime-internal.xml ./com.micronautics-awslib_scala_2.10-plugin.xml ./com.micronautics-awslib_scala_2.11-compile-internal.xml ./com.micronautics-awslib_scala_2.10-compile-internal.xml ./com.micronautics-awslib_scala_2.10-compile.xml ./com.micronautics-awslib_scala_2.10-optional.xml ./com.micronautics-awslib_scala_2.10-ensime-internal.xml ./com.micronautics-awslib_scala_2.11-test.xml ./com.micronautics-awslib_scala_2.10-pom.xml ./com.micronautics-awslib_scala_2.11-ensime-internal.xml ./com.micronautics-awslib_scala_2.11-plugin.xml ./com.micronautics-awslib_scala_2.10-runtime.xml ./com.micronautics-awslib_scala_2.11-docs.xml
You can view these XML files in most web browsers, with the exception of Google Chrome, which cannot use a style sheet to display an XML file.
You can view the most interesting file by typing the following at the command line from the awslib_scala
directory.
$ firefox target/resolution-cache/reports/com.micronautics-awslib_scala_2.10-compile.xml
Even better, here is a bash command that displays the compilation dependencies in Firefox:
$ firefox `find target/resolution-cache/reports/ -name \*compile.xml | grep -v javadoc`
Sample output looks like this:

You can also use IntelliJ IDEA to open the file from the Project pane by:
- Navigating to
target/resolution-cache/reports
/
- Right-clicking on
com.micronautics-introscalacourse_2.11-runtime.xml
- Selecting Open in Browser
- Selecting Firefox

Suppressing the Dependency Report (Supplemental)
SBT has had an experimental feature,
since v0.13.7 which can be enabled by adding this incantation to build.sbt
.
updateOptions := updateOptions.value.withCachedResolution(cachedResoluton = true)
If this statement is present, two things happen:
- Builds become faster because dependency graphs are cached instead of being recomputed
- Dependency reports are no longer generated for the project
Experimental features might be discontinued and are not guaranteed to be present in future releases. Use this feature at your own risk... however this feature has been around for years.
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.