0.4.8 (2022-11-09)

We’re happy to announce the release of Scala Native 0.4.8. The latest release brings multiple bugfixes and implementation optimizations, as well as new exciting features including building dynamic libraries, configurable optimizer, and easier access to arrays underlying memory.


Scala standard library used by this release is based on the following versions:

Scala binary version Scala release
2.11 2.11.12
2.12 2.12.17
2.13 2.13.10
3 3.2.1
Merged PRs 59
Contributors 10

Contributors

Big thanks to everybody who contributed to this release or reported an issue!

$ git shortlog -sn --no-merges v0.4.7..v0.4.8
    18	LeeTibbert
    18	Wojciech Mazur
    11	Arman Bilge
     6	Eric K Richardson
     5	David Bouyssié
     2	Mark Hammons
     1	Daniel Esik
     1	Jamie Willis
     1	João Costa
     1  Liangyong Yu

New features

Producing native libraries using Scala Native

Scala Native can now produce both dynamic and static libraries. This features allows to use Scala Native code in foreign runtimes, eg. in C, Rust or on the JVM. To enable this feature switch the build target of your project and annotate entry points for library using @exported annotation.

import scala.scalanative.build.BuildTarget
nativeConfig ~= {
  _.withBuildTarget(BuildTarget.libraryDynamic)
}

Only statically reachable functions can be exported in your library. Exporting module fields is not allowed, however, you can export their accessor using @exportAccessors annotation.

object Foo {
  @exportAccessors
  var counter: Int = 0

  @exportAccessors("error_message")
  val ErrorMessage: CString = c"Something bad just happened!"

  @exported
  def addLongs(l: Long, r: Long): Long = l + r
}

This feature is treated as experimental and might change in the future. For more information see dedicated interop section and available build targets list.

Configurable Scala Native optimizer

In the past, we have observed very long build times for some projects using Scala Native. In most of them, most of the time was spent in the optimizer, especially when using release-full build mode. Now Scala Native can be configured to limit the amount of inlines, which in some cases might have been too eager.

// build.sbt
nativeConfig ~= { config => 
  val optimizerConfig = config.optimizerConfig
  config.withOptimizerConfig{
    optimizerConfig
      .withMaxInlineDepth(10)   // Maximal amount of nested inlines - default=None
      .withMaxCallerSize(8192)  // Maximal number of instructions in caller function - default=8192
      .withMaxInlineSize(8)     // Maximal number of instructions in inlined function - default=8
  }
}

Easier access to arrays underlying memory

When interacting with native code it is sometimes expected to allocate memory Garbage Collected memory and access it directly as a pointer type. So far it was allowed to access the underlying memory of Scala Arrays, but it needed knowledge about internals of the Scala Native runtime. Now you can use the dedicated extension method instead to make this easier.

@main def sandbox = {
  import scala.scalanative.unsafe.*
  val arr: scala.Array[Byte] = new Array[Byte](1024)
  val ptr: Ptr[Byte] = arr.at(0) 
}

Merged PRs

v0.4.8 (2022-11-09)

Full Changelog

Merged pull requests:

Scala Native Compiler Plugin

Scala Native toolchain

Scala Native Standard Library

Posix library

Java Standard Library

Other