i'm compiling a clojure program to Graal that has an embedded SCI interpreter. when i try to call (hiccup2.core/html), it gives a syntax error:
Exception in thread "main" clojure.lang.ExceptionInfo: Syntax error compiling fn* at (0:0). {:type :sci/error, :line 1, :column 1, :message "Syntax error compiling fn* at (0:0).", :sci.impl/callstack #object[clojure.lang.Volatile 0x71bca854 {:status :ready, :val ({:ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta nil} {:ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta nil} {:ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta {:name eval, :doc "Evaluates the form data structure (not text!) and returns the result.", :arglists ([form]), :sci/built-in true, :ns #object[sci.lang.Namespace 0x1562e300 "clojure.core"]}} {:line 1, :column 1, :ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil} {:line 1, :column 1, :ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta {:ns #object[sci.lang.Namespace 0x32eff675 "hiccup2.core"], :name html, :macro true, :doc "Render Clojure data structures to a compiled representation of HTML. To turn\n the representation into a string, use clojure.core/str. Strings inside the\n macro are automatically HTML-escaped. To insert a string without it being\n escaped, use the [[raw]] function.\n\n A literal option map may be specified as the first argument. It accepts two\n keys that control how the HTML is outputted:\n\n `:mode`\n : One of `:html`, `:xhtml`, `:xml` or `:sgml` (defaults to `:xhtml`).\n Controls how tags are rendered.\n\n `:escape-strings?`\n : True if strings should be escaped (defaults to true).", :arglists ([options & content])}})}], :file nil}
what is going wrong here? i found https://github.com/babashka/sci/issues/370#issuecomment-664241814 which maybe looks related? but i know babashka supports hiccup so i'm not sure why it only breaks for mei did see that babashka has its own version of html, but i'm not sure how it's different or why it's necessary ... https://github.com/babashka/babashka/blob/bd20a5f973fcf1ed33131eb1079927be9de0d1d8/feature-hiccup/babashka/impl/hiccup.clj#L12-L34
have you tried using babashka's config?
might solve the problem. I don't remember the exact issue but it's there for a reason
what config do you mean?
the config you are linking to
oh i see
i suppose that works but i worry about reimplementing parts of public libraries, what if their api changes
The error "Syntax error compiling fn*" isn't coming from SCI, but from Clojure itself
i can post the backtrace if it's helpful?
> i suppose that works but i worry about reimplementing parts of public libraries, what if their api changes tests, tests, tests. you control the version of the dependency for your graal binary
sure, post the stack trace in a gist, not as plain text here
I have to go for a while, brb
oh wait actually at the end of the long backtrace is another exception
Caused by: java.lang.UnsupportedOperationException: Crema
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unimplemented(VMError.java:195)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.ClassLoaderHelper.defineClass(Target_java_lang_ClassLoader.java:330)
at java.base@24.0.2/java.lang.ClassLoader.defineClass(ClassLoader.java:271)
at java.base@24.0.2/java.lang.ClassLoader.defineClass(ClassLoader.java:265)
at clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:46)
at clojure.lang.Compiler$ObjExpr.getCompiledClass(Compiler.java:5503)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4633)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:7628)
... 143 morefull trace here https://gist.github.com/jyn514/2ae5b11e607a41069d7792aaaee2a35b
I bet you are running into clojure.core/eval usage here:
https://github.com/weavejester/hiccup/blob/master/src/hiccup/compiler.clj
scan that file for (eval ..)
and this isn't supported by graalvm native-image
which version are you using of graalvm native-image btw?
native-image 24.0.2 2025-07-15
ok. I'm fairly sure that's the issue and why babashka has its own html macros
gotcha, thank you
i think this is https://github.com/oracle/graal/issues/11327
native-image not being able to eval is a fundamental problem. you can read more about it here: https://github.com/clj-easy/graal-docs?tab=readme-ov-file#runtime-evaluation
or actually it doesnt' really have that much text. but it's the reason why SCI even exists ;)
haha
i wonder if we can convince the hiccup maintainers to have SCI as an optional feature and do platform detection to decide when to use it for eval
i know clojure supports platform detection for JVM/CLJS, idk if it has something similar for graal
the hiccup maintainer actually regrets complicating things so much to have compile time optimizations using eval. just don't go there and accept the workaround
the API won't change that much that you have to worry about it, but do make a few tests to see if your hiccup works
the custom macro calls compiler/render-html which is the dynamic version
neat, thank you
my standard library is going to have a bunch of calls to all these libraries so i'm not too worried about things being obviously broken, but i'll add a couple tests for the dynamic bindings
(i'm hitting all these weird issues before i even hit hello world in my DSL lol)
first test on the JVM before running with native-image, usually saves time
yes, i've been using JVM up until now
just started compiling to Graal last night