このページでは、旧式の .scala ビルド定義の説明をする。
以前のバージョンの sbt で複数のプロジェクトを扱うには .scala ビルド定義を使う以外しかなかったが、
sbt 0.13 からはマルチプロジェクト .sbt ビルド定義が追加され、現在はそのスタイルが推奨されている。
このページは、このガイドのこれまでのページ、特に .sbt ビルド定義 と 他の種類のセッティングを読んでいることを前提とする。
build.sbt と Build.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 sampleKeyD は sampleKeyB に対応する:
[info] Setting: java.lang.String = D: in build.sbt
[info] Provided by:
[info] {file:/home/hp/checkout/hello/}hello/*:sampleKeyD
sbt は .sbt ファイルからのセッティングを Build.settings と Project.settings に追加し、
これは .sbt 内のセッティングの優先順位が高いことを意味する。
Build.scala を変更して、build.sbt でも設定されている sampleKeyC か sampleKeyD キーを設定してみよう。
build.sbt 内のセッティングが Build.scala 内のそれに「勝って」優先されるはずだ。
もう一つ気づいたかもしれないが、sampleKeyC と sampleKeyD は build.sbt でそのまま使うことができる。
これは sbt が Build オブジェクトのコンテンツを自動的に .sbt ファイルにインポートすることにより実現されている。
具体的には build.sbt ファイル内で import HelloBuild._ が暗黙に呼ばれている。
まとめると:
.scala ファイル内で、Build.settings にセッティングを追加すると、
自動的にビルド全体にスコープ付けされる。
.scala ファイル内で、Project.settings にセッティングを追加すると、
自動的にプロジェクトにスコープ付けされる。
.scala ファイルに書いた全ての Build オブジェクトのコンテンツは
.sbt ファイルにインポートされる。
.sbt ファイル内のセッティングは .scala ファイルのセッティングに追加される。
.sbt ファイル内のセッティングは、明示的に指定されない限り
プロジェクトにスコープ付けされる。
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 を使ってビルド定義プロジェクトから普通のプロジェクトに戻る。
build.sbt 内のセッティングが、Build や Project オブジェクトの settings フィールドに
追加されると考えるのは間違っている。
そうではなく、Build や Project のセッティングリストと build.sbt のセッティングが
連結されて別の immutable なリストになって、それが sbt に使われるというのが正しい。
Build と Project オブジェクトは、immutable なコンフィギュレーションであり、
ビルド定義の全体からすると、たった一部にすぎない。
事実、セッティングには他にも出どころがある。具体的には、以下の順で追加される:
.scala ファイル内の Build.settings と Project.settings 。
~/.sbt/build.sbt に全てのプロジェクトに影響するセッティングを定義できる。
.sbt ファイル内のセッティング。
project 内のプロジェクトである)ビルド定義プロジェクトの場合は、グローバルプラグイン(~/.sbt/plugins)が追加される。
プラグインの使用で詳細が説明される。
後続のセッティングは古いものをオーバーライドする。このリスト全体でビルド定義が構成される。