构建定义基础

本页讨论 build.sbt 构建定义。

什么是构建定义?

构建定义在 build.sbt 中定义,由一组项目(类型为 Project)组成。由于项目一词可能产生歧义,本指南中我们通常称其为 subproject(子项目)。

例如,在 build.sbt 中您这样定义位于当前目录的子项目:

scalaVersion := "3.3.3"
name := "Hello"

或更明确地:

lazy val root = rootProject
  .settings(
    scalaVersion := "3.3.3",
    name := "Hello",
  )

每个子项目通过键值对配置。例如,name 是一个键,映射到字符串值,即您子项目的名称。键值对列在 .settings(...) 方法下。

build.sbt DSL

build.sbt 使用名为 build.sbt DSL 的 DSL 定义子项目,该 DSL 基于 Scala。最初您可以像使用 YAML 文件一样使用 build.sbt DSL,仅声明 scalaVersionlibraryDependencies,但随着构建规模增大,它支持更多功能以保持构建定义井然有序。

类型化设置表达式

让我们仔细看看 build.sbt DSL:

organization  :=         "com.example"
^^^^^^^^^^^^  ^^^^^^^^   ^^^^^^^^^^^^^
key           operator   (setting/task) body

每个条目称为 setting expression(设置表达式)。其中一些也称为 task expression(任务表达式)。我们将在本页后面更详细地了解两者的区别。

设置表达式由三部分组成:

  1. 左侧是键。
  2. 运算符,此处为 :=
  3. 右侧称为主体或设置/任务主体。

在左侧,nameversionscalaVersionkeys(键)。键是 SettingKey[A]TaskKey[A]InputKey[A] 的实例,其中 A 是期望的值类型。

由于键 name 的类型为 SettingKey[String]name 上的 := 运算符也专门类型为 String。如果您使用错误的值类型,构建定义将无法编译:

name := 42 // will not compile

vallazy val

为避免重复相同信息(如库的版本号),build.sbt 中可以穿插使用 vallazy valdef

val toolkitV = "0.2.0"
val toolkit = "org.scala-lang" %% "toolkit" % toolkitV
val toolkitTest = "org.scala-lang" %% "toolkit-test" % toolkitV

scalaVersion := "3.8.1"
libraryDependencies += toolkit
libraryDependencies += (toolkitTest % Test)

在上面的代码中,val 定义变量,变量从上到下初始化。这意味着 toolkitV 必须在被引用之前定义。

以下是一个错误示例:

// bad example
val toolkit = "org.scala-lang" %% "toolkit" % toolkitV // uninitialized reference!
val toolkitTest = "org.scala-lang" %% "toolkit-test" % toolkitV // uninitialized reference!
val toolkitV = "0.2.0"

如果您的 build.sbt 包含未初始化的前向引用,sbt 将无法加载,并因 NullPointerException 而抛出 java.lang.ExceptionInInitializerError。让编译器解决此问题的一种方法是将变量定义为 lazy

lazy val toolkit = "org.scala-lang" %% "toolkit" % toolkitV
lazy val toolkitTest = "org.scala-lang" %% "toolkit-test" % toolkitV
lazy val toolkitV = "0.2.0"

有些人反对过多使用 lazy val,但 Scala 3 的 lazy val 效率很高,我们认为它使构建定义在复制粘贴时更加稳健。

Note

build.sbt 中不允许顶层对象和类。 它们应放在 project/ 目录中作为 Scala 源文件。