tools-build 2022-07-14

Hello, I've noticed an issue when using the compile-clj function and I'm wondering if it's already known? Namespaces in user.clj (if you mistakenly have it in your classpath) get loaded before compiling starts, seems they get cached in *loaded-libs*, then when compiling the main namespace, if those same namespaces are required, they never get loaded and no .class file is created for them.

I can fix this issue by either remove user.clj from the classpath

;; or by adding this binding to the compile script in write-compile-script!
#'clojure.core/*loaded-libs* `(ref (sorted-set))

there’s a great thread touching on this in #clojure i think

ye looks like a similar issue, here clojure.main seems to cause the user ns to load.

if you load the clojure runtime and a http://user.clj is on the classpath it will be loaded

why not clear the loaded-libs cache in the compile script?

loaded-libs isn't everything

clearing loaded-libs will allow require to load things again, effectively forcing a reload-all, but that doesn't clear out the existing state of those namespaces before hand

all kinds of stuff can bleed over and cause further issues

the most reliable thing is a nice clean state, fresh clojure process with nothing loaded

thanks for the info, I'll be sure to keep user.clj out of my classpath when compiling 😬

yea, seems the compile-clj is trying it's best to do that

I’m trying to understand :parents and :dependents in a basis map. My ultimate goal is to get the transitive closure of jars required by a jar: in this case 'com.google.cloud.sql/postgres-socket-factory.

I’m a bit surprised that the lib itself doesn’t point to things it depends on :

classpath=> (get-in basis [:libs 'com.google.cloud.sql/postgres-socket-factory])
{:mvn/version "1.6.0",
 :deps/manifest :mvn,
 :parents #{[]},
 :paths
 ["/Users/dan/.m2/repository/com/google/cloud/sql/postgres-socket-factory/1.6.0/postgres-socket-factory-1.6.0.jar"]}
But several other libs point back at it, even though there seem to be parent and descendants keys which makes me think the graph should have edges on both sides

for example

com.google.oauth-client/google-oauth-client
 {:mvn/version "1.33.2",
  :deps/manifest :mvn,
  :dependents [com.google.api-client/google-api-client],
  :parents
  #{[com.google.cloud.sql/postgres-socket-factory
     com.google.cloud.sql/jdbc-socket-factory-core
     com.google.api-client/google-api-client]},
  :paths
  ["/Users/dan/.m2/repository/com/google/oauth-client/google-oauth-client/1.33.2/google-oauth-client-1.33.2.jar"]}
Here google-oauth-client has a parent relationship to the postgres-socket-factory but the inverse of that doesn’t seem to be present

and the docstring of create-basis states that > :libs - lib map, per resolve-deps but resolve-deps doesn’t explain this relationship so I’m a bit lost

Alex Miller (Clojure team) 2022-07-14T21:36:41.026549Z

:dependents are things that depend on this lib

Alex Miller (Clojure team) 2022-07-14T21:37:16.938859Z

:parents should be considered implementation details right now

ah ok. So i can traverse bottom up but not top down (at least for the moment)

Alex Miller (Clojure team) 2022-07-14T21:37:45.830299Z

well, it's a graph

Alex Miller (Clojure team) 2022-07-14T21:38:33.598209Z

and it's somewhat tricky in that what is reflected in the final lib set may not correspond to what was in the original dep expansion

Alex Miller (Clojure team) 2022-07-14T21:38:41.384009Z

due to version selection, exclusions, etc

sure. i meant traverse by linear searching for dependents rather than direct access by parent (there’s no index for the direction i’m starting from)

Alex Miller (Clojure team) 2022-07-14T21:39:20.562699Z

you're trying to answer a question whose answer is not necessarily in the data you are looking at

oh that’s surprising to me. I guess this information is not available anywhere then? I can resort to getting (System/getProperty "java.class.path") from a repl started with clj -Sdeps {the-lib}. Is there no other way?

Alex Miller (Clojure team) 2022-07-14T21:43:28.987629Z

