Hi all, I am running into an odd situation where some namespaces of local dependencies are not being compiled when building an uberjar. To illustrate: In project B there is a local source-only dependency on A, i.e.
;; deps.edn of Project B
{:paths ["src" "dev" "resources"]
:deps {project/A {:local/root "../project/A"} ...}}
along with a fairly standard minimal build.clj
(def basis (b/create-basis {:project "deps.edn"}))
(def class-dir "target/classes")
(defn uber
[_]
(b/delete {:path class-dir})
(b/copy-dir {:src-dirs ["src" "resources"] :target-dir class-dir})
(b/compile-clj {:basis basis :class-dir class-dir})
(b/uber
{:class-dir class-dir
:uber-file "target/uber.jar"
:basis basis
:main 'main})
Now this runs fine, but when I run the uber jar for project B, it errors out with ClassNotFound for functions that should come from A.
Initially I thought that means tools.build doesn’t support compiling source from dependencies, but I haven’t found any docs indicating that. Even more odd is that upon inspection of the jar content (via jar -tf), I notice that it is exactly the set of project A ns that has been explicitly required by B which are not compiled, whilst the transitively required nses in project A are compiled.
FYI I’m running tools.build :mvn/version "0.10.8"
Any idea on what’s going wrong here? I would love to share more detail but I’m not even sure where to startI get the ClassNotFoundException when running the uberjar built by project B; say for instances in B there’s a namespace like so
(ns b.main
(:require
[a.lib.x]))
and in A there’s
(ns a.lib.x
(:require
[a.lib.y]))
then I’d get a compiled b.main and a.lib.y , but not a.lib.xI do have a user.clj, but that’s under the dev path which shouldn’t be included in my build basis, so I’m not sure if that should affect anything
but what kind of class is not found?
I would double check by at least temporarily getting rid of the user.clj
what you are describing sounds like what would happen if a.lib.x was required, then in the same clojure runtime call like (clojure.core/compile 'a.lib.x) happened
hm looks like indeed it’s user.clj causing the issues, once I removed it (even though I’m sure its directory is not on the cp), I can see the rest of the classes in the jar
rather odd that something not on cp would affect the build, or I might be wrong and it’s sneaking in somehow; anyway thanks a lot for the tip!
the fact that it was being loaded proves it was on the classpath, user.clj is a tricky thing
what do you mean by "ClassNotFound for functions that should come from A"?
when and where do you see a classnotfound error?
do you have a user.clj?
likely you have something that is causing the namespaces to be loaded before compiling loads them, user.clj being the main thing that causes this (the only?)
because of the way clojure.core/compile is written things that it is explicitly called on will get compiled regardless of if the namespace is already loaded or not, but for transitive namespaces, if they are already loaded, they don't get compiled