1. 序章

展開のためのアプリケーションのパッケージ化は、ほとんどのソフトウェア開発の最終ステップです。 アプリケーションをパッケージ化して共有する方法は複数あります。 要件に応じて、JAR、DEB、EXEなどのさまざまなタイプのパッケージを作成できます。 このチュートリアルでは、Scalaアプリケーションをパッケージ化するさまざまな方法について説明します。

2. SBTアセンブリ

アプリケーションをパッケージ化する最も簡単で簡単な方法は、JARファイルを使用することです。 JARファイルは、JREがインストールされている任意のプラットフォームで実行できます。 実行可能JARパッケージのもう1つの利点は、JARファイルを直接実行できるため、インストールの必要がないことです。 SBT Assembly は、ファットJARを作成するための一般的なSBTプラグインです。

2.1. 依存関係の追加

sbt-assembly を使用するには、plugins.sbtにプラグインの依存関係を追加する必要があります。

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.0")

次に、 os-lib ライブラリを使用するアプリケーションを作成しているとしましょう。これを、依存関係にも追加します。

libraryDependencies ++= Seq(
  "com.lihaoyi" %% "os-lib" % "0.7.8"
)

最後に、アプリケーションのメインクラスを作成しましょう。

package com.baeldung.packaging
import os._
@main def mainMethod() =
  val osName = System.getProperty("os.name")
  val path = os.pwd.toString
  println(s"""
    | Hello from the packaged app! 
    | Current Path: ${path}
    """.stripMargin)

これで、build.sbtで実行可能JARのメインクラスファイルを提供できます。

assembly / mainClass := Some("com.baeldung.packaging.mainMethod")

2.2. アセンブリJARの生成

次に、 sbt コマンドを実行して、アセンブリJARを生成しましょう。

sbt assembly

これにより、パスの下にアセンブリJARが生成されます /target/scala-3.1.0/ JARは次のように実行できます。

java -jar <assemblyjarfile.jar>

アセンブリは、異なるJARからのすべてのクラスファイルを単一のパスにフラット化します。 依存関係の数が増えると、アセンブリJARの作成が少し複雑になる可能性があります。したがって、複数のJARファイルからのファイル名の競合を処理するための構成を追加する必要がある場合があります。

3. SBTネイティブパッケージャー

SBT Native Packager は、ZIP、TAR、EXE、MSI、DEB、RPMなどのさまざまなプラットフォーム固有のパッケージを構築するために使用できるもう1つのプラグインです

3.1. 依存関係の追加

sbt-native-packager を使用する場合、plugins.sbtに依存関係を追加する必要があります。

addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.7")

それでは、build.sbtでプラグインを有効にしましょう。

enablePlugins(JavaAppPackaging)

次に、build.sbtでメインクラス名を指定できます。

maintainer := "Baeldung"
Compile / mainClass := Some("com.baeldung.packaging.mainMethod")

3.2. アプリのパッケージ化

パッケージ化されたアプリを作成するには、SBTコマンドを実行します。

sbt stage

これにより、パスの下にパッケージが作成されます / target / Universal / stage / stage ディレクトリー内で、 lib ディレクトリーはすべての依存関係JARを保持し、binディレクトリーはUnixおよびWindowsスタイルのスクリプトファイルの両方の実行可能ファイルを保持します。 ステージディレクトリ全体を任意の場所に移動し、スクリプトファイルを使用してアプリケーションを実行できます。 ZIPパッケージを作成するには:

sbt universal:packageBin

これにより、ステージディレクトリがZIPファイル形式に変換され、簡単に転送して実行できるようになります。

3.3. プラットフォーム固有のパッケージオプション

このプラグインを使用して、さまざまな種類のネイティブパッケージを作成できます。 ただし、これらのプラットフォーム固有のパッケージは、同じプラットフォームで作成する必要があります。 ただし、これらのプラットフォーム固有のパッケージを生成するための前提条件がある場合があります。 たとえば、Windows用の msi パッケージを生成するには、システムにWIXツールキットがすでにインストールされている必要があります。 同様に、 Debian パッケージの場合、関連するdpkgツールがすでにインストールされているはずです。 windows パッケージを作成するには、次のコマンドを使用する必要があります。

sbt windows:packageBin

Debian パッケージを作成するには:

sbt debian:packageBin

同様に、 rpm docker pkgなどの他のネイティブパッケージ形式を作成できます。

3.4. Jlinkパッケージの作成

このプラグインを使用して、jlinkベースのパッケージを作成することもできます。 jlinkは必要なJREモジュールをアプリケーションと一緒にラップするため、ターゲットマシンにJREをインストールしなくても、アプリは実行できます。 build.sbt でプラグインを有効にして、必要な構成を追加しましょう。

enablePlugins(JlinkPlugin)
jlinkIgnoreMissingDependency := JlinkIgnore.only(
  "scala.quoted" -> "scala",
  "scala.quoted.runtime" -> "scala"
)

