Scala の開発環境を一から構築し直した際の手順を公開しておきます。
採用しているツール群は基本的に公式が推奨しているっぽいものにしています。
※ VSCode 派なので IntelliJ は採用しませんでした。
この記事で構築する環境の構成図はこちらです。
この構成で示している通り、 Windows 側では VSCode と WSL 拡張機能のみが動作し、実際の開発環境(JDK、Scala、SBT)は WSL 上に構築します。
1. WSL2 のインストール
Windows 10 ビルド 19041 以上、または、Windows 11 であれば、以下のコマンドだけで大丈夫です。
# OS のバージョンを確認
$PSVersionTable.OS
#=> Microsoft Windows 10.0.19045
# WSL をインストール
wsl --install
# インストールが完了すれば、wsl コマンドで Ubuntu を起動 & ログインする。
wsl
# 初回はユーザ名とパスワードを設定する。
これで Ubuntu ディストリビューションが WSL として利用できます。
それ以外の PC 環境の方は、以下の公式ページをご参照ください。
2. WSL で Scala と SBT のインストール
Coursier を使用して必要な開発ツールをセットアップしていきます。Coursier は、Scala 関連の開発ツールに特化したパッケージマネージャのようなツールです。
# Coursier の最新バージョンをダウンロード
curl -fL https://github.com/coursier/coursier/releases/latest/download/cs-x86_64-pc-linux.gz | gzip -d > cs
# 展開して実行可能ファイル「cs」を作成
chmod +x cs
# Scala、SBT、および関連ツールをインストール
./cs setup
最新のインストール手順についてはこちらをご参照ください。
JDK は既にインストールされていれば追加でインストールされることはありません。セットアップ中には必要なツールが順次インストールされ、PATH への設定も自動的に行われます。
JDK がインストールされていない場合、Coursier が自動的に検知し、インストールするか尋ねられます。
No JVM found, should we try to install one? [Y/n]
JDK を既にインストールしている場合は、このようなメッセージが表示されます。
Found a JVM installed under /home/nimzo/.sdkman/candidates/java/current.
インストールが完了したら、一度シェルを再起動(もしくは、 source ~/.profile
を実行)して環境変数の変更を反映させます。その後、以下のコマンドでインストールされたツールのバージョンを確認できます。
scala --version
#=> Scala code runner version: 1.5.4
#=> Scala version (default): 3.6.4
sbt --version
#=> sbt runner version: 1.10.11
scala-cli --version
#=> Scala CLI version: 1.7.1
3. VSCode のセットアップ
VSCode で WSL にて構築した開発環境を使うには、Microsoft 社が提供している WSL 拡張機能をインストールします。
WSL 拡張機能を使うことで、我々は VSCode の UI のみ Windows で実行し、それ以外の開発作業(例えば、コマンドや拡張機能、ターミナル操作、ビルドと実行、デバッグ、など)を WSL としてインストールされた Linux 上で実行することができます。
3-1. VSCode で WSL を開く
VSCode で開く前に、先にディレクトリを WSL 側に作っておきます。
mkdir ~/repos/qiita
cd ~/repos/qiita
Windows の VSCode から WSL に接続する方法は2つです。
まず、ターミナル上で wsl に入り、そこで code
コマンドで VSCode を起動することです。
pwd
#=> /home/nimzo6689/repos/qiita
code .
すると、 VSCode が起動し、ステータスバーの左下を見ると、WSL に接続できていることがわかります。
もう1つは、Windows で VSCode を起動し、ステータスバーの左下(上の画像で WSL: Ubuntu と表示されている箇所)をクリックし、コマンドパレットで WSL: Connect to WSL
を選択することです。どちらの方法でも利用できるように覚えておくと便利だと思います。
WSL の接続を終了するときは、同じようにコマンドパレットから Close Remote Connection
を選択すれば終了できます。
3-2. VSCode Scala 拡張機能のインストール
WSL に接続された VSCode ウィンドウで、Scala 開発に必要な拡張機能をインストールします。主に必要なのは「Scala (Metals)」拡張機能です。
Metals は Scala 言語サーバープロトコル(LSP)の実装名になります。
4. Scala プロジェクトの作成
WSL 環境で Scala プロジェクトを作成します。
4-1. sbt new にてテンプレートから生成する
SBT の new
コマンドを使ってテンプレートからプロジェクトを生成し、そのプロジェクトを code コマンドで開きなおします。
sbt new scala/scala3.g8
# プロジェクト名は「scaka-demo」とします。
#=>A template to demonstrate a minimal Scala 3 application
#=>name [Scala 3 Project Template]: scala-demo
#=>Template applied in /home/nimzo/repos/qiita/./scala-demo
# 生成されたプロジェクトを VSCode で開き直す
code --reuse-window scala-demo
フォルダを開いた後は、Scala (Metals) がビルドをインポートするか聞かれるため、Import Build をクリックします。すると、Metals のインストールが開始され、Metals が提供する機能が利用可能な状態になります。
4-2. プロジェクト構造の確認
プロジェクトが開かれると、以下のような構造が表示されます。
Scala プロジェクトの標準的な構造は以下のようになります。
-
build.sbt
: プロジェクトの設定ファイル。依存関係、バージョン、ビルド設定などを定義します -
project/
: SBT 自体の設定ファイルを含むディレクトリ-
build.properties
: SBT のバージョンを指定します -
plugins.sbt
: SBT プラグインを設定するファイル(必要に応じて作成)
-
-
src/
: ソースコードとテストコードを格納するディレクトリ-
main/scala/
: アプリケーションのメインソースコード -
test/scala/
: テストコード
-
-
.scalafmt.conf
: コードフォーマットの設定ファイル
※ 作成されていない場合、Alt+Shift+F
でフォーマットをかけようとすると、Metals から.scalafmt.conf
を作成するか聞かれます。
5. Scala コードの実行
他の言語と同じように VSCode 内でコードの実行やデバッグができます。
5-1. main 関数の実行
src/main/scala/Main.scala
を開き、デフォルトのコードを確認します。このファイルには基本的な「Hello, world!」プログラムが書かれています。
@main def hello(): Unit =
println("Hello world!")
println(msg)
def msg = "I was compiled by Scala 3. :)"
これは Scala 3 の新しい構文を使用した、シンプルな Hello World プログラムです。@main
アノテーションは、この関数がプログラムのエントリーポイントであることを示しています。
Metals が完全に読み込まれると、ファイル内に「run」というコードレンズが表示されます。これはファイル内の実行可能な関数(この場合は @main
でアノテーションされた関数)の上部に表示されるリンクです。これをクリックすると、プログラムが実行されます。
あるいは、VSCode の統合ターミナル(Ctrl+Shift+`)を開き、 sbt run
を実行することもできます。
5-2. デバッグ機能の使用
VSCode で Scala コードをデバッグするには、まず src/main/scala/Main.scala
にブレークポイントを設定し、F5 でデバッグ実行を開始します。
Main.scala のステップ実行であれば、 .vscode/launch.json
を別途作成しなくてもできますが、今後は用途によって作成が必要になることはあります。
6. MUnit によるテスト
MUnit は Scala 用の簡素なテストフレームワークで、明確なエラー表示が特徴です。
まず、build.sbt
ファイルに MUnit の依存関係を追加します。ただ、 sbt new scala/scala3.g8
で生成した場合、 MUnit はデフォルトで追加されているので、確認だけで大丈夫です。
libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test
この行はテスト用の依存関係として MUnit を追加しています。最後の % Test
はこの依存関係がテスト時のみ必要であることを示しています。
次に、テスト対象となるクラスを作成します。src/main/scala
ディレクトリに Calculator.scala
ファイルを作成し、以下のコードを記述します。
object Calculator {
def divide(dividend: Int, divisor: Int): Option[Int] = {
if (divisor == 0) None
else Some(dividend / divisor)
}
}
このクラスは単純な割り算処理と、ゼロ除算に対する関数型エラーハンドリング(Option型を使用)を提供しています。
では、この機能に対するテストを作成していきます。
src/test/scala
ディレクトリに CalculatorSuite.scala
ファイルを作成し、以下のテストコードを記述します。
import munit.FunSuite
class CalculatorTest extends FunSuite {
test("整数同士で割り切れる場合、正しい商を返す") {
val result = Calculator.divide(12, 3)
assertEquals(result, Some(4))
}
test("整数同士で割り切れない場合、整数部分の商を返す") {
val result = Calculator.divide(12, 5)
assertEquals(result, Some(2))
}
test("0で割る場合、Noneを返す") {
val result = Calculator.divide(12, 0)
assertEquals(result, None)
}
}
テストを実行するには、Activity Bar の Testing View にて実行できます。
統合ターミナルで sbt test
を実行しても同じ結果にはなります。
また、テストファイルを開くと、テストメソッドの行番号の横に実行ボタンが表示されるので、そこから実行もできますし、右クリックして Debug Test を選択するとデバッグしたりすることもできます。
7. JAR ファイルのビルド
アプリケーションを配布するために、実行可能な JAR ファイル(far JAR)を作成します。
まず、build.sbt
ファイルを以下のように修正して、アプリケーションのエントリーポイントを指定します。
val scala3Version = "3.6.4"
lazy val root = project
.in(file("."))
.settings(
name := "scala-demo",
version := "0.1.0-SNAPSHOT",
scalaVersion := scala3Version,
- libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test
+ libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test,
+ Compile / mainClass := Some("hello"),
+ assembly / mainClass := Some("hello"),
+
+ assembly / assemblyJarName := s"${name.value}-${version.value}.jar"
)
この修正では、コンパイル時とアセンブリ時のメインクラスを「hello」に設定しています。これは @main def hello
で定義したエントリーポイントに対応します。
次に、プロジェクトの project/plugins.sbt
ファイルを作成し、そこに sbt-assembly プラグインを追加します。
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.5")
sbt-assembly プラグインは、依存ライブラリを含む実行可能な「fat JAR」を作成するためのものです。これにより、依存関係の問題なく JAR ファイルを実行できるようになります。
設定が完了したら、 sbt assembly
で JAR ファイルをビルドできます。
ビルドが完了すると、target/scala-3.6.4/scala-demo-0.1.0-SNAPSHOT.jar
(Scala のバージョン名は異なる場合があります) が生成されます。
生成された JAR ファイルは以下のように実行できます。
java -jar target/scala-3.6.4/scala-demo-0.1.0-SNAPSHOT.jar
この実行によって「Hello, world!」が表示されるはずです。
コマンドからもわかる通り、この jar ファイルは Java がインストールされている環境であれば、同じコマンドで実行可能です。
8. Scala CLI の導入
Coursier でセットアップをすると、自動で Scala CLI という REPL やスクリプティング支援をしてくれるツールが導入されるので、そちらも紹介します。
詳しい使い方はこちら。
8-1. REPL
scala-cli repl
コマンドで REPL が起動します。
外部ライブラリを使いたい場合は、 scala-cli repl --dep com.lihaoyi::requests:0.9.0
のように指定することで使用できます。
もしくは、あとで紹介する //> using dep "com.lihaoyi::requests:0.9.0"
のような依存性情報を記載した sc ファイルを scala-cli repl demo.sc
のように指定するのでも OK です。こちらの方法の場合、 import も書いておけば、 REPL でいちいち import を実行する必要がないので便利です。
8-2. スクリプティング
試しに、 HTTP の GET リクエストを送信するスクリプトを書いてみます。
#!/usr/bin/env -S scala-cli shebang --quiet
//> using dep "com.lihaoyi::requests:0.9.0"
import requests._
val getResponse =
requests.get("https://httpbin.org/get", params = Map("name" -> "scala"))
println(s"GET response: ${getResponse.statusCode}")
あとはファイルの実行権限を付ければ、そのファイル単体で実行できます。
※ 単純に scala-cli demo.sc
でも可です。
chmod u+x demo.sc # 実行権限を付与
./demo.sc # スクリプトを実行
実行すると以下のような出力が表示されます。(scala-cli demo.sc
で実行してしまっていますが、 ./demo.sc
の結果も一緒です)
9. Scala Worksheet でインタラクティブにコードを実行をする
Scala Worksheet は VSCode の Metals 拡張機能の一部で、コードを書きながらすぐに結果を確認できるインタラクティブな開発環境を提供します。REPL に似ていますが、ファイルとして保存でき、リアルタイムに結果が表示される点に違いがあります。
Scala Worksheet ファイルを作成するには、.worksheet.sc
拡張子を持つファイルを作成します。たとえば、以下のような FizzBuzz アルゴリズムを試してみます。
def fizzbuzz(n: Int): String = (n % 3, n % 5) match {
case (0, 0) => "FizzBuzz"
case (0, _) => "Fizz"
case (_, 0) => "Buzz"
case _ => n.toString
}
fizzbuzz(1)
fizzbuzz(3)
fizzbuzz(5)
fizzbuzz(15)
Worksheet ファイルで書くと、自動的に式の結果を計算し、右側にコメントとして表示してくれます。
また、ファイル先頭に表示される Copy Worksheet Output
をクリックすると、実行結果とともにクリップボードにコードがコピーされるため、記事投稿やコードレビューなどで実装について説明するときに活用できそうです。