Skip to main content

Package

The package command can package your Scala code in various formats, such as:

Default package format​

The default package format writes a lightweight launcher JAR, like the "bootstrap" JAR files generated by coursier. These JARs tend to have a small size (mostly containing only the byte code from your own sources), can be generated fast, and download their dependencies upon first launch, via coursier.

These can be copied onto other machines, and will run fine there. Their only requirement is that the java command needs to be available in the PATH:

Hello.scala
object Hello {
def main(args: Array[String]): Unit =
println("Hello")
}
scala-cli package Hello.scala -o hello
./hello
# Hello

Library JARs​

Library JARs are suitable if you plan to put the resulting JAR in a class path, rather than running it as is. These follow the same format as the JARs of libraries published to Maven Central:

MyLibrary.scala
package mylib

class MyLibrary {
def message = "Hello"
}
scala-cli package MyLibrary.scala -o my-library.jar --library
javap -cp my-library.jar mylib.MyLibrary
# Compiled from "MyLibrary.scala"
# public class mylib.MyLibrary {
# public java.lang.String message();
# public mylib.MyLibrary();
# }

Assemblies​

Assemblies blend your dependencies and your sources' byte code together in a single JAR file. As a result, assemblies can be run as is, just like bootstraps, but don't need to download anything upon first launch. Because of that, assemblies also tend to be bigger, and somewhat slower to generate:

Hello.scala
object Hello {
def main(args: Array[String]): Unit =
println("Hello")
}
scala-cli package Hello.scala -o hello --assembly
./hello
# Hello

Docker container​

Scala CLI can create an executable application and package it into a docker image.

For example, here’s an application that will be executed in a docker container:

HelloDocker.scala
object HelloDocker extends App {
println("Hello from Docker")
}

Passing --docker to the package sub-command generates a docker image. The docker image name parameter --docker-image-repository is mandatory.

The following command generates a hello-docker image with the latest tag:

scala-cli package --docker HelloDocker.scala --docker-image-repository hello-docker
docker run hello-docker
# Hello from Docker

You can also create Docker images for the Scala.js and Scala Native environments. This command shows how to create a Docker image (--docker) for a Scala.js (--js) application:

scala-cli package --js --docker HelloDocker.scala --docker-image-repository hello-docker

Packaging Scala Native applications to a Docker image is only supported on Linux.

This command shows how to do that:

scala-cli package --native --docker HelloDocker.scala --docker-image-repository hello-docker

Building Docker container from base image​

--docker-from lets you specify your base docker image.

The following command generate a hello-docker image using base image openjdk:11

scala-cli package --docker HelloDocker.scala --docker-from openjdk:11 --docker-image-repository hello-docker

Scala.js​

Packaging Scala.js applications results in a .js file, that can be run with node:

HelloJs.scala
object Hello {
def main(args: Array[String]): Unit =
println("Hello")
}
scala-cli package --js HelloJs.scala -o hello.js
node hello.js
# Hello

Note that the Scala CLI doesn't offer to link the resulting JavaScript with linkers, such as Webpack (yet).

Native image​

GraalVM native image allows to build native executables out of JVM applications. It can be used from Scala CLI to build native executables for Scala applications.

Hello.scala
object Hello {
def main(args: Array[String]): Unit =
println("Hello")
}
scala-cli package Hello.scala -o hello --native-image
./hello
# Hello

Note that Scala CLI automatically downloads and unpacks a GraalVM distribution using the JVM management capabilities of coursier.

Several options can be passed to adjust the GraalVM version used by Scala CLI:

  • --graalvm-jvm-id accepts a JVM identifier, such as graalvm-java17:22.0.0 or graalvm-java17:21 (short versions accepted).
  • --graalvm-java-version allows to specify only a target Java version, such as 11 or 17 (note that only specific Java versions may be supported by the default GraalVM version that Scala CLI picks)
  • --graalvm-version allows to specify only a GraalVM version, such as 22.0.0 or 21 (short versions accepted)

Scala Native​

Packaging a Scala Native application results in a native executable:

HelloNative.scala
object Hello {
def main(args: Array[String]): Unit =
println("Hello")
}
scala-cli package --native HelloNative.scala -S 2.13.6 -o hello
file hello
# hello: Mach-O 64-bit executable x86_64
./hello
# Hello

OS-specific packages​

Scala CLI also lets you package Scala code as OS-specific packages. This feature is somewhat experimental, and supports the following formats, provided they're compatible with the operating system you're running scala-cli on:

object Hello {
def main(args: Array[String]): Unit =
println("Hello")
}
scala-cli package --deb Hello.scala -o hello.deb
file hello
# hello: Mach-O 64-bit executable x86_64
./hello
# Hello

Debian​

DEB is the package format for the Debian Linux distribution. To build a Debian package, you will need to have dpkg-deb installed.

Example:

scala-cli package --deb --output 'path.deb' Hello.scala

Mandatory arguments​

  • version
  • maintainer
  • description
  • output-path

Optional arguments​

  • force
  • launcher-app
  • debian-conflicts
  • debian-dependencies
  • architecture

RedHat​

RPM is the software package format for RedHat distributions. To build a RedHat Package, you will need to have rpmbuild installed.

Example:

scala-cli package --rpm --output 'path.rpm' Hello.scala

Mandatory arguments​

  • version
  • description
  • license
  • output-path

Optional arguments​

  • force
  • launcher-app
  • release
  • rpm-architecture

macOS (PKG)​

PKG is the software package format for macOS. To build a PKG you will need to have pkgbuild installed.

Example:

`scala-cli package --pkg --output 'path.pkg` Hello.scala

Mandatory arguments​

  • version
  • identifier
  • output-path

Optional arguments​

  • force
  • launcher-app

Windows​

MSI is the software package format for Windows distributions. To build a Windows installer, you will need to have WIX Toolset installed.

Example:

scala-cli package --msi --output 'path.msi` Hello.scala

Mandatory arguments​

  • version
  • maintainer
  • licence-path
  • product-name
  • output-path

Optional arguments​

  • force
  • launcher-app
  • exit-dialog
  • logo-path