Package
The package
command can package your Scala code in various formats, such as:
- lightweight launcher JARs
- standard library JARs
- so called "assemblies" or "fat JARs"
- docker container
- JavaScript files for Scala.js code
- GraalVM native image executables
- native executables for Scala Native code
- OS-specific formats, such as deb or rpm (Linux), pkg (macOS), or MSI (Windows)
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
:
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:
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:
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:
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
:
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.
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 asgraalvm-java17:22.0.0
orgraalvm-java17:21
(short versions accepted).--graalvm-java-version
makes it possible to specify only a target Java version, such as11
or17
(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 as22.0.0
or21
(short versions accepted)
Scala Native
Packaging a Scala Native application results in a native executable:
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.