I want to create a new lein project from a template I have created without installing the template in .m2 or on clojars. So I want to set the classpath that lein uses when it works. How is this done?
Related
I have a Clojure project I started a couple of years ago.
It's all using Leiningen. With a project.clj file etc. And my code in src/myproj/blah.clj etc.
I now want to try using Clojure's new CLI tools.
I tried navigating into the root of this project directory and launching clj then typing (require '[myproj.blah :as blah])
But this throws a FileNotFoundException.
Can the CLI tools find code in a lein type file-structure and work with existing lein projects?
If not what's the procedure to adapt a lein project to use CLI tools?
Here's a guide to the new command line tools https://clojure.org/guides/deps_and_cli
You need a deps.edn file that contains your dependencies instead of a project.clj file.
Here's some rationale of what deps does and doesn't do:
http://cdn.cognitect.com/presentations/2017/dependency_heaven.pdf
I am trying to see how I can add a directory and an external jar to the classpath when making a leiningen uberjar.
The reason is that I need to distribute a jar but some dependencies (jdbc driver for example) cannot be compiled into the uberjar due to licencing restrictions.
I would also like to provide certain external resources such as properties for logging and configuration external to the jar.
Normally in java or spring boot I would use the appropriate command line option to change the classpath. However -cp does not find the jar etc
Is there a way to do this or an appropriate plugin?
Thanks in advance
You can add the jar as a resource in the :dev profile. Then it is added to the classpath. The dev profile is for the local development and not packaged into the uberjar.
:profiles {
:uberjar {:aot :all}
:dev {:resource-paths ["no-redist/commercial-jdbc-driver.jar"]}}
At 'production' time with the uberjar you need set the classpath then manually:
java -cp no-redist/commercial-jdbc-driver.jar;your-app-uber-jar.jar main.namespace
Afaik when using the -jar flag, it uses the dependencies in the jar file, whatever is linked and referred to in there. Combining -cp and -jar might not work.
Another way is to refer to the no-distributable jar file in the jar manifest (META-INF/MANIFEST.MF):
Class-Path: no-redist/commercial-jdbc-driver.jar
The the java -jar your-app-uber-jar.jar would look for the jar in the folder no-redist/commercial-jdbc-driver.jar in the local directory. Add this in leinigen like:
:manifest {"Class-Path" "no-redist/commercial-jdbc-driver.jar"}
I defined :resource-paths in profile.clj to include some special jar (vertica jdbc) file. and then I run lein uberjar: trying to pack that jar file into the standalone jar file, but after I run it, and uncompressed it, I can't find that vertica jdbc file.
Leiningen can create jar files, but the only place it picks them up from is your maven repository (under an .m2 directory on your machine). Once your special jar is in maven you need to refer to it as a dependency in your project.clj file.
If your jar file was in clojars this would be quite easy - just put in a dependency - lein will fetch it into your maven repository. On the other hand if it was your own source code you would first need to lein install from the directory of that source code project.
However I'm guessing your file is just a jar file you have, which is not an artifact in clojars. In this case you can install it into your maven repository using this maven command (here assuming my-deps.jar is your file):
mvn install:install-file -Dfile=./my-deps.jar -DgroupId=my-deps -DartifactId=my-deps -Dversion=1.0.0 -Dpackaging=jar
You can then refer to it as a dependency in the uberjar project, and then lein uberjar.
Edit - if you don't want to use raw maven commands then consider using this leiningen library that abstracts them away for you: https://github.com/kumarshantanu/lein-localrepo.
An alternative is to add to project.clj:
:repositories {"local" "file:lib"}
Create a lib directory in your project and add the jar there.
Add the lib reference in the :dependencies tag in project.clj.
This lib directory has the same structure as .m2/repository but is inside your project and local to your project
When the uberjar is created, I also need to run lein deps. How do I make Leiningen automatically run lein deps when lein uberjar is run?
lein deps is run automatically on other lein tasks like run jar cljsbuild...
In fact I never use lein depsexcept in lein do clean, deps.
Note : I am just transitioning to boot myself, but composing tasks is much easier with this build tool.
You can have leiningen run a combination of any lein tasks via the do command. We can then define an alias to run the desired tasks with ease. In your profile.clj include the following:
:aliases {"build-with-deps" ["do" "clean" "deps" "uberjar"]}
Then whenever you call lein build-with-deps it will actually run the following: lein do clean, deps, uberjar.
I recommend reading through the sample project.clj provided by leiningen to better familiarize yourself with the capabilities of aliases.
Everytime I do a lein new I seem to get a copy of the clojure jar in the lib folder of that project. I thought that jars deps were copied to .m2/repository. Why is the clojure jar duplicated for every lein project?
This only happens with Leiningen 1. The reason for this (I think) was to allow tools to inspect the dependencies easily. With Leiningen 2, this is no longer an issue because it uses the pomegranate library (which is a wrapper for Aether) to manage dependencies. It allows for more robust dependency management, and therefore Leiningen can just link to the dependencies from your local Maven repository.
Jars are cached in your .m2 repo. However, to use them in your project, they need to be on your project's classpath, usually in your project/lib directory. Caching in your local Maven repo just saves you a download from the server.