lein-native-image
A Leiningen plugin for generating GraalVM native images from your project.
The lein native-image
command compiles your project then uses GraalVM's native-image
to build a native image.
Prerequisites
- This plugin depends on GraalVM to build native images.
- Your project.clj must specify a
:main
namespace w/entrypoint and support AOT compilation. Here's an example:(defproject my-app "0.1.0" :dependencies [[org.clojure/clojure "1.9.0"]] :plugins [[io.taylorwood/lein-native-image "0.3.0"]] :native-image {:graal-bin "/path/to/graalvm-1.0.0-rc1/Contents/Home/bin" :name "my-app"} :main ^:skip-aot my-app.core :profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]]} :test ;; e.g. lein with-profile test native-image {:native-image {:opts ["-H: ReportUnsupportedElementsAtRuntime" "--verbose"]}} :uberjar {:aot :all :native-image {:opts ["-Dclojure.compiler.direct-linking=true"]}}})
Usage
See the examples directory for apps that can be compiled to native images with GraalVM.
-
Put
[io.taylorwood/lein-native-image "0.3.0"]
into the:plugins
vector of your project.clj, or in your Leiningen user profile. -
Optionally specify a custom image name, path to GraalVM's
bin
directory ornative-image
path, ornative-image
CLI options in your project.clj:(defproject my-app "0.1.0" :native-image {:name "my-app" :graal-bin "/path/to/graalvm-1.0.0-rc1/bin" :opts ["--verbose"]})
-
:name
is an optional name for the generated native image. - The
:graal-bin
path can be specified as a string or resolved from an environment variable using a keyword e.g.:env/GRAALVM_HOME
. If:graal-bin
is unspecified, theGRAALVM_HOME
environment variable will be used by default. -
:opts
is an optional vector of arguments tonative-image
; see its documentation for more.
The plugin will merge the task-specific profile
:native-image
, or:uberjar
if that doesn't exist.You can also specify these in your Leiningen user profile
~/.lein/profiles.clj
:{:user {:plugins [[io.taylorwood/lein-native-image "0.3.0"]] :native-image {:graal-bin "/path/to/graalvm-1.0.0-rc1/Contents/Home/bin"}}}
-
-
Build a native image from your project:
➜ lein native-image Compiling my-app.core Build on Server(pid: 36212, port: 26681) classlist: 332.89 ms (cap): 1,289.90 ms 8<---------------------- write: 932.61 ms [total]: 11,789.08 ms Created native image /Users/Taylor/Projects/my-app/target/my-app
-
Execute the native image:
➜ ./target/my-app with optional args Hello, World!
Notes
GraalVM and Substrate VM's support for AOT compilation and native images is evolving. There are limitations and unsupported features you will likely encounter. This release was tested with GraalVM 1.0.0-RC1 EE; some of these notes may not apply to future releases. At least one AOT issue has been fixed since 1.0.0-RC1, but you must build Substrate VM locally to get unreleased fixes.
When the :opts ["-H: ReportUnsupportedElementsAtRuntime"]
flag is set, some native-image
build issues will be deferred as runtime exceptions.
To avoid spurious runtime errors, don't use this flag for "production" builds.
You may need to specify :opts ["-H:EnableURLProtocols=http"]
to use HTTP libraries.
HTTPS is currently in development and unsupported!
Specifying :jvm-opts ["-Dclojure.compiler.direct-linking=true"]
might allow for better optimizations by GraalVM.
This plugin doesn't shutdown GraalVM native-image
build servers after builds, so that subsequent builds are slightly faster.
You can specify :opts ["--no-server"]
to not spawn a build server at all, or use other native-image
commands to manage build server(s).
References
GraalVM Native Image AOT Compilation
Instant Netty Startup using GraalVM (and source)
Contributing
You'll need Leiningen and GraalVM installed to build and test the plugin.
Issues, PRs, and suggestions are welcome!
License
Copyright © 2018 Taylor Wood.
Distributed under the MIT License.