Creating CLI tools with Scala, Picocli and GraalVM

Previously, I wrote an article about how to create CLI tools with Scala. As I wrote in the article, writing CLI tools with Scala has various advantages for me as a Scala programmer.

However, there is a disadvantage that is the overhead of launching JVM. I was wondering if we can create a native image of my Scala-based CLI tools using GraalVM. Recently, I found Picocli which is a framework for Java-based CLI applications with native-image creation supports by GraalVM.

Immediately, I started trying to use Picocli with Scala.

Create SBT project

I tried to port checksum command which is explained in the documentation of picocli to Scala. Firstly, I created a simple Picocli available project.

Source code of the checksum command itself:

As you can see, this is a normal Scala program except that we have to define fields as var and be annotated by picocli’s annotations.

Run annotation processor

Picocli offers code generation by annotation processor for GraalVM native-image support. This means we need to run the annotation processor on SBT before creating native-image.

The annotation processor is included in picoli-codegen. We need to add it to the library dependencies as provided scope.

Also, I added the following configuration to build.sbt to run the annotation processor as processAnnotation task.

Install GraalVM

To create a native image, we, of course, need to install GraalVM. We can download GraalVM Community Edition from GitHub.

Extract tar.gz and add bin directory to PATH. Then install native-image command using gu command as follows:

Create native image

I used sbt-native-packager to create a native-image on SBT.

Added a line below to project/plugins.sbt:

Also, added the following configuration to enable native-image creation with annotation processing defined in advance:

Everything is ready. Now we can generate a native image by running SBT as follows:

A binary is generated under target/graalvm-native-image with the project name. Let’s run the generated binary.

It worked!

Conclusion

We can create a native image of Scala-based CLI tools with Picocli and GraalVM. Of course, as you may know, there are several restrictions in native-image by GraalVM. For example, the use of reflection is restricted. However, if you want to create CLI tools which don’t have the overhead of launching JVM, it would be a promising solution.

By the way, there is another solution, scala-native in the Scala world. However, scala-native faces a lack of development resource. Actually, it still stays at Scala 2.11. Also, few libraries support scala-native. I think GraalVM is a better solution for creating native-image in Scala at this moment.

A project I created through this article is below: