graalvm

markaddleman 2024-04-01T14:49:22.406169Z

I’m trying to build a native image of an internal clojure service. I can successfully create the binary but when I execute it, I get Could not locate clojure/core/server__init.class, clojure/core/server.clj or clojure/core/server.cljc on classpath . First of all, I’m puzzled why clojure.core.server is being loaded. It’s not referenced in my source. Regardless, I can’t find the right twiddleebits to get around this problem. The relevant clojure.core.server class files are in my uber jar. My native-image command is

native-image -jar target/service-standalone.jar --no-fallback --initialize-at-build-time=org.slf4j.helpers,clojure --initialize-at-run-time=clojure.lang.Compiler
Has anyone seen this problem?

borkdude 2024-04-01T14:52:03.083199Z

yes, you need to use --initialize-at-build-time= for every clojure package. when using https://github.com/clj-easy/graal-build-time this will be done automatically

borkdude 2024-04-01T14:52:39.710989Z

also probably remove --initialize-at-run-time=clojure.lang.Compiler

markaddleman 2024-04-01T14:55:00.574289Z

Doh! I included graal-build-time in my deps.edn but I forgot to add --features=clj_easy.graal_build_time.InitClojureClasses to my native-image command line

greg 2024-04-01T17:03:31.546559Z

I'm looking at some examples of compiling Clojure with GraalVM, and I noticed that many sample projects in https://github.com/clj-easy/graalvm-clojure/tree/master, if not all, use:

:aot :all
Same says the guide: https://github.com/clj-easy/graalvm-clojure/blob/master/doc/clojure-graalvm-native-binary.md On the other hand babashka sets:
:main babashka.main
:aot [babashka.main]
I don't assume anything, I'm just curious. Is it better to aot only the main?

borkdude 2024-04-01T17:22:59.072149Z

Avoid aot all, it can cause stuff to be compiled twice and cause weird bugs

👍 1
lread 2024-04-01T21:39:16.771409Z

@borkdude I can update the guide and add a tip about aot all being problematic…

👍 1
greg 2024-04-01T18:35:17.559499Z

I took graal-build-time 2.0.5 and I noticed this log:

[clj-easy/graal-build-time] Registering packages for build time initialization: clojure, clj_easy.graal_build_time, simplecgt.web.server
Is that correct for list to include clj_easy.graal_build_time ? It sounds like the package is included in the final binary. Shouldn't only facilitate the graalvm compilation?

borkdude 2024-04-01T18:39:11.065979Z

Dunno, did you include the dependency on the classpath of the uberjar and did you use aot all? If yes, then don't do that

greg 2024-04-01T21:57:01.997429Z

So what I got: • graal-built-time in classpath for uberjar • aot only for main • the only build time flag related to initialize is: --features=clj_easy.graal_build_time.InitClojureClasses Here is this demo: • https://github.com/rynkowsg/simple-cgt-web/blob/main/scripts/compile-native.bash#L17https://github.com/rynkowsg/simple-cgt-web/blob/main/project.clj

borkdude 2024-04-01T21:59:23.235209Z

o wait, you do need it

borkdude 2024-04-01T21:59:59.337379Z

but I don't think your image will actually contain any of this tool, it's probably how this is supposed to work

borkdude 2024-04-01T22:00:48.654569Z

graalvm will cut out anything that is not reachable from your main entry point

greg 2024-04-01T22:01:01.023309Z

Tbh I only noticed the log so I was curios whether this end up in the final binary or not

greg 2024-04-01T22:01:11.698019Z

oh, nice