GraalVM Native Image with Scala 3 and sbt

Are there ‘official’ examples on how to create native images with Scala 3 and GraalVM?

I have the following build.sbt:

ThisBuild / scalaVersion := "3.3.1"
ThisBuild / version := "0.1.0"
ThisBuild / organization := "com.example"

lazy val root = (project in file("."))
  .settings(
    name := "scala-native-hello-world",
    libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test,

    addCompilerPlugin("org.graalvm.nativeimage" % "native-image" % "22.3.0"),
    nativeImageOptions := Seq(
      "--no-fallback",
      "-H:+ReportUnsupportedElementsAtRuntime",
      "-H:+ReportExceptionStackTraces"
    )
  )

plugins.sbt:

addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.4.0")

and get the following error:

[info] welcome to sbt 1.10.2 (Azul Systems, Inc. Java 21.0.4)
[info] loading settings for project scala-native-hello-world-build from plugins.sbt ...
[info] loading project definition from /Users/myUser/development/playground/graalvm/scala-native-hello-world/project
[info] Updating scala-native-hello-world-build
[info] Resolved scala-native-hello-world-build dependencies
[warn]
[warn] 	Note: Some unresolved dependencies have extra attributes.  Check that these dependencies exist with the requested attributes.
[warn] 		org.scalameta:sbt-native-image:0.4.0 (sbtVersion=1.0, scalaVersion=2.12)
[warn]
[warn] 	Note: Unresolved dependencies path:
[error] sbt.librarymanagement.ResolveException: Error downloading org.scalameta:sbt-native-image;sbtVersion=1.0;scalaVersion=2.12:0.4.0
[error]   Not found
[error]   Not found
[error]   not found: https://repo1.maven.org/maven2/org/scalameta/sbt-native-image_2.12_1.0/0.4.0/sbt-native-image-0.4.0.pom
[error]   not found: /Users/myUser/.ivy2/localorg.scalameta/sbt-native-image/scala_2.12/sbt_1.0/0.4.0/ivys/ivy.xml
[error]   not found: https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/org.scalameta/sbt-native-image/scala_2.12/sbt_1.0/0.4.0/ivys/ivy.xml
[error]   not found: https://repo.typesafe.com/typesafe/ivy-releases/org.scalameta/sbt-native-image/scala_2.12/sbt_1.0/0.4.0/ivys/ivy.xml
[error] 	at lmcoursier.CoursierDependencyResolution.unresolvedWarningOrThrow(CoursierDependencyResolution.scala:346)
[error] 	at lmcoursier.CoursierDependencyResolution.$anonfun$update$39(CoursierDependencyResolution.scala:315)
[error] 	at scala.util.Either$LeftProjection.map(Either.scala:573)
[error] 	at lmcoursier.CoursierDependencyResolution.update(CoursierDependencyResolution.scala:315)
[error] 	at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:60)
[error] 	at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:60)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:142)
[error] 	at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:74)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:144)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:131)
[error] 	at sbt.util.Tracked$.$anonfun$inputChangedW$1(Tracked.scala:220)
[error] 	at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:169)
[error] 	at sbt.Classpaths$.$anonfun$updateTask0$1(Defaults.scala:3894)
[error] 	at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] 	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:63)
[error] 	at sbt.std.Transform$$anon$4.work(Transform.scala:69)
[error] 	at sbt.Execute.$anonfun$submit$2(Execute.scala:283)
[error] 	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:24)
[error] 	at sbt.Execute.work(Execute.scala:292)
[error] 	at sbt.Execute.$anonfun$submit$1(Execute.scala:283)
[error] 	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] 	at sbt.CompletionService$$anon$2.call(CompletionService.scala:65)
[error] 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
[error] 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
[error] 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
[error] 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
[error] 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
[error] 	at java.base/java.lang.Thread.run(Thread.java:1583)
[error] (update) sbt.librarymanagement.ResolveException: Error downloading org.scalameta:sbt-native-image;sbtVersion=1.0;scalaVersion=2.12:0.4.0
[error]   Not found
[error]   Not found
[error]   not found: https://repo1.maven.org/maven2/org/scalameta/sbt-native-image_2.12_1.0/0.4.0/sbt-native-image-0.4.0.pom
[error]   not found: /Users/myUser/.ivy2/localorg.scalameta/sbt-native-image/scala_2.12/sbt_1.0/0.4.0/ivys/ivy.xml
[error]   not found: https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/org.scalameta/sbt-native-image/scala_2.12/sbt_1.0/0.4.0/ivys/ivy.xml
[error]   not found: https://repo.typesafe.com/typesafe/ivy-releases/org.scalameta/sbt-native-image/scala_2.12/sbt_1.0/0.4.0/ivys/ivy.xml
[warn] Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore? (default: r)
´´´

The last released version of this plugin is 0.3.4

For simple projects you can consider using scala-cli (or simply scala since 3.5.0)

scala package --native-image \
  --graalvm-args --no-fallback \
  --graalvm-args -H:+ReportUnsupportedElementsAtRuntime  \
  test.scala 
1 Like

Thank you! Now tried it as described in the link you provided but I get the following error:

Downloading https://github.com/coursier/jvm-index/raw/master/index.json
Downloaded https://github.com/coursier/jvm-index/raw/master/index.json
JVM graalvm-java11:20.2.0 not found in index: No graalvm-java11 version matching '20.2.0' found
[error] stack trace is suppressed; run last nativeImageGraalHome for the full output
[error] (nativeImageGraalHome) Nonzero exit value: 1
[error] Total time: 7 s, completed Oct 14, 2024, 5:51:20 PM

Does that mean my JDK is too new?

Versions 20.2.0 can be easily found in the coursier index file from logs, so maybe there is some bug in the plugin. The index itself defines different available versions depending on OS/CPU combination, check if it contains suitable for your machine. If it’s defined but not available for 20.2.0 version you set choose different one using nativeImageVersion and nativeImageJvm sbt settings.
If the correct version is present in the file, but you still cannot download it, then you can consider using other version of the plugin, or try to install directly using coursier.