graalvm

jyn 2025-09-28T18:21:03.826709Z

I want to embed a git commit hash in my binary. I added (def COMMIT (ps/shell "git describe --always")) to my clojure file, which works fine when running as a script. But when I compile to graal, I get this error:

Fatal error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Detected a started Thread in the image heap. Thread name: clojure-agent-send-off-pool-0. Threads running in the image generator are no longer running at image runtime. If these objects should not be stored in the image heap, you can use
Is there a way to tell Clojure to shutdown any threads that are running after the module is initialized? or the opposite, to tell ps/shell to spawn processes from the main thread instead of trying not to block?

borkdude 2025-09-28T18:22:48.194529Z

including (shutdown-agents) at the end should work

jyn 2025-09-28T18:23:12.418449Z

ohhh at the module level instead of in main-

jyn 2025-09-28T18:23:14.582879Z

yes that makes sense

jyn 2025-09-28T18:23:21.876299Z

ty!

borkdude 2025-09-28T18:23:40.203189Z

hmm no that wouldn't work, then you can't run any futures or agents in -main anymore

jyn 2025-09-28T18:24:37.865559Z

ah yeah i see that 😅

flower join-frontmatter: error: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@383496a0[Not completed, task = clojure.core$binding_conveyor_fn$fn__5844@41f9b699] rejected from java.util.concurrent.ThreadPoolExecutor@2142b70d[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]

jyn 2025-09-28T18:26:19.370989Z

is there some equivalent startup-agents i could call in main?

borkdude 2025-09-28T18:26:24.049679Z

I do something similar in babashka but via an env var. I do this:

BABASHKA_COMMIT_SHA=... native-image -EBABASHKA_COMMIT_SHA
and
(def COMMIT (System/getenv "BABASHKA_COMMIT_SHA"))

borkdude 2025-09-28T18:26:54.789909Z

-EBABASHKA_COMMIT_SHA means that this env var is supposed to be captured at build time

jyn 2025-09-28T18:27:03.652129Z

ah hm, i could probably do this in my build.clj

jyn 2025-09-28T18:27:29.602869Z

let me mess around with dynamic bindings

borkdude 2025-09-28T18:27:52.233239Z

why dynamic bindings?

borkdude 2025-09-28T18:28:43.310299Z

here's a commit in bb you could look at : https://github.com/babashka/babashka/pull/1747/files

jyn 2025-09-28T18:28:45.864569Z

because i want this to work for uberjars, not just for graal executables

jyn 2025-09-28T18:29:01.497529Z

i'm not sure java has any equivalent of setenv but if it did i guess that would work

borkdude 2025-09-28T18:29:13.318419Z

it doesn't

borkdude 2025-09-28T18:29:52.095759Z

for uberjars I wouldn't use env vars, I would just spit the commit sha to a file and include it in the resources

jyn 2025-09-28T18:31:16.293129Z

hm ok

borkdude 2025-09-28T18:32:10.444029Z

Example of something similar but for bb's version: https://github.com/babashka/babashka/blob/9853d8fe3d0aa151e953c3f2fcbf2b853af7cf6d/src/babashka/impl/common.clj#L13

2025-09-28T18:32:21.303909Z

You could also spit out a little clojure namespace with a single def among the sha as part of the build process

jyn 2025-09-28T18:33:07.543929Z

oh i don't like that lol

jyn 2025-09-28T18:33:12.008939Z

i would rather do that resource thing

borkdude 2025-09-28T18:33:17.035429Z

that's also possible, I've done that here ;) https://github.com/babashka/http-client/blob/main/src/babashka/http_client/internal/version.clj

jyn 2025-09-28T18:33:20.847719Z

my build process is complicated enough as is

jyn 2025-09-28T18:43:50.096469Z

> for uberjars I wouldn't use env vars, I would just spit the commit sha to a file and include it in the resources this worked quite well, ty 🙂

jyn 2025-09-28T18:44:24.252769Z

actually this is even better than "run git at startup" because now i'm able to still test the output in snapshot tests

👍 1
igrishaev 2025-09-29T12:37:24.604209Z

My two cents: it will be simpler just to add a resource file called VERSION with a version line. Then, you have a function get-version that slurps that resource.

borkdude 2025-09-29T12:38:40.330309Z

which is basically what she settled on, but note that the version in her case has to be a compile time constant which you can accomplish by doing the expression at the top level

igrishaev 2025-09-29T12:39:17.887089Z

So you have this as a part of your Makefile:

get describe --bla > VERSION
and then in your native image args:
-H:IncludeResources='^VERSION$$'
and in Clojure:
(defn get-version []
 (-> "VERSION" io/resource slurp))

borkdude 2025-09-29T12:39:43.418079Z

that's also possible yes

borkdude 2025-09-29T12:41:45.246239Z

note that it helps to qualify your version file to not get conflicts with other projects that include their version on the classpath

igrishaev 2025-09-29T12:43:14.528439Z

yeah, worth naming it like MY_PROJECT_VERSION . It could be also be MY_PROJECT_META with version, author, etc

borkdude 2025-09-29T12:43:58.820899Z

done that as well: https://github.com/nextjournal/clerk/blob/main/resources/META-INF/nextjournal/clerk/meta.edn it seems I've had about every variation of this in one project or another ;)

😆 1
jyn 2025-09-29T14:34:52.914379Z

> note that it helps to qualify your version file to not get conflicts with other projects that include their version on the classpath i've been putting all my resources in META-INF/resources/flower

jyn 2025-09-29T14:35:05.776899Z

unclear if this is actually the intended directory, but it's nice and unambiguous, so

borkdude 2025-09-29T14:38:29.902249Z

I think that's a good location 👍

🙂 1