• Stars
    star
    238
  • Rank 169,306 (Top 4 %)
  • Language
    Scala
  • Created about 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Plugin to generate native-image binaries with sbt

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_HOME or 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.
  • works with Scala 3 (Dotty)
  • 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

First, add the sbt plugin to your build in project/plugins.sbt.

// project/plugins.sbt
addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.2")

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")
    )

Additionally, if your app uses reflection or JNI, you may need to run nativeImageRunAgent command to capture runtime information. For more details, see nativeImageRunAgent section.

Finally, run the nativeImage task to generate the binary.

$ sbt
> myNativeImageProject/nativeImage
...
[info] Native image ready!
[info] /path/to/your/binary

Optionally, 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 binary

Configuration

sbt-native-image provides several settings, tasks and input tasks to customize native-image generation and to automate your native-image workflows.

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.2.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 the combinations below.

Example usage: nativeImageJvm := "graalvm"

nativeImageJvm nativeImageVersion nativeImageJvmIndex source
graalvm, graalvm-java11, graalvm-java17 1.0.0-x,19.0.0~21.1.0 cs https://github.com/coursier/jvm-index
graalvm-ce-java8, graalvm-ce-java11, graalvm-ce-java16 19.3~21.1.0 jabba https://raw.githubusercontent.com/shyiko/jabba/master/index.json

nativeImageJvmIndex

Type: SettingKey[String]

Description: the index to use for resolving the JVM version. By default, uses the Cousier JVM index.

Default: "cs". Must be one of: "cs", "jabba".

Example usage: nativeImageJvmIndex := "jabba".

nativeImageCommand

Type: TaskKey[Seq[String]]

Description: the base command that is used to launch native-image.

Default: resolves the command using nativeImageGraalHome task.

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"

nativeImageInstalled

Type: SettingKey[Boolean]

Description: whether GraalVM is manually installed or should be downloaded with coursier.

Default: checks if NATIVE_IMAGE_INSTALLED / GRAALVM_INSTALLED environment variables or native-image-installed / graalvm-installed properties are set to true.

nativeImageGraalHome

Type: TaskKey[Path]

Description: path to GraalVM home directory.

Default: if nativeImageInstalled is true, then tries to read the path from environment variables 1) GRAAL_HOME, 2) GRAALVM_HOME or 3) JAVA_HOME (in given order). Otherwise, automatically installs GraalVM via Coursier. Customize this setting if you prefer to not to use environment variables.

Example usage: nativeImageGraalHome := file("/path/to/graalvm/base/directory").toPath

nativeImageRunAgent

Type: InputKey[Unit]

Description: run application, tracking all usages of dynamic features of an execution with native-image-agent.

You may need to run this command if your app or any dependency uses reflection or JNI.

Example usage:

First, add the reflection configuration to the native image options

  // build.sbt

lazy val myNativeProject = project
  .settings(
+     nativeImageOptions += s"-H:ReflectionConfigurationFiles=${target.value / "native-image-configs" / "reflect-config.json"}",
+     nativeImageOptions += s"-H:ConfigurationFileDirectories=${target.value / "native-image-configs" }",
+     nativeImageOptions +="-H:+JNI"
  )
  .enablePlugins(NativeImagePlugin)

Then, make sure to generate the reflection configuration with nativeImageRunAgent before running nativeImage.

# Step 0: Start sbt shell.
$ sbt
# Step 1: Run application on the JVM with native-image agent.
> myProject/nativeImageRunAgent " arg1 arg2"
# Step 2: Create native-image binary with assisted configuration.
> myProject/nativeImage
# Step 3: Run native-image that was generated with assisted configuration.
> myProject/nativeImageRun arg1 arg2

nativeImageAgentOutputDir

Type: SettingKey[File]

Description: directory where native-image-agent should put generated configurations.

Default: baseDirectory.value / "native-image-configs"

Example usage: nativeImageAgentOutputDir := baseDirectory.value / "native-image-agent" / "out"

nativeImageAgentMerge

Type: SettingKey[Boolean]

Description: whether native-image-agent should merge generated configurations.

Default: false

Example usage: nativeImageAgentMerge := true

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.

  1. Copy the native.yml file 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
    
  2. Edit the file to replace "example" with the name of your binary.

  3. Commit your changes.

  4. Push your commit to GitHub and see the binary get uploaded as an artifact to the CI job.

  5. 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-image while 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.

More Repositories

1

metals

Scala language server with rich IDE features πŸš€
Scala
2,090
star
2

scalafmt

Code formatter for Scala
Scala
1,434
star
3

scalameta

Library to read, analyze, transform and generate Scala programs
Scala
1,112
star
4

nvim-metals

A Metals plugin for Neovim
Lua
459
star
5

munit

Scala testing library with actionable errors and extensible APIs
Scala
428
star
6

mdoc

Typechecked markdown documentation for Scala
Scala
394
star
7

metals-vscode

Visual Studio Code extension for Metals
TypeScript
298
star
8

sbt-scalafmt

sbt plugin for Scalafmt
Scala
201
star
9

coc-metals

Deprecated in favor of scalameta/nvim-metals
TypeScript
166
star
10

metabrowse

Static site generator for code search with IDE features for Scala
Scala
107
star
11

tutorial

Scalameta tutorial
JavaScript
72
star
12

scalagen

WIP - Scalameta powered code generation
Scala
39
star
13

metaconfig

Small library for reading configuration into case classes
Scala
38
star
14

metals-feature-requests

Issue tracker for Metals feature requests
37
star
15

svm-subs

GraalVM native-image substitutions for Scala
Java
25
star
16

metals-eclipse

Eclipse Scala LSP plugin for Metals (WIP)
Scala
22
star
17

moped

Scala
19
star
18

lsp4s

Scala implementation for JSON-RPC and Language Server Protocol
Scala
19
star
19

metals-gitpod-sample

Scala
18
star
20

metals-sublime

Sublime Text package for Metals, a language server for Scala
Python
16
star
21

sbt-semantic-example

DEPRECATED - minimal template to play with the Scalameta semantic API
Scala
15
star
22

fastpass

Command-line tool to export a Pants build to Bloop
Scala
9
star
23

metals-languageclient

Language client library for Node.js Metals clients
TypeScript
9
star
24

mill-scala-seed.g8

A Giter8 template for a sample Scala project using the Mill build tool.
Shell
8
star
25

trees

Scalameta syntax tree definitions
Scala
7
star
26

semanticdb-sbt

Compiler plugin to build Semantic DB for sbt 0.13.
Scala
4
star
27

lsp-example

Minimal example to get started with implementing a language server in Scala
TypeScript
3
star
28

gradle-scala-seed.g8

A Giter8 template for a sample Scala project using the Gradle build tool!
Scala
3
star
29

scalameta.github.io

Scalameta website. No PRs here, this repo contains generated artifacts from https://github.com/scalameta/tutorial
HTML
2
star
30

maven-scala-seed.g8

A Giter8 template for a sample Scala project using the Maven build tool!
Scala
1
star