you can probably extract something close to what you by doing what you're doing (and that's what old versions of -Stree did - that code is still in tools.deps.alpha). The code in tools.deps.alpha.tree is probably better but really requires taking a trace of the dep expansion so duplicates the work done to calculate the basis

thanks. i’ll look at that. many thanks for answering questions

Alex Miller (Clojure team) 2022-07-14T21:45:12.853049Z

depending on whether you care, you could just call calc-trace then trace->tree to get an actual tree (specifically, the tree you see now with -Stree or -X:deps tree) with a lot of data (probably way more data than you want)

i’m ok with data. Ideally just want jars because i need to find out if i have duplicate classfiles on the classpath. So I just need an authoritative way to enumerate jars, then enumerate their files, and then intersect those

Alex Miller (Clojure team) 2022-07-14T21:46:25.816739Z

what you just said doesn't seem to require what you're asking for?

Alex Miller (Clojure team) 2022-07-14T21:46:49.002879Z

why not just do that directly off the classpath?

Alex Miller (Clojure team) 2022-07-14T21:47:27.200889Z

is that because you don't have the classpath, you're doing it from deps?

because we load other jars at runtime for extension. and adding the postgres-socket-factory to the main app breaks lazily loading the bigquery driver.

Alex Miller (Clojure team) 2022-07-14T21:48:07.671999Z

well rather than using the lib map, you could grab the classpath from the basis

Alex Miller (Clojure team) 2022-07-14T21:48:54.961549Z

specifically :classpath-roots from the basis

good point. It would be a little overinclusive (many more jars than what is brought in by the socket factory) but won’t be underinclusive. Thanks

Alex Miller (Clojure team) 2022-07-14T21:49:38.151499Z

I think if you find the conflict, should be easy to understand why there is one

agree. Thank you very much

Alex Miller (Clojure team) 2022-07-14T21:50:32.543709Z

and btw, I'd love to have this packaged as a tool I could run somehow :) people need this all the time

I just randomly looked for duplicated files and was surprised to see we had so many. Somehow have two copies of batik stuff for images

Alex Miller (Clojure team) 2022-07-14T21:51:11.671759Z

that batik stuff is a mess

Alex Miller (Clojure team) 2022-07-14T21:51:21.937439Z

they have some jars with circular dependencies

Alex Miller (Clojure team) 2022-07-14T21:51:31.482669Z

ask me how I know

Alex Miller (Clojure team) 2022-07-14T21:51:32.949999Z

:)

i’m assuming some very long days at work

Alex Miller (Clojure team) 2022-07-14T21:51:56.774509Z

broke tools.deps a long while back

i can’t imagine the edge cases it takes to get nice new tooling to play with every dark corner of the java ecosystem

Alex Miller (Clojure team) 2022-07-14T21:53:29.072729Z

such dark corners :)

and still headscratching. The jars are completely disjoint. We were pretty sure we had two different copies of com.google.cloud.ServiceOption on the classpath under different classloaders. But doesn’t seem to be the case

Alex Miller (Clojure team) 2022-07-14T22:26:07.953569Z

the same class loaded in different classloaders are two different classes

Alex Miller (Clojure team) 2022-07-14T22:27:03.083169Z

that is, class identity is based on classloader+name

Alex Miller (Clojure team) 2022-07-14T22:27:29.477549Z

I'm not sure I said that is the most understandable way so let me know if that doesn't make sense

I’m very handwavy right now. We seem to have found the offending class but somehow the longer I spend on this the less I feel i know where solid ground is 🙂

Alex Miller (Clojure team) 2022-07-14T22:28:17.216449Z

if classloader A loads class C, and classloader B loads class C, then instances of B are not instances of A

Alex Miller (Clojure team) 2022-07-14T22:28:39.238479Z

(C is the identical class on disk)

Alex Miller (Clojure team) 2022-07-14T22:29:19.586199Z

in general, the way to avoid this is to always have A or B in a parent-child relationship where the parent loads C