付録: .scala ビルド定義 

このページでは、旧式の .scala ビルド定義の説明をする。 以前のバージョンの sbt で複数のプロジェクトを扱うには .scala ビルド定義を使う以外しかなかったが、 sbt 0.13 からはマルチプロジェクト .sbt ビルド定義が追加され、現在はそのスタイルが推奨されている。

このページは、このガイドのこれまでのページ、特に .sbt ビルド定義他の種類のセッティングを読んでいることを前提とする。

build.sbtBuild.scala の関係 

ビルド定義の中で、.sbt.scala を混ぜて使うには、両者の関係を理解する必要がある。

実際に 2 つのファイルを使って説明しよう。 まず、プロジェクトが hello というディレクトリにあるなら hello/project/Build.scala を以下のように作る:

import sbt._
import Keys._

object HelloBuild extends Build {
  val sampleKeyA = settingKey[String]("demo key A")
  val sampleKeyB = settingKey[String]("demo key B")
  val sampleKeyC = settingKey[String]("demo key C")
  val sampleKeyD = settingKey[String]("demo key D")

  override lazy val settings = super.settings ++
    Seq(
      sampleKeyA := "A: in Build.settings in Build.scala",
      resolvers := Seq()
    )

  lazy val root = Project(id = "hello",
    base = file("."),
    settings = Seq(
      sampleKeyB := "B: in the root project settings in Build.scala"
    ))
}

次に hello/build.sbt を以下のような内容で作成する:

sampleKeyC in ThisBuild := "C: in build.sbt scoped to ThisBuild"

sampleKeyD := "D: in build.sbt"

sbt のインタラクティブプロンプトを起動する。 inspect sampleKeyA と入力すると、以下のように表示されるはずだ(一部抜粋):

[info] Setting: java.lang.String = A: in Build.settings in Build.scala
[info] Provided by:
[info]  {file:/home/hp/checkout/hello/}/*:sampleKeyA

次に inspect sampleKeyC と入力すると、以下のように表示される:

[info] Setting: java.lang.String = C: in build.sbt scoped to ThisBuild
[info] Provided by:
[info]  {file:/home/hp/checkout/hello/}/*:sampleKeyC

二つの値とも “Provided by” は同じスコープを表示していることに注目してほしい。 つまり、.sbt ファイルの sampleKeyC in ThisBuild は、 .scala ファイルの Build.settings リストにセッティングを追加することと等価ということだ。 sbt はビルド全体にスコープ付けされたセッティングを両者から取り込んでビルド定義を作成する。

次は、inspect sampleKeyB:

[info] Setting: java.lang.String = B: in the root project settings in Build.scala
[info] Provided by:
[info]  {file:/home/hp/checkout/hello/}hello/*:sampleKeyB

sampleKeyB は、ビルド全体({file:/home/hp/checkout/hello/})ではなく、 特定のプロジェクト({file:/home/hp/checkout/hello/}hello) にスコープ付けされいることに注意してほしい。

もうお分かりだと思うが、inspect sampleKeyDsampleKeyB に対応する:

[info] Setting: java.lang.String = D: in build.sbt
[info] Provided by:
[info]  {file:/home/hp/checkout/hello/}hello/*:sampleKeyD

sbt は .sbt ファイルからのセッティングを Build.settingsProject.settings追加し、 これは .sbt 内のセッティングの優先順位が高いことを意味する。 Build.scala を変更して、build.sbt でも設定されている sampleKeyCsampleKeyD キーを設定してみよう。 build.sbt 内のセッティングが Build.scala 内のそれに「勝って」優先されるはずだ。

もう一つ気づいたかもしれないが、sampleKeyCsampleKeyDbuild.sbt でそのまま使うことができる。 これは sbt が Build オブジェクトのコンテンツを自動的に .sbt ファイルにインポートすることにより実現されている。 具体的には build.sbt ファイル内で import HelloBuild._ が暗黙に呼ばれている。

まとめると:

インタラクティブモードにおけるビルド定義 

sbt のインタラクティブプロンプトでカレントプロジェクトを project/ 内のビルド定義プロジェクトに切り替えることができる。 reload plugins と打ち込むことで切り替わる:

> reload plugins
[info] Set current project to default-a0e8e4 (in build file:/home/hp/checkout/hello/project/)
> show sources
[info] ArrayBuffer(/home/hp/checkout/hello/project/Build.scala)
> reload return
[info] Loading project definition from /home/hp/checkout/hello/project
[info] Set current project to hello (in build file:/home/hp/checkout/hello/)
> show sources
[info] ArrayBuffer(/home/hp/checkout/hello/hw.scala)
>

上記にあるとおり、reload return を使ってビルド定義プロジェクトから普通のプロジェクトに戻る。

注意: 全てが immutable だ 

build.sbt 内のセッティングが、BuildProject オブジェクトの settings フィールドに 追加されると考えるのは間違っている。 そうではなく、BuildProject のセッティングリストと build.sbt のセッティングが 連結されて別の immutable なリストになって、それが sbt に使われるというのが正しい。 BuildProject オブジェクトは、immutable なコンフィギュレーションであり、 ビルド定義の全体からすると、たった一部にすぎない。

事実、セッティングには他にも出どころがある。具体的には、以下の順で追加される:

後続のセッティングは古いものをオーバーライドする。このリスト全体でビルド定義が構成される。