はじめに
sbt-dependency-graphは、Scalaプロジェクトにおける依存関係を可視化・分析するための強力なsbtプラグインです。本稿では、標準機能を超えたカスタム出力の生成方法や、複雑な依存ツリーを効率的に管理するための高度なフィルタリング手法について解説します。
プラグインの導入と基本設定
使用を開始するには、まずproject/plugins.sbtに以下の行を追加します。
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1")
適用後、次の主要タスクが利用可能になります:
dependencyTree:階層的な依存ツリーを表示dependencyList:平文化された依存リストdependencyStats:モジュール数や重複バージョンの統計情報licenseInfo:ライセンス一覧
出力形式の拡張とカスタマイズ
デフォルトのテキスト出力に加え、外部ツール連携可能な形式への対応が可能です。
DOT形式によるグラフ生成
Graphvizとの連携により、視覚的に理解しやすい依存グラフを作成できます。次のようにヘッダーとノードラベルをカスタマイズ可能です。
dependencyDotHeader :=
"""
|digraph "project-deps" {
| graph [rankdir="LR", fontsize=12];
| node [shape=ellipse, fontname="Meiryo", margin="0.2"];
| edge [arrowhead=vee, color="#555"];
""".stripMargin
dependencyDotNodeLabel := { (org, name, ver) =>
s"""<table border="0" cellborder="1" cellspacing="0">
<tr><td colspan="2" bgcolor="#f0f8ff"><b>$name</b></td></tr>
<tr><td>org</td><td>$org</td></tr>
<tr><td>ver</td><td>$ver</td></tr>
</table>"""
}
実行コマンド:
sbt dependencyDot → target/scala-*/dependency-graph.dot を生成
HTMLベースのインタラクティブビュー
ブラウザ上で探索可能な依存関係図を生成するタスクも提供されています。
dependencyBrowseGraph := Def.task {
val htmlPath = (Compile / target).value / "dependency-graph.html"
val dotContent = rendering.DOT.dotGraph(
(moduleGraph in Compile).value,
dependencyDotHeader.value,
dependencyDotNodeLabel.value,
rendering.DOT.LabelTypeHtml
)
IO.write(htmlPath, DagreHTML.template(dotContent))
sys.process.Process("open", Seq(htmlPath.toURI.toString)).!
htmlPath
}.value
高度なフィルタリング戦略
大規模プロジェクトでは不要な依存を除外することで、分析の焦点を絞ることが重要です。
特定組織の除外
たとえば社内ライブラリ(例: com.internal.*)を除外する場合:
dependencyTree := {
val rawGraph = (moduleGraph in Compile).value
val filtered = GraphTransformations.filter(rawGraph) { module =>
!module.id.organisation.startsWith("com.internal")
}
rendering.AsciiTree.asciiTree(filtered)
}
Scala標準ライブラリの制御
Scalaのコアライブラリを表示対象から除外する設定:
filterScalaLibrary in Global := true
これをfalseにすると、暗黙的に含まれるscala-libraryも明示的に表示されます。
逆依存検索(whatDependsOn)
あるモジュールがどのプロジェクトから参照されているかを調査できます。
// sbtシェル内での使用例
sbt> whatDependsOn org.typelevel cats-core _
上記コマンドは、cats-coreを利用しているすべてのモジュールを検出します。
ファイル出力と共有
コンソール出力をファイルに保存する機能により、文書化やチーム内共有が容易になります。
// build.sbt内に定義
lazy val exportDeps = taskKey[Unit]("Export dependency tree to file")
exportDeps := {
val log = streams.value.log
val tree = (dependencyTree in Compile).value
val file = (Compile / target).value / "dependencies.tree"
IO.write(file, tree)
log.info(s"Dependency tree saved to ${file.getAbsolutePath}")
}
実践的な設定例
以下は、カスタムフィルタと出力形式を組み合わせた総合的な設定例です。
import net.virtualvoid.sbt.graph._
// 全ての依存タスクに共通設定を適用
inConfig(Compile)(Seq(
dependencyDotHeader := """|digraph G {
| rankdir=TB;
| node[shape=box, style=rounded, fontname="Helvetica"]
|""".stripMargin,
dependencyTree := {
val graph = moduleGraph.value
val pruned = GraphTransformations.pruneTransitiveDependencies(graph)
val noTest = GraphTransformations.excludeConfigurations(pruned, Set("test"))
rendering.AsciiTree.asciiTree(noTest)
}
))
トラブルシューティング
出力が肥大化する場合
filterScalaLibrary := trueで言語ランタイムを除外excludeConfigurationsでtestやprovidedスコープを除外- カスタム
GraphTransformationで不要な組織名をフィルタ
HTML生成が失敗する場合
主な原因は出力ディレクトリの権限不足またはパスの不正です。targetディレクトリの存在と書き込み権限を確認してください。