Skip to content

Latest commit

 

History

History
167 lines (106 loc) · 8.69 KB

README.adoc

File metadata and controls

167 lines (106 loc) · 8.69 KB

Building native CLI apps in Java with picocli and GraalVM (Maven version)

Travis Build Status

Examples of using Maven to create GraalVM native images for picocli-based applications

Caution
Below is work in progress
exe picocli on graalvm

Introduction

This project shows examples of creating native images for picocli-based Java command line applications that can run as standalone executables on Windows, Linux and MacOS without requiring a JVM to be installed.

This project uses Maven, see the picocli-native-image-demo project for an example that uses Gradle.

Artifacts

CheckSum

The main project builds a checksum executable. This is a picocli-based command line application. On Windows it uses Jansi to show colors on the console and the picocli-jansi-graalvm library to enable the Jansi library for GraalVM native applications.

Windows Note

The Windows executables created with the Java 8 version of GraalVM depend on the msvcr100.dll native library. Windows executables created with the Java 11 version of GraalVM depend on the VCRUNTIME140.dll native library.

You will have to distribute these DLLs with your application, or tell your users to download and install the Microsoft Visual C++ 2015 Redistributable Update 3 RC to get the VCRUNTIME140.dll for Java 11-based native images, or Microsoft Visual C++ 2010 SP1 Redistributable Package (x64) to get the msvcr100.dll for Java 8-based native images.

Testing Native Images

This project uses JUnit 5 for testing. It has a unit test that is run before the JAR file is created, and an integration test that is run after the native image is generated.

The integration test is tagged with @org.junit.jupiter.api.Tag("native-image"), and this tag is used in the Maven Surefire and Maven Failsafe plugins to ensure that only the unit tests run before the JAR is created, and only the integration tests are run after the native image has been generated.

Cross Compilation

GraalVM does not have cross-compile support for native images yet, so at the moment you need to compile on Windows to get a Windows executable, compile on Linux to get a Linux executable, and on MacOS to get a MacOS executable.

This project shows how to do this with TravisCI. The current setup creates Linux, MacOS and Windows executables on TravisCI.

Installing GraalVM

This project provides a install-graal.sh script to install GraalVM for Linux, and a install-graal.cmd Windows version. The Windows version will also attempt install the Windows Compiler Toolchain for the selected Java version via chocolatey if it does not exist.

The install script will cache the download and installation in ~/.m2/caches/info.picocli.graal, so that subsequent invocations can reuse the previously downloaded GraalVM installation.

The script will set the JAVA_HOME variable to the GraalVM installation directory. Always run the install-graal script before running the mvnw clean verify build with Maven.

Alternative: SDKMAN!

An alternative for Unix-based systems is to use the bash-based SDKMAN! to install and manage the GraalVM installation.

Windows Git Bash users may need to download zip, which is not included by Windows Git Bash by default. To resolve this, go to https://sourceforge.net/projects/gnuwin32/files/ and find zip in the list. Download zip-3.0-bin.zip and extract zip.exe in the bin folder. Copy it to c:\Program Files\Git\usr\bin. Now run the SDKMan install script again.

Install Compiler Toolchain

The setup for your Continuous Integration environment needs to have a JDK, and the toolchain to compile C/C++ code.

Linux and MacOS Compiler Toolchain

For compilation native-image depends on the local toolchain, so on Linux and MacOS we need glibc-devel, zlib-devel (header files for the C library and zlib) and gcc to be available on our system. The below is not required with GitHub Actions, since these are already available:

On Linux: sudo dnf install gcc glibc-devel zlib-devel or sudo apt-get install build-essential libz-dev.

On macOS, execute xcode-select --install.

Windows Compiler Toolchain for Java 8

Note
It turns out to be surprisingly difficult to get the below toolchain set up in the various CI build environments. I recommend using the setup for Java 11 instead. Many CI build environments already have visualstudio2017-workload-vctools set up, so all that is needed is to activate the environment.

To build native images using the Java 8 version of GraalVM, you need the Microsoft Windows SDK for Windows 7 and .NET Framework 4 as well as the C compilers from KB2519277. You can install these using chocolatey:

choco install windows-sdk-7.1 kb2519277

Then (from the cmd prompt), activate the sdk-7.1 environment:

call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd"

This starts a new Command Prompt, with the sdk-7.1 environment enabled. All subsequent commands must be run in this Command Prompt window.

Windows Compiler Toolchain for Java 11

To build native images using the Java 11 version of GraalVM (19.3.0 and greater), install the Visual C++ Build Tools Workload for Visual Studio 2017 Build Tools using chocolatey:

choco install visualstudio2017-workload-vctools

After installation, set up the environment from the cmd prompt with this command:

call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"

Then run native-image in that Command Prompt window.

Maven

The Graal team publishes a Maven plugin called native-image-maven-plugin that can invoke the native-image generation tool. This project uses this plugin for generating a native image.

The native-image-maven-plugin Maven plugin is not as powerful as the Palantir Gradle-Graal plugin, in that it requires GraalVM to be installed; it cannot download and install GraalVM for you.

This project provides install-graal scripts that take care of the GraalVM installation. Always run the install-graal script before running the mvnw clean verify build with Maven. The script will set the JAVA_HOME variable to the GraalVM installation directory. On Windows, this script will activate the sdk-7.1 environment.

You can pass additional arguments to the underlying native-image generator command with the buildArgs system property. On Linux, you may want to run the maven build with:

./mvnw -DbuildArgs=--no-server clean verify