Library dependencies can be added in two ways:
Most people use managed dependencies instead of unmanaged. But unmanaged can be simpler when starting out.
Unmanaged dependencies work like this: add jars to
lib and they will be
placed on the project classpath. Not much else to it!
lib go on all the classpaths (for
console). If you wanted to change the classpath for just one of
those, you would adjust
Compile / dependencyClasspath or
Runtime / dependencyClasspath for example.
There’s nothing to add to
build.sbt to use unmanaged dependencies,
though you could change the
unmanagedBase key if you’d like to use a
different directory rather than
custom_lib instead of
unmanagedBase := baseDirectory.value / "custom_lib"
baseDirectory is the project’s root directory, so here you’re changing
unmanagedBase depending on
baseDirectory using the special
as explained in task graph.
There’s also an
unmanagedJars task which lists the jars from the
unmanagedBase directory. If you wanted to use multiple directories or do
something else complex, you might need to replace the whole
unmanagedJars task with one that does something else, e.g. empty the list for
Compile configuration regardless of the files in
Compile / unmanagedJars := Seq.empty[sbt.Attributed[java.io.File]]
sbt uses Coursier to implement managed dependencies, so if you’re familiar with Coursier, Apache Ivy or Maven, you won’t have much trouble.
Most of the time, you can simply list your dependencies in the setting
libraryDependencies. It’s also possible to write a Maven POM file or Ivy
configuration file to externally configure your dependencies, and have
sbt use those external configuration files. You can learn more about
Declaring a dependency looks like this, where
revision are strings:
libraryDependencies += groupID % artifactID % revision
or like this, where
configuration can be a string or a
Configuration value (such as
libraryDependencies += groupID % artifactID % revision % configuration
libraryDependencies is declared in
val libraryDependencies = settingKey[Seq[ModuleID]]("Declares managed dependencies.")
% methods create
ModuleID objects from strings, then you add those
Of course, sbt (via Coursier) has to know where to download the module. If your module is in one of the default repositories sbt comes with, this will just work. For example, Apache Derby is in the standard Maven2 repository:
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3"
If you type that in
build.sbt and then
update, sbt should download Derby
to the Coursier cache. (By the way,
update is a dependency
compile so there’s no need to manually type
update most of the time.)
Of course, you can also use
++= to add a list of dependencies all at
libraryDependencies ++= Seq( groupID % artifactID % revision, groupID % otherID % otherRevision )
In rare cases you might find reasons to use
If you use
organization %% moduleName % version rather than
organization % moduleName % version (the difference is the double
organization), sbt will add your project’s binary Scala version to the artifact
name. This is just a shortcut. You could write this without the
libraryDependencies += "org.scala-stm" % "scala-stm_2.13" % "0.9.1"
scalaVersion for your build is
2.13.12, the following is
identical (note the double
libraryDependencies += "org.scala-stm" %% "scala-stm" % "0.9.1"
The idea is that many dependencies are compiled for multiple Scala versions, and you’d like to get the one that matches your project to ensure binary compatibility.
See Cross Building for some more detail on this.
organization % moduleName % version does not have to be a
single fixed version. Ivy can select the latest revision of a module
according to constraints you specify. Instead of a fixed revision like
"1.6.1", you specify
"[1.0,)". See the
documentation for details.
Occasionally a Maven “version range” is used to specify a dependency
(transitive or otherwise), such as
[1.3.0,). If a specific version
of the dependency is declared in the build, and it satisfies the
range, then sbt will use the specified version. Otherwise, Coursier could
go out to the Internet to find the latest version. This would result
to a surprising behavior where the effective version keeps changing
over time, even though there’s a specified version of the library that
satisfies the range condition.
Maven version ranges will be replaced with its lower bound if the
build so that when a satisfactory version is found in the dependency
graph it will be used. You can disable this behavior using the JVM
Not all packages live on the same server; sbt uses the standard Maven2 repository by default. If your dependency isn’t on one of the default repositories, you’ll have to add a resolver to help Ivy find it.
To add an additional repository, use
resolvers += name at location
with the special
at between two strings.
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
resolvers key is defined in
Keys like this:
val resolvers = settingKey[Seq[Resolver]]("The user-defined additional resolvers for automatically managed dependencies.")
at method creates a
Resolver object from two strings.
sbt can search your local Maven repository if you add it as a repository:
resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
or, for convenience:
resolvers += Resolver.mavenLocal
See Resolvers for details on defining other types of repositories.
resolvers does not contain the default resolvers; only additional ones
added by your build definition.
resolvers with some default repositories to form
Therefore, to change or remove the default resolvers, you would need to
externalResolvers instead of
Often a dependency is used by your test code (in
is compiled by the
Test configuration) but not your main code.
If you want a dependency to show up in the classpath only for the
configuration and not the
Compile configuration, add
% "test" like this:
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3" % "test"
You may also use the type-safe version of
Test configuration as follows:
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3" % Test
Now, if you type
show Compile/dependencyClasspath at the sbt interactive
prompt, you should not see the derby jar. But if you type
show Test/dependencyClasspath, you should see the derby jar in the list.
There are more details and tips-and-tricks related to library dependencies on this page.