the https://github.com/sig-gis/triangulum/blob/35b4eccbeb0ef871d1c0326ca3d9a2edae772abf/src/triangulum/server.clj#L166, of the https://github.com/pyregence/pyregence, i want to use to build my uber-jar is in a dependency (in the https://github.com/pyregence/pyregence/blob/3a89800e0a65f3ff60b5c36edb7bb71c59270b59/deps.edn#L25) of the project. Is that somehow going to be a problem? I tried calling java -jar uber-jar and it's telling it can't find the main class i tried to pass it, i can't tell if i'm just bad at pathing or if this arrangement is somehow an issue. At the same time, this arraignment feels like the dep is a framework and my project is having to call into it, rather then compose pieces from libraries and i'm wondering if i shouldn't just ignore the convention it seems to be implying to me. I bet i can though, i'm just doing it wrong lol. This is how i built it (i know im getting too far into the weeds of my highly specific needs...)
#+begin_src sh
clojure -X triangulum.packaging/build-uberjar :app-name pyregence :main-ns "triangulum.server"
#+end_srcThanks @seancorfield. It makes perfect sense to me that the triangulum.server would need to be required in order to do the build. I need to get better at inspecting jars, i should have just peaked inside it to see what was going on!!
I'll look into that top level def that's getting configs, thanks for the heads up.
Also thanks Alex! I missed your comment when i scrolled.
I'm getting the impression that the clojure.tools.build.api/compile-clj :jvm-opts is for the jvm that builds the jar, not the resulting jar... is that right? THe docs say:
> Additional options flow to the forked process doing the compile: ... jvm-opts
What is the "forked process" doing? building the jar? err, what is it forked off of?
Look at the source: https://github.com/clojure/tools.build/blob/master/src/main/clojure/clojure/tools/build/tasks/compile_clj.clj#L82
compile-clj spawns a separate Java process that runs Clojure to compile the files...
correct, there is no way for a jar itself to have jvm-opts
Ah, maybe I misunderstood what @drewverlee was asking there...
it is a thing I have wanted more than once ... but, not a thing
Specifically, on line 102, https://github.com/clojure/tools.build/blob/master/src/main/clojure/clojure/tools/build/tasks/compile_clj.clj#L102 the :java-opts provided to compile-clj are used in the java command process that is spawned to do the compilation. A JAR file can't influence the java command used to run it (except for specifying the main class to use for -main).
ok yep, that makes sense. Thanks again friends 🫶 .
Shouldn’t matter
Did you compile it? Needs to be a class not a clj
If I clone that project and run the command you showed, I get this error:
> clojure -X triangulum.packaging/build-uberjar :app-name pyregence :main-ns "triangulum.server"
Execution error (ExceptionInfo) at triangulum.errors/init-throw (errors.clj:11).
Error: Cannot find config file config.edn.
Full report at:
/tmp/clojure-17145164912284408922.edn
Execution error (ExceptionInfo) at clojure.tools.build.tasks.compile-clj/compile-clj (compile_clj.clj:114).
Clojure compilation failed, working dir preserved: /tmp/compile-clj6611280221737648496
Full report at:
/tmp/clojure-10813327763111763454.edn(Kinda concerning that just compiling the code tries to read an EDN file?!)
Thanks Sean, I'll... Think about that. 🤔
I copied config.default.edn to config.edn, re-ran the command and got a standalone JAR. But looking inside it, I see
7741 Sat Mar 22 21:31:01 PDT 2025 triangulum/server.clj
but no .class files so the build isn't compiling the ns (so you can't use it directly with java -jar)That packaging build uberjar fn compiles the src-dirs:
;; Compile Clojure source code to classes in the jar-content folder
(b/compile-clj {:src-dirs src-dirs
:class-dir jar-content
:basis basis
:bindings bindings
:compile-opts compile-opts
:java-opts java-opts})
which is your project's src folder and I'm guessing you don't have any code that requires triangulum.server so the transitive compile won't reach it.I added this to the :require in :
[triangulum.server]
and re-ran the build and now I see:
1349 Sat Mar 22 21:42:31 PDT 2025 triangulum/server$fn__19256.class
1976 Sat Mar 22 21:42:31 PDT 2025 triangulum/server.class
2846 Sat Mar 22 21:42:31 PDT 2025 triangulum/server$send_to_nrepl_server_BANG_.class
1923 Sat Mar 22 21:42:31 PDT 2025 triangulum/server$fn__19261.class
2798 Sat Mar 22 21:42:31 PDT 2025 triangulum/server$send_to_nrepl_server_BANG_$fn__19277.class
10776 Sat Mar 22 21:42:31 PDT 2025 triangulum/server__init.class
...
And I can run that with java -jar now:
> java -jar target/pyregence-2025.03.17-3a89800e-standalone.jar
Exception in thread "main" clojure.lang.ExceptionInfo: Error: Config file config.edn failed spec check:
"<prod/dev>" - failed: (not (re-matches #"<.*>" %)) in: [:triangulum.server/mode] at: [:server-keys :triangulum.server/mode] spec: :triangulum.config/string
"<prod/dev>" - failed: (not (re-matches #"<.*>" %)) in: [:triangulum.server/mode] at: [:database-keys :triangulum.server/mode] spec: :triangulum.config/string
"<prod/dev>" - failed: (not (re-matches #"<.*>" %)) in: [:triangulum.server/mode] at: [:email-keys :triangulum.server/mode] spec: :triangulum.config/string
"<prod/dev>" - failed: (not (re-matches #"<.*>" %)) in: [:triangulum.server/mode] at: [:triangulum.server/mode] spec: :triangulum.config/string
(because the config.edn file is a copy of the default with no changes so it isn't valid)
but at least it runs the server -main.This is the code that is reading the config.edn during compilation I think:
https://github.com/pyregence/pyregence/blob/3a89800e0a65f3ff60b5c36edb7bb71c59270b59/src/clj/pyregence/match_drop.clj#L29-L33
You should never have top-level def forms that have side-effects. When this is compiled it is going to read the configuration file at that time, not at runtime.