This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-07-28
Channels
- # asami (1)
- # aws (9)
- # babashka (16)
- # beginners (32)
- # calva (2)
- # clj-kondo (20)
- # cljdoc (6)
- # clojure (35)
- # clojure-dev (25)
- # clojure-europe (11)
- # clojure-india (1)
- # clojure-norway (2)
- # clojure-spec (26)
- # clojure-uk (1)
- # clojurescript (41)
- # conjure (3)
- # css (9)
- # cursive (18)
- # data-oriented-programming (6)
- # data-science (2)
- # emacs (47)
- # events (1)
- # fulcro (15)
- # graalvm (30)
- # gratitude (7)
- # honeysql (27)
- # inf-clojure (4)
- # introduce-yourself (2)
- # lsp (129)
- # malli (7)
- # missionary (21)
- # nbb (17)
- # off-topic (18)
- # re-frame (6)
- # releases (1)
- # shadow-cljs (120)
- # vim (7)
- # xtdb (15)
Hey.
Is there a way to lazily load a namespace from a function?
Is it require
?
@U028ART884X If you're still doing this with graalvm native-image: this won't work. If not, then it's fine :)
I did this: https://github.com/ring-clojure/ring/pull/469/files This prevents the import for my non-SSL case.
That's exactly where I'd use requiring-resolve
. Then that line for clj-kondo wouldn't be needed at all, as well as two statements would become one.
@U028ART884X If this still has to do with your questions in #graalvm, this is not a plausible approach
lazy loading stuff will not work in graalvm and will bloat the native image as well. The solution here is usually to use a delay:
(def logger (delay ..))
and then use @logger
instead of logger
This is the same issue as in graalvm. The thing is that version 1.8.0 of that library works just fine but version 1.8.1 fails because something loads that logger when I import that exact namespace. So it's the import that fails, not my code. Or maybe that means that I'm delusional and I don't understand completely anything 😄 But well I got a response: https://github.com/ring-clojure/ring/issues/468
This removed class is imported: https://github.com/ring-clojure/ring/pull/469/files#diff-0f29f4241b1d903dd3fdd238246ce43555ef48543ea51188e8612e1b4f0d36bfL18 I remove it by moving it into a different namespace and lazy-loading it only when it's needed. And graalvm compilation would still fail on that method that requires that class. So I didn't fix that failure. I could add a flag though :thinking_face: In my case I'm not going to use that class at all. So I'll do the minimum possible fix and ask the maintainer if he wants that I'd also add a flag. But the flag would mean that part of the functionality wouldn't work for SSL that is served directly by the server. So by adding a flag I'd be removing functionality :thinking_face:
If you're going to dynamically require something, do it on the top level, but not in the middle of a function. Like this:
(def foo (when (System/getProperty "foo.bar")
(requiring-resolve 'dude/foo))
This is fine for graalvm.
But not:
(defn foo []
(when ...))
But I only know if I want to require when I call the method and there is no env var :thinking_face:
Should I introduce an env var?
That library has two methods: ssl-connector
and http-connector
of which both are private :thinking_face:
And I don't know if I want to control that behavior via an env var. If only graalvm would set GRAALVM=true
... then I could do it.
What I would personally do is find out why this class is initialized during build time: i.e. find out the root cause. A repro with just one clj file which narrows down the problem
GraalVM does have such a thing, it's `the
"com.oracle.graalvm.isaot"
system propertyIt has static LOG = LoggerFactory.getLogger()
and it's imported in that namespace. What else should I look for?
https://github.com/eclipse/jetty.project/blob/cb127793e5d8b5c5730b964392a9a905ba49191d/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/KeyStoreScanner.java#L39
See if you can repro the problem in a clojure project of 1 file where you just import the class, but don't use it
Ah, I'll try.
Ok. That's very weird. I really thought it's this class... I added all of these dependencies and started a ring handler in the same way as in my app:
[[org.clojure/clojure "1.11.1"]
[ring/ring-core "1.8.1"]
[ring/ring-jetty-adapter "1.9.1"]
[com.fzakaria/slf4j-timbre "0.3.21"]
[org.clojure/tools.logging "1.2.4"]]
I don't know what I'm doing apparently. And I bothered a library author.
But what's strange is that that library fails on something that was introduced in that minor version on my other project. So probably I missed some kind of dependency that does something else.
My main:
(ns simple.main
(:require [ring.adapter.jetty :as jetty])
(:import org.eclipse.jetty.util.ssl.KeyStoreScanner)
(:gen-class))
(defn handler
[request]
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello GraalVM"})
(defn -main []
(println org.eclipse.jetty.util.ssl.KeyStoreScanner)
(println "server started on: ")
(jetty/run-jetty handler {:port 3000}))
It works. That's why I don't know what's wrong. I have my big project and I should copy more libs until it stops working :thinking_face:
This is the thing with graalvm: it's better to make isolated repros and then slowly build things up
I was commenting my namespaces in my large project and when I comment-out the jetty
import then it magically compiles. There are probably some kind of bindings that happen in some kind of specific way. Some kind of static Java goodness.
I think thought I found it.
[com.google.firebase/firebase-admin "8.1.0"]
If you add it as your only dependency then you'll fail your graalvm build.
And they managed to release version 9.0.0
recently which doesn't have this issue on my minimal repro.
So the good news is that it doesn't fail on the minimal repro on version 9.0.0
.
The bad news is that on my fat project it still fails no matter which version it is 🥳
So something... somehow... interacts...
So much magic it's not even funny 😄 I guess I'll have to keep digging. I already dug out several of these bugs.
Maintaining babashka is no joke :thinking_face:
Just be very careful with adding dependencies and test image size and compilation time on every new commit that adds new dependencies/functions
is there a way to remove all taps?
I added a fn as a tap but didn't stash a reference to it so I could remove it later
and then you can call reset!
on it with #{}
to clear them all