ライブラリ依存性の基本

このページは、sbt を使ったライブラリ依存性管理の基本を説明する。

sbt はマネージ依存性 (managed dependency) を実装するのに内部で Coursier を採用していて、Coursier、npm、PIP などのパッケージ管理を使った事がある人は違和感無く入り込めるだろう。

マネージ依存性とは何か

JAR ファイルを 1つ 1つ手でダウンロードする (アンマネージ依存性) 代わりに、マネージ依存性システムはサブプロジェクトで使われる外部ライブラリの取得を自動化する。Coursier のようなツールは宣言された ModuleID 列を解釈して、依存性解決 (全ての間接的依存性を展開して、バージョン衝突を解決して、正確なバージョンを決定する) を行い、結果となったアーティファクトをダウンロードしキャッシュして、一貫性のある JAR 管理を保証する。

libraryDependencies キー

依存性の宣言は、以下のようになる。ここで、groupIdartifactId、と revision は文字列だ:

libraryDependencies += groupID % artifactID % revision

もしくは、以下のようになる。このときの configuration は文字列もしくは Configuration の値だ (Test など)。

libraryDependencies += groupID % artifactID % revision % configuration

コンパイルを実行すると:

> compile

sbt は自動的に依存性を解決して、JAR ファイルをダウンロードする。

%% を使って正しい Scala バージョンを入手する

groupID % artifactID % revision のかわりに、 groupID %% artifactID % revision を使うと(違いは groupID の後ろの二つ連なった %%)、 sbt はプロジェクトの Scala のバイナリバージョンをアーティファクト名に追加する。これはただの略記法なので %% 無しで書くこともできる:

libraryDependencies += "org.scala-lang" % "toolkit_3" % "0.2.0"

ビルドの Scala バージョンが 3.x だとすると、以下の設定は上記と等価だ("org.scala-lang" の後ろの二つ連なった %% に注意):

libraryDependencies += "org.scala-lang" %% "toolkit" % "0.2.0"

多くの依存ライブラリは複数の Scala バイナリバージョンに対してコンパイルされており、この機構はそのうちの中からプロジェクトとバイナリ互換性のある正しいものを選択する便利機能だ。

ライブラリ依存性を一箇所にまとめる

project 内の任意の .scala ファイルがビルド定義の一部となることを利用する一つの例として project/Dependencies.scala というファイルを作ってライブラリ依存性を一箇所にまとめるということができる。

// project/Dependencies.scala にこのファイルを置く

import sbt.*

object Dependencies:
  // versions
  lazy val toolkitV = "0.2.0"

  // libraries
  val toolkit = "org.scala-lang" %% "toolkit" % toolkitV
  val toolkitTest = "org.scala-lang" %% "toolkit-test" % toolkitV
end Dependencies

この Dependencies オブジェクトは build.sbt 内で利用可能となる。 定義されている val が使いやすいように Dependencies.* を import しておこう。

import Dependencies.*

scalaVersion := "3.7.3"
name := "something"
libraryDependencies += toolkit
libraryDependencies += toolkitTest % Test

ライブラリ依存性の可視化

sbt シェルに Compile/dependencyTree と入力すると、ライブラリ依存性の間接的依存性を含むツリーが表示される:

> Compile/dependencyTree

これは以下のように表示されるはずだ:

sbt:bar> Compile/dependencyTree
[info] default:bar_3:0.1.0-SNAPSHOT
[info]   +-org.scala-lang:scala3-library_3:3.3.1 [S]
[info]   +-org.scala-lang:toolkit_3:0.2.0
[info]     +-com.lihaoyi:os-lib_3:0.9.1
[info]     | +-com.lihaoyi:geny_3:1.0.0
[info]     | | +-org.scala-lang:scala3-library_3:3.1.3 (evicted by: 3.3.1)
[info]     | | +-org.scala-lang:scala3-library_3:3.3.1 [S]
....