组织构建 

本页面将讨论构建结构的组织。

本小节假设你已经阅读了之前的章节,尤其是 build.sbt库依赖多工程构建

sbt是递归的 

build.sbt 很简单,隐藏了 sbt 是如何工作的。sbt 构建是用 Scala 代码定义的。代码本身也必须是能被构建的。有比 sbt 更好的建立方式么?

project 目录 是你的工程内另一个工程的项目,它知道如何构建你的工程。为了区分这两种构建,我们有时使用正常构建表示你的构建,使用元构建指代在 project中的构建。在元构建中的项目能做任何其他项目可以做的事情。 你的构建定义是一个 sbt 项目。

递归可以继续下去。如果你喜欢, 你可以通过创建 project/project/ 目录稍稍调整项目的构建定义。

下面是一个例子:

hello/                  # 项目的基目录

    Hello.scala         # 一个项目源文件(也可以在src/main/scala)

    build.sbt           # build.sbt 是project/ 中元构建根项目的源代码。是构建定义项目的一部分。

    project/            # 元构建根项目的基目录

        Build.scala     # 元构建根项目的一个源文件,是你的构建定义的构建定义源文件

        build.sbt       # 元元构建的根项目——project/project的源代码;构建定义的构建定义

        project/        # 元元构建的根项目的基目录;构建定义的构建定义工程

            Build.scala # project/project/ 元元构建的根项目中的源文件

不用担心! 大部分时候不需要 project/project/ 目录。但是理解它是有帮助的。

另外,任何以 .scala 或者 .sbt 结尾的文件都会被使用,命名为 build.sbtBuild.scala只是惯例。多个文件也是允许的。

在同一个地方跟踪依赖项 

project下的.scala文件组成构建定义的一个实际用例是创建project/Dependencies.scala来在同一个地方跟踪依赖项。

import sbt._

object Dependencies {
  // Versions
  lazy val akkaVersion = "2.6.21"

  // Libraries
  val akkaActor = "com.typesafe.akka" %% "akka-actor" % akkaVersion
  val akkaCluster = "com.typesafe.akka" %% "akka-cluster" % akkaVersion
  val specs2core = "org.specs2" %% "specs2-core" % "4.20.0"

  // Projects
  val backendDeps =
    Seq(akkaActor, specs2core % Test)
}

Dependencies对象将在build.sbt中可用。如果要让使用val的代码更加简单,可以引入Dependencies._

import Dependencies._

ThisBuild / organization := "com.example"
ThisBuild / version      := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.12.18"

lazy val backend = (project in file("backend"))
  .settings(
    name := "backend",
    libraryDependencies ++= backendDeps
  )

当你的多工程构建变得很大,并且想要确保子项目有一致的依赖关系时,这种技术很有用。

何时用 .scala 文件 

.scala 文件,你可以写任意的 Scala 代码,包括顶层的类和对象。

推荐的方法是定义大部分设置在多工程的 build.sbt 文件中,并且使用 project/*.scala 文件来做任务实现或在多个文件中共享键值。对.scala文件的使用也取决于你的团队对scala的熟练程度。

定义自动插件 

对于更高级的用户,另一种方式组织你的构建是在project/*.scala中定义一次性自动插件。通过定义触发的插件,自动插件可以用作一种简便方法来注入跨所有子项目的自定义任务和命令。