§ビルドをデバッグする
sbt を思い通りに動かすのに手こずっているのであれば、ビルドのデバッグを支援するために sbt が提供している組み込みユーティリティをいくつか使う必要があるのかもしれません。
§依存性のデバッグ
sbt はデフォルトで、どの依存性が他の依存性に取り込まれているかを示す依存性ツリー、そして複数の依存性が要求されたときに sbt がどのようにしてバージョンを選択しているかを表示するコンフリクト解決テーブルを含む、すべての依存性のレポートを生成します。
このレポートは、XSL をサポートしているブラウザでは XML から HTML に変換できるようにする XSL スタイルシートを伴った XML ファイルとして生成されます。これをサポートしているブラウザには Firefox と Safari が含まれますが、注目すべきことに Chrome が含まれていません。
このレポートはプロジェクトの target/resolution-cache/reports
ディレクトリ内にプロジェクトのスコープごとに生成されており、例えば com.example-my-first-app_2.11-compile.xml
のように organization-projectId_scalaVersion-scope.xml
という名前が付けられています。このレポートは Firefox で開くと以下のように見えます:
§設定のデバッグ
sbt は、ビルドを理解し、なにかおかしくなったところを解決するために使うことのできる便利なコマンドをいくつか提供しています。
§show コマンド
show コマンドはあらゆる sbt タスクの戻り値を表示します。例えば、あるソースファイルがコンパイルされるかどうかよく分からない場合、show sources
を実行して sbt がそれをソースに含めているかどうか見ることができます:
[my-first-app] $ show sources
[info] ArrayBuffer(my-first-app/app/controllers/Application.scala,
my-first-app/target/scala-2.11/twirl/main/views/html/index.template.scala,
my-first-app/target/scala-2.11/twirl/main/views/html/main.template.scala,
my-first-app/target/scala-2.11/src_managed/main/routes_reverseRouting.scala,
my-first-app/target/scala-2.11/src_managed/main/routes_routing.scala,
my-first-app/target/scala-2.11/src_managed/main/controllers/routes.java)
上記の出力はスクリーンにぴったり収まるように整形されていますが、実行したタスクが長いリストを返す場合は、その内容を理解するためにエディタにコピーする必要があるかもしれません。
例えば test:sources
や compile:sources
のように、タスクに特定のスコープを指定したり、my-project/compile:sources
のように特定のプロジェクトを指定することもできます。また、あるタスクが他のタスクのスコープとなっている別の場合は、そのスコープを指定することもできます。例えばプロジェクトの jar ファイルにパッケージされるものをすべて表示するには、packageBin
タスクをスコープとする mappings
タスクを表示します:
[my-first-app] $ show compile:packageBin::mappings
[info] List(
(my-first-app/target/scala-2.11/classes/application.conf,application.conf),
(my-first-app/target/scala-2.11/classes/controllers/Application.class,controllers/Application.class),
...
§inspect コマンド
inspect コマンドは、タスクが何に依存しているか、何から依存されているか、どこに定義されているか、などの詳細情報を提供します。これは show
コマンドと同じように使うことができます:
[my-first-app] $ inspect managedSources
[info] Task: scala.collection.Seq[java.io.File]
[info] Description:
[info] Sources generated by the build.
[info] Provided by:
[info] {file:my-first-app/}root/compile:managedSources
[info] Defined at:
[info] (sbt.Defaults) Defaults.scala:185
[info] Dependencies:
[info] compile:sourceGenerators
[info] Reverse dependencies:
[info] compile:sources
...
ここでは managedSources
コマンドを調査し、このタスクはファイルのシーケンスを提供すること、Sources generated by the build
という説明文を持つことが分かります。sourceGenerators
タスクに依存していること、sources
タスクから依存されていることも確認できます。どこに定義されているかを確認することもできて、この場合は sbt のデフォルトタスク定義の 185 行目です。
§inspect tree コマンド
inspect tree コマンドは、あるタスクのタスクツリー全体を表示します。unmanagedSources
タスクのタスクツリーを調査した場合、以下のように表示されます:
[my-first-app] $ inspect tree unmanagedSources
[info] compile:unmanagedSources = Task[scala.collection.Seq[java.io.File]]
[info] +-*/*:sourcesInBase = true
[info] +-*/*:unmanagedSources::includeFilter = sbt.SimpleFilter@3dc46f24
[info] +-compile:unmanagedSourceDirectories = List(my-first-app/app, my-first-a..
[info] | +-compile:javaSource = app
[info] | | +-*:baseDirectory = my-first-app
[info] | | +-*:thisProject = Project(id root, base: my-first-app, configurations: List(compile,..
[info] | |
[info] | +-compile:scalaSource = app
[info] | +-*:baseDirectory = my-first-app
[info] | +-*:thisProject = Project(id root, base: my-first-app, configurations: List(compile,..
[info] |
[info] +-*:baseDirectory = my-first-app
[info] +-*/*:excludeFilter = sbt.HiddenFileFilter$@49e479da
ここでは、どのファイルを含める、あるいは除外するかを判断するフィルタを含め、プロジェクト内にあるソースを発見するために sbt が使うタスクツリー全体が表示されています。inspect tree
コマンドは、ビルドのある部分がどのように構築されていてのかよく分からず、それらがどのように組み合わさるのかを解明したい場合に特に便利で、これによりさらに詳しく調べていくことができます。
§インクリメンタルコンパイルのデバッグ
人々が Play に持っている共通の問題は、期待していないときに Play が再コンパイルし、再ロードすることです。多くの場合、これはソースジェネレータまたは IDE がなんらかの事情で Play クラスパスの要素を更新し、再ロードを強制することで引き起こされます。このような問題を解決するために、compile タスクのデバッグログを見ることができます。sbt はタスクを実行すると、それを表示するしないに関わらずログ出力をすべてキャプチャするので、必要な場合は後から調査することができます。これは last
コマンドを使って調査することができます。
さて、ここで compile
を実行して、あるファイルを再コンパイルする必要があったとしましょう:
[my-first-app] $ compile
[info] Compiling 1 Scala source to my-first-app/target/scala-2.11/classes...
[success] Total time: 1 s, completed 07/04/2015 1:28:43 PM
last compile
を実行すると、compile コマンドの実行中に起こったことの完全なデバッグログを取得できます。大量のダンプが出力されますが、興味があるのは以下に示す最初の部分だけです:
[my-first-app] $ last compile
[debug]
[debug] Initial source changes:
[debug] removed:Set()
[debug] added: Set()
[debug] modified: Set(my-first-app/app/controllers/Application.scala)
[debug] Removed products: Set()
[debug] External API changes: API Changes: Set()
[debug] Modified binary dependencies: Set()
[debug] Initial directly invalidated sources: Set(my-first-app/app/controllers/Application.scala)
[debug]
[debug] Sources indirectly invalidated by:
[debug] product: Set()
[debug] binary dep: Set()
[debug] external source: Set()
これは、my-first-app/app/controllers/Application.scala
が変更されたために再コンパイルが引き起こされたことを伝えています。
Next: 公開アセットを使う
このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。