EwenG / badigeon

A Clojure build library based on tools.deps.
144 stars 19 forks source link

uberjar with AOT? #3

Closed kanwei closed 5 years ago

kanwei commented 5 years ago

Cool library, thanks!

I'm trying to use this to eventually have a blah-0.0.1-SNAPSHOT-uber.jar, with just one file that I can run java -jar blah-0.0.1-SNAPSHOT-uber.jar on. Using bundle gets me to a spot where all the things seem to be there, but the final uberjar isn't built yet. Can you provide some guidance as to how to finish this?

Thanks!

EwenG commented 5 years ago

Hi, I'm glad you find the library useful.

I decided against uberjar because I don't see a use case for them which is not already covered by a "bundle" directory. Also the library needs to decide what to do with conflicting files: what if several of your dependencies include a LICENSE.txt file ? Should none of them be included ? Should we select only one of them, or should they be concatenated ? With a bundle directory it is easy for the user of the library to do exactly what he wants by moving files around. I will eventually add to Badigeon a helper namespace to manipulate the file system.

That said, a jar is just a zip so once everything you need is in your "bundle" directory, the only thing left to do is to zip the directory ! For example, the "war" namespace does exactly that: https://github.com/EwenG/badigeon/blob/master/src/badigeon/war.clj#L154

To make your jar executable you also need to include a MANIFEST.MF file with a "main" entry. the "make-manifest" function in the '"jar" namespace can help you for that: https://github.com/EwenG/badigeon/blob/master/src/badigeon/jar.clj#L43

I hope this helps.

EwenG commented 5 years ago

The clojure jar already contains the AOT compiled clojure files. You can try using a dependency on the "slim" version of clojure: {:mvn/version "1.9.0" :classifier "slim"}

EwenG commented 5 years ago

You need to both depend on the "slim" version of clojure and to explicitly specify the clojure.core and clojure.main namespaces: (compile/compile '[doublethedonation.core clojure.core clojure.main]).

Unfortunately this is the way clojure.core/compile works :(

I will have to find a way to make it easier to AOT compile the clojure sources. Maybe by giving the option to copy the clojure AOT classes from the clojure jar.

kanwei commented 5 years ago

Ah okay, that makes sense. It did seem like the namespaces that were already loaded, didn't get AOT'ed, so I guess that's why you spin up a new Clojure instance to compile things.

I also figured out a new way to deploy our app, without needing an uberjar, which is to "release", then "compile" into the release directory and just running "java -cp release-dir". One suggestion would be to allow the "compile" endpoint take a "(make-out-path)" result instead of just a string, for consistency. Thanks again!

EwenG commented 5 years ago

Yes, I wrote down the reasons for compiling using a fresh classloader here https://github.com/EwenG/badigeon/blob/master/src/badigeon/compile.clj#L92

Indeed, "compile" does not work with a Path, I will fix that ! Thanks

EwenG commented 5 years ago

Version 0.0.5 is released.

badigeon.compile/compile now accepts java.nio.file.Path instances. The fact that dependencies that are already AOT compiled do not get AOT compiled again is now documented. I did not find a satisfying way to have the clojure core dependencies to be AOT compiled yet. I will keep thinking about that.