tools-deps

2025-12-18T15:28:33.426419Z

I https://github.com/jacobobryant/biff/issues/249#issuecomment-3670796822 that setting a org.clojure/clojure version in a library doesn't actually do anything, at least when running a project with clj. In this case I have a library that needs clojure 1.12, so it includes that in its deps.edn. But if you have clj 1.11 installed and you try to run an application that depends on that library, you end up with 1.11 and thus get an exception. You have to put the org.clojure/clojure version in your project's deps.edn, not in the library's deps.edn. That's not a big deal in this case, but I'm still curious if that's an intentional behavior and what the rationale is if so? From some searching all I've found is https://ask.clojure.org/index.php/14112/way-specify-clojure-version-across-all-deps-files-monorepo (and the linked https://clojurians.slack.com/archives/C03S1KBA2/p1725756729831549?thread_ts=1725754474.109679&cid=C03S1KBA2) which was closed as a duplicate, however that question is specifically asking about setting a org.clojure/clojure version, and the question it was marked as a duplicate of doesn't cover that.

seancorfield 2025-12-18T15:33:15.143189Z

The general practice with libraries tends to be that you specify the oldest version that your library works with in its deps.edn and you note any minimum Clojure version in your README. And with applications, you generally specify the version of Clojure you want to use. Relying on the CLI install's default Clojure version is not recommended.

2025-12-18T15:35:47.890969Z

that's what I'm trying to do, specify the oldest version it works with in the deps.edn. but it doesn't work.

2025-12-18T15:36:00.345569Z

(in the library's deps.edn)

seancorfield 2025-12-18T15:36:05.984029Z

Right, but it's essentially "documentation".

Alex Miller (Clojure team) 2025-12-18T15:36:19.501859Z

In Maven, lein, and tools.deps the versions of top level deps specified in an application are used regardless of transitive versions specified via deps. This allows an app to have the final say, and to override a deps choices

Alex Miller (Clojure team) 2025-12-18T15:37:28.734569Z

The important thing to know is that libs never control the version of their deps used at runtime

2025-12-18T15:42:51.244359Z

right, I'm just curious why the handling of the org.clojure/clojure dep seems to be different from every other dep? Usually, if you don't set a version in your top-level deps.edn for some dependency, then the highest version dependended on transitively will be used. But for org.clojure/clojure, transitive versions are ignored. If it's recommended that projects should always set an explicit org.clojure/clojure version, that seems reasonable, in which case I suppose this behavior doesn't really matter. But I'm still curious if it's intentional, and why if so. Maybe it's just an implementation quirk from clj?

seancorfield 2025-12-18T15:45:16.612169Z

There are three sets of deps: root, user, and project. The root version of Clojure is whatever the CLI default is. So it acts as a top-level dep. That's my understanding of it.

Alex Miller (Clojure team) 2025-12-18T15:46:03.949629Z

Correct

Alex Miller (Clojure team) 2025-12-18T15:46:18.481289Z

It's special in that it's always a top level dep via the root deps

seancorfield 2025-12-18T15:47:14.422479Z

The root deps.edn is essentially:

{
  :paths ["src"]

  :deps {
    org.clojure/clojure {:mvn/version "1.12.4"}
  }

  :aliases {
    :deps {:replace-paths []
           :replace-deps {org.clojure/tools.deps.cli {:mvn/version "0.14.121"}}
           :ns-default clojure.tools.deps.cli.api
           :ns-aliases {help }}
    :test {:extra-paths ["test"]}
  }

  :mvn/repos {
    "central" {:url ""}
    "clojars" {:url ""}
  }
}
(for CLI 1.12.4.1582)

Alex Miller (Clojure team) 2025-12-18T15:47:25.695889Z

This is intentional because clj is a Clojure program runner and it always invokes some Clojure program so it needs Clojure on the classpath

seancorfield 2025-12-18T15:48:18.103679Z

(but it's baked into the tools uberjar as a resource so the installed deps.edn is not used, even tho' it is still shipped)

2025-12-18T16:02:59.852499Z

Ok, that makes sense. In terms of implementation/why it's happening, at least. I'm still not sure about should-this-be-happening... > This is intentional because clj is a Clojure program runner and it always invokes some Clojure program so it needs Clojure on the classpath Theoretically this could be implemented in some way where the org.clojure/clojure dep from clj wasn't treated as a top-level dep, right? In which case, if the user's project doesn't specify a clojure version, then the latest version from either clj or any transitive deps would be used. In this case (biff) since I control the new project template, it's easy for me to stick a org.clojure/clojure dep in there. But if this were a "regular" library and a user hadn't set a clojure version in their project's deps.edn, it seems like it would be a better user experience for clj to use a higher-than-default clojure version (i.e. the version specified transitively) rather than the user getting an exception when the library code doesn't compile?

seancorfield 2025-12-18T16:24:11.467949Z

Perhaps the "solution" here is for the CLI to be more active in encouraging users to upgrade? The first 1.12 CLI came out well over a year ago: 1.12.0.1479 (Sep 5, 2024).

2025-12-18T16:25:26.013639Z

and/or maybe have it print a warning if you're using a project-level deps.edn file that doesn't specify a clojure version?

Alex Miller (Clojure team) 2025-12-18T16:27:52.792859Z

I expect that to be a common case (including for non-project uses cases), so not want to warn there

👍 1
seancorfield 2025-12-18T16:28:06.157149Z

Given the root <- user <- project deps.edn merging, I'm not sure how the CLI would be avoid treating the root deps as "top-level"... I don't think the warning would be a good UX for beginners: https://clojure.org/guides/deps_and_cli shows that you only need the "additional" libraries. Being able to run a REPL with nothing, but then having to specify Clojure in deps.edn as soon as you create it seems... confusing and burdensome?

seancorfield 2025-12-18T16:30:03.759939Z

Could the CLI check for the latest CLI version and if it differs in the main Clojure version, suggest that the user upgrade? (obvs this can only be done once the user has already upgraded to a version that includes this check)

➕ 1
2025-12-18T16:32:38.680739Z

> Given the root <- user <- project deps.edn merging, I'm not sure how the CLI would be avoid treating the root deps as "top-level"... seems like an easy hack would be to have the root deps.edn depend on some wrapper/shell library which then in turn depends on org.clojure/clojure ?

Alex Miller (Clojure team) 2025-12-18T17:33:26.127419Z

we have an open enhancement about adding upgrade check + warn. some people are opposed to this as they don't want the CLI doing extra network traffic (particularly relevant in containers and CI etc). having some way to ask for the check seems like an obvious add, but I'm on the fence about automatic checking

Alex Miller (Clojure team) 2025-12-18T17:36:13.586469Z

> seems like an easy hack would be to have the root deps.edn depend on some wrapper/shell library which then in turn depends on org.clojure/clojure ? this is one option I've been considering for tools, which have the occasional problem where a tool wants a newer version (like an upcoming alpha) than what is available. right now, it's not possible to do get that in a tool due to how the classpath is formed.

👍 1