Welcome! Please see the About page for a little more info on how this works.

+1 vote
in tools.build by

I ran across this issue with depstar but observed that tools.build behaves the same, possibly incorrect, way.

See https://github.com/seancorfield/with-dir-repro

If you wrap (b/create-basis ..) in with-dir from tools.deps.alpha, it calculates the basis from the deps.edn file in the context of the with-dir location.

However, if you use that basis with tools.build functions, they do not behave correctly -- even if they are also wrapped in the same with-dir context.

The dependencies come from the project deps.edn (Clojure 1.9.0 in this example) but the src used is from the root of the repo, not from the project folder.

This is counter-intuitive (and took me a while to track down with depstar -- where I definitely consider it to be a bug).

1 Answer

+1 vote
selected by
Best answer

tools.build sits on top of tools.deps.alpha. If you're using tools.build, you should set its directory context via https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-set-project-root.21.

Why would you use the underlying lib's dir control in this context? What's the actual use case for that?

At work we have a build function that iterates over projects and runs code in the context of `with-dir` that calculates a basis for the project and then does stuff with that basis, such as invoking `depstar`. So the dynamic context seems like it should be idiomatic there.

This is for a monorepo where the project context varies, depending on what you're operating on in the repo.

I see that clojure.tools.build.api/*project-root* is public and dynamic so it could be used with binding -- but looking at the source of create-basis, I'm a bit surprised it seems to respect t.d.a's with-dir context since it uses that internally already. Ah, with-dir depends on the behavior of canonicalize which will prepend the current *the-dir* value if the file is relative but otherwise will keep the file path as-is if it is already absolute! So calling tools.build's create-basis in a with-dir context of "." will use that existing context.

I'll update my repro example with dynamic binding of *project-root* but the reason I went with with-dir in the first place was because depstar is built on t.d.a and it creates the correct basis that way -- even though depstar then fails to resolve relative file paths against that context correctly.

But that also means that if depstar is used in the context of tools.build with *project-root* bound, it won't work the same way as tools.build's built-in functions.

I'll report back with findings/suggestions.
Dynamic binding of *project-root* works "as expected" (although I was initially surprised that class-dir and uber-file "disappeared" into projects/example until I realized what was going on).

I tested some combinations of with-dir and binding *project-root* and they don't behave well when *project-root* is a relative path (except for "." which is why this didn't initially fail for me when trying to use with-dir!).

I'll have to think carefully about what this means for depstar since it calculates basis internally (using t.d.a) and that is affected by with-dir but depstar doesn't resolve paths relative to that in general -- but if it was invoked in the context of tools.build, it should resolve paths relative to *project-root* (instead).