simuons / rules_clojure

Clojure rules for Bazel
Apache License 2.0
34 stars 8 forks source link

Support tools.deps #56

Open jasonh-logic2020 opened 3 years ago

jasonh-logic2020 commented 3 years ago

Hello and thanks for making this. I would not be able to use clojure at work without it.

Is there any chance of supporting tools.deps, by which I mean using the clojure cli to report dependencies, classpaths, and names (library and binary) from deps.edn?

simuons commented 3 years ago

Hi @jasonh-logic2020,

thanks for reporting this and sorry for delay.

Could you elaborate more and give some examples how such integration would look like?

You need rules to emit deps.edn? Or you need a rule that consumes deps.edn?

jasonh-logic2020 commented 3 years ago

Hello, and thanks for replying.

Since you asked:

I have a multiproject monorepo which provides two clojurescript front ends and a dozen backend artifatcts. Historically we followed the pattern described here and have moved to the third way of organizing our code described therein.

This means we use no tools other than the clojure CLI to develop, build and test. and use :override-deps to do our version pinning across projects. For example, to start a cljs repl:

clojure -M:defaults:ui:dev-cljs

n.b.: defaults does the :override-deps dependency resolution, ui adds the ui project source paths, and dev-cljs adds development dependencies (i.e. shadow-cljs) and some :main-opts to run shadow-cljs watch app.

To build a backend artifact:

clojure -M:defaults:user-service:build-clj

n.b.: build-clj adds a dependency on depstar and adds :main-opts to build a jar.

My ideal bazel rules would look similar to the tools.deps structures:

deps_run(
  alias_deps = ["defaults", "ui"],
  main_opts = ["-m", "shadow-cljs.devtools.cli", "watch", "ui"]
)

deps_build(
  alias_deps = ["defaults", "user-service"],
  main_opts = ["-X:depstar", "uberjar", "jar", "user-service.jar"]
  )

Following this tools.deps model means that clojure -Stree -M:<alias-1>:<alias-2>:...<alias-n> will return the resolved list of maven dependencies to be turned into rules_jvm_ext/maven_install` rules in WORKSPACE.

. It also means that the same rules can support clojurescript once you have your node dependencies installed via rules_nodejs/node_repositories and rules_nodejs/npm_install in WORKSPACE.

AFAIK, using clojure's dependency resolution is deterministic, so it should work with bazel's cache.

Lastly, to hash-lock external dependencies, it would be great if we could add :bazel/hash keys with appropriate values to deps.edn deps maps like:

  {:extra-deps {thheller/shadow-cljs          {:mvn/version "2.11.22"
                                               :bazel/hash "hash goes here"}

Adding that extra key doesn't break anything but I asked alex miller and he wasn't sure whether the extra key would be passed along internally, but there is a way in tools.deps.alpha to get the project basis (including the map of dependency -> version -> downloaded jar) as a data structure after it's done, so getting the hash and the jar to provide to Bazel. is doable.

https://clojure.github.io/tools.deps.alpha/clojure.tools.deps.alpha-api.html#clojure.tools.deps.alpha/lib-location

I'm happy to answer any questions or help if I can.

simuons commented 3 years ago

@jasonh-logic2020 thanks for clarification. I'll try to take a look as soon as I can. Or if you willing to contribute I'm absolutely open to it.