This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-25
Channels
- # announcements (21)
- # babashka (7)
- # beginners (27)
- # calva (7)
- # chlorine-clover (3)
- # cider (1)
- # clerk (21)
- # clojure (24)
- # clojure-europe (28)
- # clojure-finland (3)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-uk (2)
- # clojurescript (13)
- # clr (2)
- # conjure (1)
- # consulting (1)
- # datahike (1)
- # datomic (13)
- # fulcro (3)
- # graalvm (33)
- # gratitude (7)
- # honeysql (7)
- # humbleui (12)
- # hyperfiddle (26)
- # interop (11)
- # introduce-yourself (4)
- # jobs-discuss (8)
- # lsp (26)
- # malli (6)
- # nbb (11)
- # polylith (26)
- # practicalli (1)
- # rdf (3)
- # re-frame (7)
- # reitit (10)
- # releases (2)
- # shadow-cljs (1)
- # tools-deps (15)
Just adding a small echo that https://github.com/clj-easy/graal-docs/blob/master/doc/hello-world.md did in fact work
Now I'm on a quest to get static linking working.
Currently this far. It required a manual specification of --native-compiler-path
on my particular OS.
Unfortunately...
/bin/ld: cannot find -lz: No such file or directory
collect2: error: ld returned 1 exit status
And https://docs.oracle.com/en/graalvm/enterprise/22/docs/reference-manual/native-image/guides/build-static-executables/ says I need the latest zlib
, but I do indeed have that installed (via my system package manager) so I'm not sure what the problem is.Definitely exists:
zlib /usr/
zlib /usr/include/
zlib /usr/include/zconf.h
zlib /usr/include/zlib.h
zlib /usr/lib/
zlib /usr/lib/libz.a
zlib /usr/lib/libz.so
zlib /usr/lib/libz.so.1
zlib /usr/lib/libz.so.1.2.13
LIBRARY_PATH
looks good...
LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../:/lib/:/usr/lib/
--static build statically linked executable (requires static libc and zlib)
but /usr/lib/libz.a
is static 
You want libz to be static. I'm not sure if graalvm picks up LIBRARY_PATH. You can try explicitly putting libz on the path with an arg like:
--native-compiler-options='/usr/lib/libz.a'
another try would be:
--native-compiler-options='-L' --native-compiler-options='/usr/lib/'
The LIBRARY_PATH
I outputted above was from Graal's own output
Did you try those compiler args?
Yes, they unfortunately didn't work
You can also see how babashka sets up for musl, https://github.com/babashka/babashka/blob/236768cada33d6c570b36e199d3cbb26761574b2/script/setup-musl#L6
Cute
# Install libz.a in the correct place so ldd can find it
install -Dm644 "/usr/local/lib/libz.a" "/usr/lib/$arch-linux-musl/libz.a"
The binary is actually smaller than before :thinking_face:
In my case, it required symlinking a new /usr/lib/musl/lib/libz.a
to the original /usr/lib/libz.a
Got it!
12mb statically linked binary of a Clojure program
Having some issues with bigger programs. Has anyone ever seen:
Exception in thread "main" java.lang.IllegalArgumentException: No matching ctor found for class org.eclipse.jetty.server.Server
when trying to run a statically linked binary that uses ring
?Are you setting (set! *warn-on-reflection* true)
and making sure you're not making any reflective calls? What library are you using? One tip is to use babashka libraries so you don't have to worry if they're graalvm compatible.
Any java interop from clojure in graalvm will require either type hints or some config that tells graalvm to include reflection info for the classes you're interested in.
It was a very simple program; just a basic Ring server with a single handler.
It used ring-jetty-adapter
as well
Assuming it works under regular java17, I would check to see if any clojure code makes interop calls that require reflection
The stack trace was indeed showing a Reflector call
deeper down mind you, not in code I wrote
I see ring/jetty
under https://github.com/clj-easy/graalvm-clojure, but not sure if anyone has tried new versions.
Not all clojure libraries are native-image compatible so if a library makes interop calls that require reflection, you either need to patch them or include extra config.
That example you just posted looks basically exactly the same as what I had
Perhaps something is just different in newer versions? that one was from 3 years ago
Yea, I wouldn't be surprised. Having a bit of reflection used in java interop isn't a big deal for most clojure code, so it's easy to let them sneak in if you don't have an explicit check.