Leiningen: How to include specific dependencies in jar? - clojure

I am attempting to create a jar which contains just a part of the dependencies. I read about uberjar but that contains all dependencies but I would like to point out the exact dependencies I would like to include in the final jar

Related

Cmake issue. Copying dll post build

I'm struggling again with cmake.
What I'm trying to achieve is this:
I have a project, say ProjectA, which contains a submodule with a CMakeLists.txt, say ProjectB.
ProjectA adds ProjectB as subdirectory.
ProjectB outputs a shared library (.dll).
ProjectA has a post build script that copies the dll into its output directory in order to use it.
The problem is that when i change a few things inside ProjectB, this one gets built, but since no modifications are made in ProjectA, it wont build nor copy the dll.
The solution would be to move the post build script inside ProjectB, but if i do that my submodule will be incompatible in other scenarios and tied to ProjectA implementation (what I mean is that the Cmakelists file of projectB should copy the dll in a folder outside it's directory, which is something I want to avoid).
I can't really find a way to avoid manually rebuilding the whole project every time.
To make the situation more clear, the project hierarchy is something like
ProjectA/
CMakeLists.txt
src/
vendor/
ProjectB/
CMakeLists.txt
src/
The First CMakeLists.txt adds Project B as subdirectory.
This cmakelists file also apply a post build script to the target in project A that copies content of ProjectB/bin (dll).
I managed to solve this by myself.
For those who has the same issue and want to find a good solution, just do not use a post build script.
Instead you can add a second parameter to add_subdirectory specifying the build folder of the subproject.

Can Leiningen recursively download the dependencies of its checkout dependencies?

Checkout dependencies can be used to add another work-in-progress project to your Leiningen project during development (for example: you're developing an app and underlying library in parallel).
However, when a checkout dependency itself has a "traditional" dependency (from Clojars), running lein run in the parent project will throw a java.io.FileNotFoundException since it apparently does not retrieve the "traditional" dependencies of its checkout dependencies.
Is there a way to let a Leiningen project recursively download the dependencies of its checkout dependencies?
My opinion of the "proper" way to do this is to have your project depend on the library in your checkouts directory as a traditional dependency in addition to having it in your checkouts directory.
Then every time you change dependencies, run lein install in your library project. This will cause lein to generate the appropriate jar file and install it into your local maven repo. It does not matter if this library project is finished, because you are not actually running it in this state, just using it to fetch dependencies.
Then when it does work you don't have to do anything to "switch to production" other than remove your checkouts directory. The dependency is already in place in the dependent project.
There is a side effect of using checkouts to work on libraries in that the code is loaded twice. Once from the "depended on" version, and then again from the "checkouts version". This is very occationally a problem for me when I'm using protocols and have to remember to re-load the protocol definition.

How can I add a local library into my Leinigen project?

I'd like to add a local library of utilities that I wrote to my project in Leinigen without having to make jars of the library, or without copying the code.
Is that possible?
You can use the checkouts feature of leiningen to add a symbolic link to the project directory containing the library.
cd project-dir # where the project.clj file is
mkdir checkouts
ln -s ~/library/project/dir/ checkouts/library-name
Then add a dependency to the project.clj file
EDIT: If your included code is not it's own project then perhaps including the source directly with git submodules is an option, though some would recommend making it a project that can have a version. It's also worth considering running lein install to build jars and put them in your local maven repo since it only takes two words.
ps: i'm assuming your library is a clojure project.

Determining Clojure Jar Path

The point of this question is to clear up confusion about Clojure project.clj dependencies and how to specify a local dependency.
I have a bunch of Clojure lein projects in a tree
./projects/clojure/bene-csv # A csv parsing library
./projects/clojure/bene-cmp # A main program that depends on bene-csv
I'm editing bene-cmp's project.clj file. I want to make a dependency to
./projects/clojure/bene-csv/bene-csv-1.0.0-SN.jar .
Do I use simple directory notation to specify the path or something else
Thank you.
Edit:
I can include bene-csv in my project by entering lein install in the bene-csv project directory, and using these project.clj entries in bene-cmp's project directory's project.clj file:
(defproject bene-cmp "1.0.0-SN"
:description "This is the main benetrak/GIC comparison program."
:dependencies [[org.clojure/clojure "1.3.0"]
[clojure-csv/clojure-csv "1.3.2"]
[bene-csv "1.0.0-SN"]])
However, I am still trying to figure out what the path is, and would appreciate any pointers or help along those lines. Thank You.
Leinigen uses maven dependency management under the covers, so all dependencies get installed in
${HOME}/.m2/repository/${groupId-as-path}/${artifactId}/$[version}/${artifactId}-${version}.jar
where for [org.clojure/clojure "1.3.0"] groupId is org.clojure, artifactId is clojure and version is 1.3.0. groupIds are converted to paths, so a groupId of org.clojure has a path of org/clojure.
In a maven dependency, specified in pom.xml, this would look like:
<project>
...
<dependencies>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>clojure</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
...
</project>
Note - If no groupId is specified then leiningen uses same value for both the groupId and artifactId.
The benefit of using maven dependency management is that it handles transitive dependencies for you, ie. if you specify a dependency on something, you get all the things it depends on and all the thing that those things depend on etc etc.
So to depend on a local project, the correct thing is to install the local project in your local repository.
To save you changing your versions endlessly while in a development phase, maven supports SNAPSHOT dependencies, whereby some extra information is appended to the version (the datetime basically) and maven knows, that for say 1.3.1-SNAPSHOT it should look for the latest version of that snapshot. This is triggered by the naming convention of {version}-SNAPSHOT.
You can, in maven, specify system dependencies with a hard coded path but generally that's bad practice - it's usually used for things that are platform dependent, i.e. may have a native library component.
By default maven central repository is searched, and leinigen adds in the clojars repository, which serves as a central repo for clojure jars.
leinigen uses this stuff under the covers and builds a classpath referring to the jars in your local maven repository.
Note that you can generate a pom.xml from a leinigen project with lein pom. You could then drive maven from that. A useful feature is
mvn dependency:tree
which gives an ascii art represenation of all the dependencies.

Using Maven 1.x without extra plugins, how does someone build an executable jar?

Using Maven 1.x with just the bundled/standard plugins, what configuration is necessary to build an executable Jar?
Answers should cover:
including dependencies in target Jar
proper classpath configuration to make dependency Jars accessible
Well the easiest way is to simply set the maven.jar.mainclass property to the main class you'd like to use.
As far as setting up the manifest classpath you can use maven.jar.manifest.classpath.add=true to have maven automatically update the classpath based on the dependencies described in the project.xml.
Disclaimer: It's been a long time since I've used Maven 1 and I did not test any of this out, but I'm pretty sure this will get you started in the right direction. For more information check out the jar plugin docs.