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.

Such JARs can be copied to 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 Scala.js and Scala Native applications. The following 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.

The following 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, which 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 Scala CLI doesn't offer the ability to link the resulting JavaScript with linkers, such as Webpack (yet).

Native image

GraalVM native image makes it possible 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 makes it possible 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 makes it possible 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 a 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 a software package format for Windows. To build an MSI 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

Using directives

Instead of passing the package options directly from bash, it is possible to pass some of them with using directives.

packaging.packageType

This using directive makes it possible to define the type of the package generated by the package command. For example:

//> using packaging.packageType "assembly"

Available types: assembly, raw-assembly, bootstrap, library, source, doc, spark, js, native, docker, graalvm, deb, dmg, pkg, rpm, msi.

packaging.output

This using directive makes it possible to define the destination path of the package generated by the package command. For example:

//> using packaging.output "foo"

The using directive above makes it possible to create a package named foo inside the current directory.