Generate native-image binaries with sbt
This plugin makes it easy to generate native-image binaries with sbt. Key features:
- automatic GraalVM native-image installation powered by
Coursier, no need to start sbt with a custom
$JAVA_HOMEor spin up Docker. See One-click install for Scala for more details. - automatic support for Scala 2.12.12+ and 2.13.3+, no need to deal with issues like scala/bug#11634.
- get a notification when the binary is ready to use.
- works on macOS, Windows and Linux.
- works with Java 8 and Java 11.
Overview:
- Getting started
- Configuration
- Generate native-image from GitHub Actions
- Comparison with sbt-native-packager
Getting started
First, add the sbt plugin to your build in project/plugins.sbt.
// project/plugins.sbt
addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.2.1")Next, enable the plugin to your native-image application in build.sbt and
configure the main class.
// build.sbt
lazy val myNativeImageProject = project
+ .enablePlugins(NativeImagePlugin)
.settings(
// ...
+ Compile / mainClass := Some("com.my.MainClass")
)Finally, run the nativeImage task to generate the binary.
$ sbt
> myNativeImageProject/nativeImage
...
[info] Native image ready!
[info] /path/to/your/binaryOptionally, use nativeImageRun to execute the generated binary and manually
test that it works as expected.
> myNativeImageProject/nativeImageRun argument1 argument 2
# output from your native-image binaryConfiguration
sbt-native-image provides several settings, tasks and input tasks to customize native-image generation and to automate your native-image workflows.
nativeImage: generate a native imagenativeImageOptions: customize native image generationnativeImageRun: execute the generated native imagenativeImageCopy: generate a native image and copy the binarynativeImageVersion: the GraalVM version to use for native-imagenativeImageJvm: the GraalVM JVM version to use for native-imagenativeImageCommand: the command to launchnative-imagenativeImageReady: callback hook when native-image is readynativeImageCoursier: the path to acoursierbinarynativeImageOutput: the path to the generated native-image binary
nativeImage
Type: TaskKey[File]
Description: runs native-image and returns the resulting binary file.
Example usage: sbt myProject/nativeImage
nativeImageOptions
Type: TaskKey[Seq[String]]
Description: custom native-image linking options. See native-image --help
for available options. Empty by default.
Example usage: nativeImageOptions ++= List("--initialize-at-build-time")
nativeImageRun
Type: InputKey[File]
Description: executes the native-image binary with given arguments. This
task can only be used after nativeImage has completed.
Example usage:
sbt myProject/nativeImage 'myProject/nativeImageRun hello'- Error:
sbt clean myProject/nativeImageRun. Crashes because native-image does not exist.
nativeImageCopy
Type: InputKey[File]
Description: identical to nativeImage except the resulting binary is
additionally copied to the provided file. This task is helpful when configuring
CI to generate the binary in a specific place.
Example usage:
sbt 'myProject/nativeImageCopy mybinary-x86_64-apple-darwin'.sbt 'myProject/nativeImageCopy mybinary-x86_64-pc-linux'.
nativeImageVersion
Type: SettingKey[String]
Description: the GraalVM version to use.
Default: 20.1.0
Example usage: nativeImageVersion := "19.3.3"
nativeImageJvm
Type: SettingKey[String]
Description: the GraalVM JVM version to use.
Default: "graalvm-java11". Must be one of: "graalvm-java11", "graalvm"
(Java 8).
Example usage: nativeImageJvm := "graalvm"
nativeImageCommand
Type: TaskKey[Seq[String]]
Description: the base command that is used to launch native-image.
Default: automatically installs GraalVM native-image via
Coursier. Customize this setting if you prefer to
manually install native-image.
Example usage: nativeImageCommand := List("/path/to/native-image")
nativeImageReady
Type: SettingKey[() => Unit]
Description: a side-effecting callback that is called the native image is ready.
Default: alerts the message "Native image ready!" via the say command-line
tool on macOS. Does nothing by default on Linux and Windows.
nativeImageCoursier
Type: TaskKey[File]
Description: the path to a coursier binary.
Default: copies a slim bootstrap binary from sbt-native-image resources.
This setting is ignored if you customize nativeImageCommand to use something
else than Coursier.
nativeImageOutput
Type: SettingKey[File]
Description: the path to the native-image binary that is generated.
Default: target/native-image/NAME where NAME is the name of the sbt
project. for available options.
Example usage: nativeImageOutput := file("target") / "my-binary"
Generate native-image from GitHub Actions
The easiest way to distribute native-image binaries for Linux and macOS is to build the binaries in CI with GitHub Actions.
-
Copy the
native.ymlfile from this repo into the.github/workflows/directory in your project.mkdir -p .github/workflows && \ curl -L https://raw.githubusercontent.com/scalameta/sbt-native-image/master/.github/workflows/native.yml > .github/workflows/native.yml -
Edit the file to replace "example" with the name of your binary.
-
Commit your changes.
-
Push your commit to GitHub and see the binary get uploaded as an artifact to the CI job.
-
Create a GitHub release and see the binary get uploaded as assets to the release page.
Comparison with sbt-native-packager
The sbt-native-packager plugin provides similar support to generate native-image binaries. Check out their documentation at https://sbt-native-packager.readthedocs.io/en/stable/formats/graalvm-native-image.html
The key differences between sbt-native-packager and sbt-native-image are:
- sbt-native-image automatically installs GraalVM native-image by default. You don't need to configure a docker image or manually install a correct GraalVM JDK before starting sbt.
- sbt-native-image automatically works out-of-the-box with Scala 2.12.12+ and 2.13.3+. You don't need custom settings to work around issues like like scala/bug#11634.
- sbt-native-image displays live progress output from the
native-imagewhile it's generating the binary. For some reason, sbt-native-packager only displays output from native-image after the process completes (see issue #1345). - sbt-native-packager has Docker support, which is helpful if you need more fine-grained control over the linking environment. There are no plans to add Docker support in sbt-native-image.

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.