jlink が推移的な依存関係の一部を自動的に処理できず、ビルドが失敗する場合があります。 JlinkIgnore 構成は、パッケージング中に提供された依存関係を無視するようにパッケージャーに通知します。 パッケージを作成するには、次のコマンドを実行する必要があります。

sbt universal:packageBin

これにより、アプリケーションを実行するために必要な最小限のJREモジュールとともにZIPファイルとしてパッケージ化されます。 jlinkパッケージは、JDK11以降からのみ機能することに注意してください。 JDK 10以下では、これを実行すると次のエラーで失敗します。

java.io.FileNotFoundException: $HOME/jvm/adopt@1.8.0-292/Contents/Home/jre/release (No such file or directory)

JREはプラットフォームに依存するため、jlinkパッケージはターゲットシステムと同じプラットフォームで実行する必要があります。

4. SBT ProGuard

ProGuard は、パッケージ化中にアプリケーションを難読化および最適化するために使用されるJavaベースのツールです。 これは、アプリのサイズが重要なAndroidやその他のプラットフォームで広く使用されています。 SBT ProGuard は、ProGuardツールを使用してScalaアプリケーションをパッケージ化するプラグインです。 まず、プラグインをplugins.sbtに追加しましょう。

addSbtPlugin("com.github.sbt" % "sbt-proguard" % "0.5.0")

次に、 build.sbt でプラグインを有効にし、基本的な構成を提供します。

enablePlugins(SbtProguard)
Proguard / proguardOptions ++= Seq("-dontoptimize","-dontnote", "-dontwarn", "-ignorewarnings")
Proguard / proguardOptions += ProguardOptions.keepMain("com.baeldung.packaging.mainMethod")
Proguard / proguardInputs := (Compile / dependencyClasspath).value.files
Proguard / proguardFilteredInputs ++= ProguardOptions.noFilter((Compile / packageBin).value)

proguardOptions フラグは、パッケージングプロセスの最適化と構成に役立ちます。 最後に、パッケージを生成しましょう。

sbt proguard

これにより、パスの下に実行可能JARファイルが生成されます /target/scala-3.1.0/proguard 。 これで、コマンドを使用して、他のJARファイルと同じようにアプリを実行できます。 java -jarassemblyProGuardの両方で生成されたJARファイルを比較すると、生成されたアセンブリJARファイルのサイズは7 MBですが、ProGuardJARファイルはわずか1MBです。[X180X ]

5. Scala-CLIの使用

Scala-CLIは、Scalaプログラムの作成と実行に使用できる新しいコマンドラインツールです。 一部の領域では、アンモナイトスクリプトに似ています。 scala-cliを使用して小さなScalaスクリプトを書くことができます。 さらに、スクリプトファイルを実行可能ファイルとしてパッケージ化して配布できます。 最初にツールをインストールする必要があります。 インストール後、次のコマンドを使用してインストールを確認できます。

scala-cli

正常にインストールされると、scala-cliヘルプ情報が出力されます。 次に、単純なアプリケーションをscala-cliスクリプトとして記述しましょう。

using scala "3.1.0"
package com.baeldung.scalacli
import $dep.`com.lihaoyi::os-lib:0.7.8`
import os._
object ScalaCliApp {
  @main def app() = {
    val osName = System.getProperty("os.name")
    val path = os.pwd.toString
    println(s"""
            | Hello from the scala-cli packaged app!
            | Current Path: ${path}
            """.stripMargin)
  }
}

ディレクティブusingを使用してScalaのバージョンを指定できます。 Scala-CLIは、 Ivy スタイルの構文に従って、外部の依存関係を追加します。 それでは、プログラムをコンパイルしましょう。

scala-cli compile ScalaCliApp.scala

最初の実行時に、scala-cliCoursierを使用して必要なすべての依存関係をダウンロードします。 次に、次のコマンドを使用してアプリケーションを実行できます。

scala-cli run ScalaCliApp.scala

最後のステップは、依存関係ライブラリを使用してアプリケーションをパッケージ化することです。

scala-cli package ScalaCliApp.scala -o app --assembly

–assembly フラグは、依存関係JARとともにアプリケーションをパッケージ化します。 これにより、appという名前の実行可能パッケージが生成されます。 これで、この生成されたアプリケーションを配布して、他の実行可能ファイルと同じように実行できます。 Scala-CLIは、小さなScalaファイルを配布するための優れたオプションです。 ただし、大きなプロジェクトを構築するのにはあまり理想的ではありません。 より複雑な要件が必要になる可能性があるため、より大きなアプリケーションを構築するにはSBTプロジェクトを使用することをお勧めします。 Scala-CLIは、プロトタイピング、実験、および単一ファイルのScalaアプリケーションの共有に適しています。

6. 結論

この記事では、Scalaアプリケーションをパッケージ化するさまざまな方法について説明しました。 いつものように、この記事で使用されているサンプルコードは、GitHubから入手できます。