sbt 需要为项目获取 Scala,它可以自动执行此操作,也可以显式配置。为项目配置的 Scala 版本将编译、运行、文档化并为项目代码提供 REPL。编译项目时,sbt 需要运行 Scala 编译器,并为编译器提供类路径,这可能包括多个 Scala jar,例如反射 jar。
最常见的情况是,您想使用仓库中可用的 Scala 版本。唯一需要的配置是您要使用的 Scala 版本。例如,
scalaVersion := "2.10.0"
这将从通过 resolvers
设置配置的仓库中检索 Scala。它将使用此版本构建您的项目:编译、运行、scaladoc 和 REPL。
默认情况下,标准 Scala 库会自动添加为依赖项。如果您想将其配置为与默认值不同,或者您的项目只有 Java 源代码,请设置
autoScalaLibrary := false
为了编译 Scala 源代码,Scala 库需要位于类路径上。当 autoScalaLibrary
为 true 时,Scala 库将位于所有类路径上:测试、运行时和编译。否则,您需要像添加任何其他依赖项一样添加它。例如,以下依赖项定义仅在测试中使用 Scala
autoScalaLibrary := false
libraryDependencies += "org.scala-lang" % "scala-library" % scalaVersion.value % "test"
当使用标准库以外的 Scala 依赖项时,将其添加为正常的托管依赖项。例如,要依赖于 Scala 编译器,
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
请注意,无论上一节中描述的 autoScalaLibrary
设置的值如何,这都是必需的。
为了编译 Scala 代码、运行 scaladoc 并提供 Scala REPL,sbt 需要 scala-compiler
jar。这应该不是项目的正常依赖项,因此 sbt 在特殊的私有 scala-tool
配置中添加了对 scala-compiler
的依赖项。在某些情况下,您可能希望对此进行更多控制。使用 managedScalaInstance
键禁用此自动行为
managedScalaInstance := false
这也会禁用对 scala-library
的自动依赖。如果您不需要 Scala 编译器执行任何操作(编译、REPL、scaladoc 等),则可以到此为止。在这种情况下,sbt 不需要您的项目中的 Scala 实例。否则,sbt 仍然需要访问 Scala 编译器的 jar 文件,用于编译和其他任务。您可以通过在 scala-tool
配置中声明依赖项或通过显式定义 scalaInstance
来提供它们。
在第一种情况下,添加 scala-tool
配置并在该配置中添加对 scala-compiler
的依赖项。组织并不重要,但 sbt 需要模块名称为 scala-compiler
和 scala-library
,以便适当地处理这些 jar 文件。例如,
managedScalaInstance := false
// Add the configuration for the dependencies on Scala tool jars
// You can also use a manually constructed configuration like:
// config("scala-tool").hide
ivyConfigurations += Configurations.ScalaTool
// Add the usual dependency on the library as well on the compiler in the
// 'scala-tool' configuration
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-library" % scalaVersion.value,
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "scala-tool"
)
在第二种情况下,直接构造类型为 ScalaInstance 的值,通常使用 伴生对象 中的方法,并将其分配给 scalaInstance
。您还需要将 scala-library
jar 添加到类路径中,以编译和运行 Scala 源代码。例如,
managedScalaInstance := false
scalaInstance := ...
Compile / unmanagedJars += scalaInstance.value.libraryJar
要使用本地构建的 Scala 版本,请按照下一节中的说明配置 Scala 主目录。Scala 仍然会像以前一样解析,但 jar 文件将来自配置的 Scala 主目录。
从源代码构建 Scala 的结果是 Scala 主目录 <base>/build/pack/
,其中包含一个子目录 lib/
,其中包含 Scala 库、编译器和其他 jar 文件。通过下载和解压缩 Scala 分发版可以获得相同的目录布局。此类 Scala 主目录可以通过设置 scalaHome
来用作 jar 文件的源代码。例如,
scalaHome := Some(file("/home/user/scala-2.10/"))
默认情况下,lib/scala-library.jar
将被添加到非托管类路径中,lib/scala-compiler.jar
将被用于编译 Scala 源代码并提供 Scala REPL。不会在 scala-library
上记录托管依赖项。这意味着 Scala 只有在您显式定义对 Scala 的依赖项或 Scala 通过依赖项间接依赖的情况下才会从仓库中解析。在这些情况下,解析的依赖项的工件将被 Scala 主目录 lib/
目录中的 jar 文件替换。
例如,考虑在配置 scalaHome
时添加对 scala-reflect
的依赖项
scalaHome := Some(file("/home/user/scala-2.10/"))
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
这将像往常一样解析,只是 sbt 会查看 /home/user/scala-2.10/lib/scala-reflect.jar
是否存在。如果存在,该文件将用于替换托管依赖项中的工件。
您可以直接添加 Scala jar 文件,而不是添加对它们的托管依赖项。scalaInstance
任务提供了对 Scala 分发版的结构化访问。例如,要添加 Scala 主目录 lib/
目录中的所有 jar 文件,
scalaHome := Some(file("/home/user/scala-2.10/"))
Compile / unmanagedJars ++= scalaInstance.value.jars
要仅添加一些 jar 文件,请在添加它们之前从 scalaInstance
中过滤掉 jar 文件。
sbt 需要 Scala jar 文件才能运行自身,因为它是用 Scala 编写的。sbt 使用相同的 Scala 版本编译您为项目编写的构建定义,因为它们使用 sbt API。此 Scala 版本在特定 sbt 版本中固定,无法更改。对于 sbt 1.9.8,此版本为 Scala 2.12.18。由于此 Scala 版本在 sbt 运行之前是必需的,因此用于检索此版本的仓库是在 sbt 启动器 中配置的。