tools-build

dorab 2021-09-17T03:30:34.204700Z

I was moving over one of my projects from depstar to the latest build-clj. I ran into the following issue that was not there when I used depstar. Not sure what the error means exactly and what to do about it.

Dorabs-iMac:recj dorab$ clj -T:build uber

Writing pom.xml...
Skipping coordinate: {:local/root /Users/dorab/Projects/gadj, :deps/manifest :deps, :deps/root /Users/dorab/Projects/gadj, :parents #{[]}, :paths [/Users/dorab/Projects/gadj/src /Users/dorab/Projects/gadj/resources]}
Skipping coordinate: {:local/root /Users/dorab/Projects/gsheetj, :deps/manifest :deps, :deps/root /Users/dorab/Projects/gsheetj, :parents #{[]}, :paths [/Users/dorab/Projects/gsheetj/src /Users/dorab/Projects/gsheetj/resources]}
Copying src, resources...
Skipping compilation because :main, :ns-compile, and :sort were omitted...
Building uberjar target/recj-0.2.97.jar...
Execution error (ExceptionInfo) at clojure.tools.build.tasks.uber/explode (uber.clj:172).
Cannot write META-INF/license/LICENSE.tomcat-native.txt from io.grpc/grpc-netty-shaded as parent dir is a file from another lib. One of them must be excluded.

Full report at:
/var/folders/lk/mf8f6ghs0zqcw70nmy739khm0000gn/T/clojure-7423998483693171531.edn
Ideas?

seancorfield 2021-09-17T03:47:35.207800Z

@dorab Yup, this bit me too. depstar writes everything directly into a temporary zip file which is case-sensitive. tools.build writes everything to disk first, then bundles it up into a JAR. You're on a case-insensitive O/S. Most libs have META-INF/LICENSE as a text file. The grpc-netty-shaded lib unfortunately has the path shown above which conflicts on case-insensitive O/S.

seancorfield 2021-09-17T03:49:02.209200Z

You can solve this by explicitly depending on an alternative to that lib. We depended on grpc-okhttp as a top-level dep and that gets picked up as a good implementation for what grpc-netty-shaded provides.

dpsutton 2021-09-17T03:50:00.210200Z

we dropped in depstar because it handled this case. i'm trying the latest tools.build but i suspect we will have to work around this. I was surprised to see depstar archived so quickly

seancorfield 2021-09-17T03:51:27.211500Z

Here's where we ran into this:

com.google.cloud/google-cloud-vision {:mvn/version "1.103.7"
                                        :exclusions [io.grpc/grpc-netty-shaded]}
  io.grpc/grpc-okhttp {:mvn/version "1.39.0"}

seancorfield 2021-09-17T03:53:52.215500Z

@dpsutton depstar 1.0 actually had this exact same problem because it worked the same way as tools.build does. 2.0 only avoided it because a user ran into a problem with a library that contained aux.clj which you can't write to the filesystem on Windows (because AUX is a reserved filename(!) along with NUL, PRN, and a few other things).

dpsutton 2021-09-17T03:54:35.216800Z

ha, didn't know that was the cause. i figured it would have been the license problem

seancorfield 2021-09-17T03:54:56.217300Z

2.0 was also substantially faster by writing to ZipFileSystem and then just moving it to the final location but it's not how other JAR builders work as far as I know? What does Leiningen do here?

dorab 2021-09-17T03:55:30.217600Z

@seancorfield Thanks. I will try that workaround. In my case, the dependency is coming from one of the Google APIs as well (Google Ads or Google Sheets - not sure which at the moment).

seancorfield 2021-09-17T03:56:19.218200Z

FWIW, the okhttp lib is a lot smaller than the netty-shaded version -- saved about 8MB in our JAR I think.

seancorfield 2021-09-17T03:58:56.220100Z

We also ran into a problem with a lib that depended on log4j2 2.13.3 as a pom which doesn't work properly with deps.edn but that problem is hidden by the fact it also depended on all the jar artifacts as well. However, when you try to build an uberjar, tools.build choked on finding something that wasn't either a .jar it could expand or a directory it could expand.

seancorfield 2021-09-17T04:01:10.222500Z

depstar explicitly ignored such files (and would tell you about it if you asked, as I recall), and I just got a complaint about depstar ignoring .tar.gz files which come from Oracle's GraalVM JARs I think and it expects them as top-level deps -- which doesn't work really in a JVM world. I gather it's an Oracle-specific issue.

seancorfield 2021-09-17T04:04:21.224600Z

As for the swift archiving of depstar, I think it's a problem that we have a bunch of different JAR builders for deps.edn instead of everyone pitching in to make one solution "the best" and I really want the official core team's offering to be the solution.

dorab 2021-09-17T04:05:33.226200Z

Thanks for the explanations. Agree with having one solution.

seancorfield 2021-09-17T04:05:50.226600Z

I've been working with Alex on getting tools.build to a point where I can stop maintaining depstar and start using the official core tool at work -- and I'd been using tools.build for my OSS projects for a while, switching away from depstar.

dpsutton 2021-09-17T04:06:11.226800Z

yeah good point.

dpsutton 2021-09-17T04:17:24.228500Z

removed depstar. thanks for it in the meantime sean and ghadi

dorab 2021-09-17T04:19:29.229700Z

@seancorfield Your suggestion about the exclusion and grpc-okhttp worked in the sense that I was able to create the uberjar. When I tried to run the uberjar using java -jar target/recj-0.2.98.jar --help I get no main manifest attribute, in target/recj-0.2.98.jar. I presume that means I need to supply some other parameters to the uber task that sets the main class?

seancorfield 2021-09-17T04:22:13.229900Z

:main

seancorfield 2021-09-17T04:24:46.231Z

@dorab Just FYI, since you were talking about what deps-new produces by way of build.clj:

seanc@Sean-win-11-laptop:~/clojure$ clojure -Tnew app :name foo/bar
Creating project from org.corfield.new/app in bar
seanc@Sean-win-11-laptop:~/clojure$ cat bar/build.clj
(ns build
  (:refer-clojure :exclude [test])
  (:require [org.corfield.build :as bb]))

(def lib 'foo/bar)
(def version "0.1.0-SNAPSHOT")
(def main 'foo.bar)

(defn test "Run the tests." [opts]
  (bb/run-tests opts))

(defn ci "Run the CI pipeline of tests (and build the uberjar)." [opts]
  (-> opts
      (assoc :lib lib :version version :main main)
      (bb/run-tests)
      (bb/clean)
      (bb/uber)))
You can see that it defines main and passes it to uber.

dorab 2021-09-17T04:28:36.232Z

Thanks. Seems like the value of :main could be figured out from the value of :lib (by default, if not specified)?

dorab 2021-09-17T04:36:35.234100Z

Got the project transferred over from using depstar to build-clj. Thanks for your help. Now, on to moving thenext project over to build-clj. 🙂

seancorfield 2021-09-17T04:53:12.237Z

@dorab Well, lib/`version` are used (if provided) by write-pom for the group/artifact (and version), and lib is used by default for the JAR filename, but main is a namespace that isn't necessarily related to the lib at all -- although in the simple case of a new app they are related. Although I'm tempted to remove lib/`version` there for a minimal app project since they're not really needed (an app doesn't need a pom.xml)... but that's a tough call.

dharrigan 2021-09-17T08:02:10.237400Z

Can the build.clj (for example) live in another directory other than the root of the project?

Kirill Chernyshov 2021-09-17T08:10:01.237500Z

yes, for example you can move build.clj to “./foo/bar” directory relative to project’s deps.edn to use it you have to specify the namespace in build.clj as foo.bar.build and set :ns-default in deps.edn

dharrigan 2021-09-17T08:35:02.237700Z

perfecto

dharrigan 2021-09-17T08:35:04.237900Z

thank you

dharrigan 2021-09-17T08:35:17.238100Z

I like to keep my root's clean (as possible) 🙂 Directories ftw! 🙂

👍 1
borkdude 2021-09-17T08:55:07.238400Z

I've also been considering this. You could even make a ".build" directory and put that on the classpath

dharrigan 2021-09-17T08:55:14.238600Z

That's a good idea

dharrigan 2021-09-17T08:55:17.238800Z

unix ftw!

borkdude 2021-09-17T08:55:31.239Z

or just build as a dir

borkdude 2021-09-17T09:01:34.239200Z

I usually have a script or scripts dir (others also have bin but I don't think that name makes sense for non-binary programs, or is it some kind of trash bin?)

borkdude 2021-09-17T09:01:42.239400Z

For command line scripts

borkdude 2021-09-17T09:02:02.239600Z

which is probably a slightly different use case

borkdude 2021-09-17T09:02:17.239800Z

perhaps .clojure is also a nice name for such a clojure build script dir

borkdude 2021-09-17T09:03:13.240Z

<overthinking/>

dharrigan 2021-09-17T09:05:19.240200Z

🙂

lread 2021-09-17T15:10:38.248200Z

I continue my happy migration to tools.build and am finding myself a bit confused by API docs for https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-install. Perhaps this is because I am coming from https://github.com/slipset/deps-deploy#install-locally. The tools.build install API docs say Generate pom file and install pom and jar to local Maven repo but then later :class-dir - required, used to find the pom file, which leaves me asking myself, “wait, does this create the pom.xml or read the pom.xml”? And then, because it takes :version and :lib as required params, I ask myself, “wait, can’t it get these from the jar I created, or maybe… does it create the jar?“.

Alex Miller (Clojure team) 2021-09-17T15:16:43.248700Z

it does not create the pom file, so that doc is wrong

Alex Miller (Clojure team) 2021-09-17T15:17:03.248900Z

it also does not create the jar file

Alex Miller (Clojure team) 2021-09-17T15:19:26.249300Z

updated api doc

lread 2021-09-17T15:24:09.249500Z

Much thanks @alexmiller! Curious, why are :version and :lib required, could they not be gleaned from jar contents or pom? And I guess, why does pom file need to be found if it can be assumed to be inside jar? Maybe because pom.xml is not necessarily included in jar?

Alex Miller (Clojure team) 2021-09-17T15:31:53.254100Z

they do not have to match the jar or the pom

Alex Miller (Clojure team) 2021-09-17T15:32:31.254300Z

the pom needs to be submitted as a separate file, or the repo won't have it as metadata

Alex Miller (Clojure team) 2021-09-17T15:33:19.254500Z

which means that maven won't see its deps

lread 2021-09-17T15:36:39.255100Z

I think that slipset’s deps-deploy local install just grabbed all this from inside the specified jar file (?). Tools.build is more flexible, I guess.

seancorfield 2021-09-17T19:34:55.255400Z

I've always assumed that @slipset’s deps-deploy used the local pom.xml file if present but maybe you're right and it pulls the pom.xml out of the JAR to get that?

slipset 2021-09-17T19:39:49.255900Z

No, I believe (I guess I should know) it only uses the local pom.xml

1
slipset 2021-09-17T19:40:38.256100Z

deps-deploy most certainly does not extract anything from the jar, but I don’t know what aether might do.

seancorfield 2021-09-17T19:58:38.258900Z

Here's what build-clj does with deps-deploy:

(let [target    (default-target target)
        class-dir (default-class-dir class-dir target)
        jar-file  (or jar-file (default-jar-file target lib version))]
    (dd/deploy (merge {:installer :remote :artifact jar-file
                       :pom-file (b/pom-path {:lib lib :class-dir class-dir})}
                      opts)))

seancorfield 2021-09-17T19:59:08.259100Z

So it tells it to use the generated pom.xml in target/classes/META-INF/...

seancorfield 2021-09-17T19:59:47.259300Z

(but that :pom-file option is only available in the "exec" usage, not via -M -m)

lread 2021-09-17T21:26:06.261100Z

Cool, thanks all! deps-deploy doesn’t need lib and version respecified though, I suppose it grabs those from pom.xml?

seancorfield 2021-09-17T21:28:31.261400Z

@lee In this case I'm threading lib and version through everything so the pom-path call returns the right path and the jar-file name/path is correct.

seancorfield 2021-09-17T21:30:43.261600Z

Otherwise, if you're relying on write-pom (from tools.build or indirectly via build-clj), that :pom-file option needs to be target/classes/META-INF/group/artifact/pom.xml (which is what pom-path computes from lib) and if you're building the JAR via tools.build, it's going to be target/<name-from-lib>-<version>.jar where <name-from-lib> is going to be (name lib)

seancorfield 2021-09-17T21:30:57.261800Z

Does that make sense/clarify what's going on there?

lread 2021-09-17T21:31:44.262Z

Yeah, that works for me, thanks. Was originally outright confused before alex updated docs - but am now just curious about differences in strategies between build.tools install and deps-deploy local install.

lread 2021-09-17T21:32:18.262200Z

But… I really don’t need answers to carry on productively.

slipset 2021-09-17T19:34:58.255700Z

@slipset has joined the channel

slipset 2021-09-17T19:50:02.258700Z

In other news, (as I’m reading through some of the backlog here) I’ll make deps-deploy use tools-build for building jars in the very near future. And, as mentioned elsewhere, I’d be more than happy to follow @seancorfield’s suite and archive deps-deploy as soon as tools-build has the same capabilities, ie install to local (which it seems tools-build has) and deploy (which I understand may or may not become a part of tools-build ?)

Alex Miller (Clojure team) 2021-09-17T20:10:50.259700Z

I would still plan to use deps-deploy for that part

slipset 2021-09-18T09:05:07.277100Z

Of which you are already aware, I imagine, but the signing part of deps-deploy is fairly separated from the actual deploy code: https://github.com/slipset/deps-deploy/blob/master/src/deps_deploy/gpg.clj I guess this could be separated out into a separate lib which could then be made tools-build compatible if that would serve any purpose.

slipset 2021-09-18T09:06:54.277400Z

Looking at it now, it should be taught how to sign with a mechanism which doesn’t require input on std-in, in the same way that lein does.

slipset 2021-09-18T09:07:20.277600Z

https://github.com/slipset/deps-deploy/issues/33 is the issue for that.

seancorfield 2021-09-17T20:16:18.259900Z

I'm curious as to why that's not on the roadmap? Is it because of the focus on non-artifact dependencies and wanting to encourage git deps more?

seancorfield 2021-09-17T20:16:41.260100Z

Or is it just too much of a pain to bother with due to the vagaries of Maven?

Alex Miller (Clojure team) 2021-09-17T20:17:23.260300Z

just a finite amount of time

Alex Miller (Clojure team) 2021-09-17T20:18:05.260500Z

there are genuinely interesting questions, particularly when dealing with s3, but I have not had time to really work on it

Alex Miller (Clojure team) 2021-09-17T20:19:38.260700Z

I would love to have a solid path to upload to Maven central (which is a harder path than clojars) but it's tricky because you get into gpg signing and all that junk. the datomic team actually has done a lot of the work for this, but it's all buried in private stuff.

seancorfield 2021-09-17T20:24:12.260900Z

Ah, yeah, Central is a lot more work than just Clojars, and S3 is a whole other kettle of fish. Good points.