2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Scala3のマルチプラットフォームプロジェクトを作る

Posted at

TL;DR

  • 2025年6月現在のScalaエコシステムでも、sbt-crossprojectを使ったマルチプラットフォームプロジェクトを作成し、すべてのプラットフォームでビルドおよび実行を行うことができました
  • Scala NativeやScala.jsもScala3に対応してくれたおかげで、Scala3でマルチプラットフォームプロジェクトを作れるようになっていました

初めに

JVM、ネイティブ、ブラウザなどの複数のプラットフォームをターゲットとするプロジェクトを扱うフレームワークとして、Scalaにはsbt-crossprojectというものがあります1

しかし、sbt-crossprojectは最終更新が2年前で止まっており、そのGitter8テンプレートは約8年前に更新が止まっています。そのため、sbt-crossprojectが現在でも使い続けられるかという心配がありましたが、主に各種バージョン調整のみで現在最新のScalaエコシステムを使用することができました。

本記事はその報告です。

前提条件

scalacsbt2 の最新版がインストールされているものとします。まだ環境をお持ちでない場合、Coursierをインストールして環境構築を行ってください。

また、ネイティブ向けのバイナリを作成したい場合、LLVMなどが必要になります。詳細はScala Nativeのセットアップガイドを参照してください。

プロジェクトテンプレートの適用

  1. 適当なプロジェクトディレクトリを作成し、そこに cd しておきます
  2. sbt new portable-scala/sbt-crossproject.g8 を実行し、プロジェクトテンプレートを適用します。適用後のディレクトリ構成は以下のようになります
.
│  build.sbt
│
├─bar
│  ├─js
│  │  └─src
│  │      └─main
│  │          └─scala
│  │                  Foo.scala
│  │
│  ├─jvm
│  │  └─src
│  │      └─main
│  │          └─scala
│  │                  Foo.scala
│  │
│  ├─native
│  │  └─src
│  │      └─main
│  │          └─scala
│  │                  Foo.scala
│  │
│  └─shared
│      └─src
│          └─main
│              └─scala
│                      Bar.scala
│
└─project
        build.properties
        plugins.sbt

このうち、project 以下にはプロジェクトの共通設定等、それ以外のディレクトリ(テンプレートでは bar のみ)にはサブプロジェクトが入ります。

また、bar/js, bar/jvm, bar/nativeのそれぞれはブラウザ(JavaScript)、JVM、ネイティブそれぞれの固有コードやファサードなどを置き、bar/shared に全プラットフォーム共通のコードを置きます。

各種バージョンの調整

build.properties

project/build.propertiessbt.version を最新のsbtのバージョンに書き換えておきます。
執筆時点での sbt の最新版は 1.11.2 なので、project/build.properties を以下のように書き換えます。

sbt.version=1.11.2

plugins.sbt

各sbtプラグインの最新のバージョン番号を調査し、project/plugins.sbt の当該箇所を書き換えてそのバージョンを使用させるようにします。
執筆時点(2025-06-30)では、書き換え後のproject/plugins.sbt は以下のようになります。

addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject"      % "1.3.2")
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2")
addSbtPlugin("org.scala-js"       % "sbt-scalajs"                   % "1.19.0")
addSbtPlugin("org.scala-native"   % "sbt-scala-native"              % "0.5.8")

build.sbt

sbtのビルドスクリプトである、build.sbt を以下のように書き換えます。scalaVersion は最新のものを使用してください。

import sbtcrossproject.CrossPlugin.autoImport.crossProject

val sharedSettings = Seq(
  scalaVersion := "3.7.1"
)

lazy val bar = crossProject(JSPlatform, JVMPlatform, NativePlatform)
  .settings(sharedSettings)
  .jsSettings(
    scalaJSUseMainModuleInitializer := true
  )

コードの最新バージョンへの追従

JSのFoo.scala

bar/js/src/main/scala/Foo.scala は現在のScala.jsでは古い書き方になっているため、bar/jvm/src/main/scala/Foo.scalaなど、他の Foo.scala と同一の内容で上書きしておきます。

実行

ここまでのところで、プロジェクトが各プラットフォームで正しくビルドおよび実行できることを確認します。

プロジェクトのルートディレクトリで sbt コマンドを叩いて sbtを起動し、表示された対話画面で barJVM/run, barNative/run, barJS/runをそれぞれ実行します。
これらのビルドおよび実行が正常に行われることを確認してください。

実戦に向けた改良

ここまでで、最新のScalaエコシステム上でマルチプラットフォームプロジェクトを運用するための最低限の処置を行いました。

ここからは、作成したプロジェクトを実戦で使えるように改良を加えていきます。

サブプロジェクトの名称変更

このプロジェクトの(唯一の)サブプロジェクトは現在 bar という名前ですが、これはあまり実戦的ではありません。そのため、これをより適当名前、ここでは例として "main" に書き換えておきます。

以下の手順を実行してください。

  1. プロジェクトルートの bar というディレクトリを main にリネームする
  2. build.sbtlazy val bar = ... という個所を lazy val main = ... に書き換える

Foo.scala のリネーム

main/{jvm,native,js}/src/main/scala/Foo.scala の名前もあまりよろしくないため、これらをすべて Main.scala という名前にリネームしてしまいます。

Main.scala のScala3化

Scalaは近年、2から3へとメジャーバージョンアップがあったのですが、このテンプレートでは追従できていません。
Scala3ではScala2で冗長だった箇所などが整理されたほか、各種括弧の省略ルールなどが強化され、よりエレガントな書き方ができるようになりました。
その恩恵にあずかるため、Main.scalaもすべてScala3準拠にアップデートしておきます。

すべての Main.scala を以下のように書き換えます:

@main def main(): Unit =
  println(Bar.a)

これらが終わったら再度 sbt の対話画面で reload を実行した後 mainJVM/run, mainNative/run, mainJS/run を実行し、ビルド等が正しく行われることを確認します。
なお、サブプロジェクト名を変更した影響で、実行時に入力する文字列も bar{JVM,Native,JS} から main{JVM,Native,JS} に変更となっていることに注意してください。

なお、Bar.scala はどうせ消してしまうので、Scala3には対応させません。

この後

この後は必要に応じて、パッケージを切る、main/shared 内にアプリケーションの実体を書いていく、などの作業を行っていきます。

  1. Kotlinでいう、Kotlin Multiplatformのようなものです

  2. Scalaのビルドツールの最大手

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?