sbtのディレクトリ構成カスタム時に必要なbuild.sbt指定を調べてみた

Scalaでsbtを使う際のチュートリアル系記事は基本的なプロジェクト構成になっているケースがほとんどでした。カスタマイズされた構成でのbuild.sbt指定を調べてみました。Scala 2.11.12、sbt 1.3.7前提となります。
2020.06.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

sbtを使ったプロジェクトは必ずしも標準的なディレクトリ構成にならないことがあります。その場合、build.sbtへディレクトリ構成について幾つか設定追加が必須になってきます。

ディレクトリのカスタム構成について触れてある記事を検索してみたものの、公式ドキュメントでの記載で唯一確認できた状態だったため、試した結果を備忘録含めてまとめました。

基本的なディレクトリ構成

ディレクトリのみとなりますが、大体こんな感じです。

├── build.sbt
└── src
    ├── main
    │   ├── resources
    │   └── scala
    └── test
        ├── resources
        └── scala

main/scala以下にテストケースを追加する場合

build.sbtに次の一行を追加します。baseDirectory.valueはプロジェクトのルートになります。

Test / scalaSource := baseDirectory.value / "src/main/scala"

追加前後でのsbt test実行結果は以下の様に変わってきます。

追加前

[info] Loading settings for project glue-build from plugins.sbt,metals.sbt ...
[info] Loading project definition from /path/to/root/project
[info] Loading settings for project glue from build.sbt ...
[info] Set current project to project (in build file:/path/to/root/)
[info] ScalaTest
[info] Run completed in 36 milliseconds.
[info] Total number of tests run: 0
[info] Suites: completed 0, aborted 0
[info] Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0

追加後

[info] Loading settings for project glue-build from plugins.sbt,metals.sbt ...
[info] Loading project definition from /path/to/root/project
[info] Loading settings for project glue from build.sbt ...
[info] Set current project to project (in build file:/path/to/root/)
[info] Compiling 41 Scala sources to /path/to/root/target/scala-2.11/test-classes ...
20/06/22 19:08:33 WARN Utils: Your hostname, localhost resolves to a loopback address: 127.0.0.1; using 192.168.0.186 instead (on interface en0)
20/06/22 19:08:33 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address
20/06/22 19:08:33 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
20/06/22 19:08:34 WARN SparkContext: Using an existing SparkContext; some configuration may not take effect.
[info] Filter:
[info] - Is owner
[info] - Not owner
20/06/22 19:08:35 WARN SparkContext: Using an existing SparkContext; some configuration may not take effect.
20/06/22 19:08:35 WARN SparkSession$Builder: Using an existing SparkSession; some configuration may not take effect.
20/06/22 19:08:35 WARN SparkSession$Builder: Using an existing SparkSession; some configuration may not take effect.
20/06/22 19:08:35 WARN SparkSession$Builder: Using an existing SparkSession; some configuration may not take effect.
[info] Record:
[info] - HTTP *** FAILED ***
[info]   java.util.NoSuchElementException: None.get
[info]   at scala.None$.get(Option.scala:347)
[info]   at scala.None$.get(Option.scala:345)
[info]   ..
[info]   ..
[info]   ..
[info]   at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:22)
[info]   ...
[info] ScalaTest
[info] Run completed in 6 seconds, 202 milliseconds.
[info] Total number of tests run: 4
[info] Suites: completed 3, aborted 0
[info] Tests: succeeded 3, failed 1, canceled 0, ignored 0, pending 0
[info] *** 1 TEST FAILED ***
[error] Failed: Total 4, Failed 1, Errors 0, Passed 3
[error] Failed tests:
[error]     Record
[error] (Test / test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 17 s, completed 2020/06/22 19:08:38

テストファイルを認知していることがわかります。

独自ディレクトリ内に外部ライブラリファイルを追加する

libディレクトリを追加して外部ライブラリを入れると、build.sbtには特に記載無しで認識されます。何らかの事情でディレクトリを分けたい場合に使えると思います。

unmanagedBase := baseDirectory.value / "libs"

TestやCompileのみに限定する方法についてはunmanagedBase in (Test)との指定が記載されていましたが、実際にやってみるとパスが通っていなかったため検証中です。

指定早見

用途 追加先
Complie Compile / scalaSource := baseDirectory.value / "add/path"
Test Test / scalaSource := baseDirectory.value / "add/path"
lib unmanagedBase := baseDirectory.value / "add/path"

あとがき

build.sbtへの指定については、過去バージョンで使われていた記述等が現在ではコンパイルエラー等で使えないケースも多く、公式ドキュメント内で比較的新しいバージョンのドキュメントを見つけて、そこから試行錯誤で望む形にするのが早そうだと感じました。

build.sbtにおける暗黙の認知等を触ることができたのは良かったと思っています。

参考リンク