How to install a dependency in a Clojure project - clojure

This is a noob question, so I'm sorry if I offend somebody.
But how do I install seesaw on a *nix computer?
Yes, I've read the README.MD file, but how does the project.clj know where to find the library jars (for seesaw for example)?

Edit project.clj and add the dependency (the vector of project-identifying info and version) to the :dependencies vector in project.clj.
The dependency declaration looks like this: [seesaw "1.4.2"] Which you find by searching for seesaw on http://clojars.org.
Your project file should at minimum look something like:
(defproject my-awesome-gui-application "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.4.0"]
[seesaw "1.4.2"]])
If you are using a newer version of leiningen you can type lein deps :tree to see your dependency tree. In other words you can see what libraries are actually being used, ie. the ones you declared and their transitive dependencies.
$ lein deps :tree
[org.clojure/clojure "1.4.0"]
[seesaw "1.4.2"]
[com.jgoodies/forms "1.2.1"]
[com.miglayout/miglayout "3.7.4"]
[j18n "1.0.1"]
[org.fife.ui/rsyntaxtextarea "2.0.3"]
[org.swinglabs.swingx/swingx-core "1.6.3"]
[org.swinglabs.swingx/swingx-action "1.6.3"]
[org.swinglabs.swingx/swingx-autocomplete "1.6.3"]
[org.swinglabs.swingx/swingx-common "1.6.3"]
[org.swinglabs.swingx/swingx-painters "1.6.3"]
[org.swinglabs.swingx/swingx-plaf "1.6.3"]
If you are using an older version of leiningen, type lein deps and look in ./libs to see what jars got fetched (newer versions of lein are smarter and use the jars in ~/.m2 directly instead of copying them into your project. The directory ~/.m2 is the location of your local Maven repository. Leiningen deals with Maven and downloads all the dependencies you've specified so that you don't have to worry about Maven directly.)
I mentioned Maven and your local maven repository in ~/.m2. With any luck you may never have to think about Maven at all (except perhaps browsing through maven central to look up Java libs to stick in your project.clj), but there are times when you might suspect that a jar was corrupted or something to that effect, and it is good to know that you can just blow away that state by deleting your .m2 repository.

project.clj files specify the project configuration for leiningen.
Leiningen downloads and installs the dependencies specifies in the project.clj file and starts the project / runs the repl process / compiles the project to a java jar / whatever. See the link above. In short, leiningen is the most popular glue between your basic OS and the basic java-based clojure runtime/compiler.
Normally, you should not have to install any clojure libs (or even clojure). Except when you need additional libs to develop/debug the current project (and often you don't), you just install leiningen, and leiningen will install the dependencies for the project you want to run.
To be more specific: leiningen gets its download locations/install instructions by delegating to maven, which is a very interesting project. But possibly not worth looking into too closely if your time is precious.

Related

Confusion surrounding lein :dependencies and :plugins

In a project.clj, when you see things like:
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.7.228"]
[com.cemerick/piggieback "0.2.1"]
[org.clojure/tools.nrepl "0.2.10"]
[org.clojure/core.async "0.2.374"]]
and:
:plugins [[org.bodil/lein-noderepl "0.1.11"]
[lein-cljsbuild "1.1.2"]
[lein-npm "0.6.1"]
[lein-repls "1.9.5"]
[lein-doo "0.1.6"]]
Where are these packages coming from? Is it solely Clojars and Maven? Can Lein be configured to get them from GitHub as well?
When these packages are added to your project, is lein merely downloading them and adding them to your java class path? Or something else happening as well?
Where are these packages coming from?
is answered well by What are the leiningen default repositories?
You can use something like lein-git-deps to download dependencies from GitHub, but I would recommend using Maven repos, as this is what the Leiningen ecosystem is built around.
Is lein merely downloading them and adding them to your java class path? Or is something else happening as well?
This deserves some more discussion. When you start a leiningen REPL (for example), Leiningen will first look in its local ~/.m2 repository for all of the dependencies in :dependencies. If it can't find any of them there, it will make a request to each of the repositories for that project to see if they have a copy of that dependency. If they do, Leiningen will download it, then recursively download that dependencies dependencies and so-on. Once all of the dependencies are downloaded, Leiningen will add them all to your application's classpath and start the application.
One thing to keep in mind with Leiningen is that there are two JVM's and two classpaths, one for your application, and one for Leiningen. When you add dependencies to :dependencies they go into your application's classpath, when they are added to :plugins, they go to Leiningen's classpath.

Is there a standalone Clojure package within Leiningen?

After installing leiningen with this script https://raw.github.com/technomancy/leiningen/preview/bin/lein , I can use the repl by typing lein repl, so I think the clojure has already been installed by leiningen.
Do I need to download the JAR of the clojure again from the offical site?
If there's no need to do this, where's the JAR file of clojure that leiningten depends on?
leiningen downloads dependencies from maven repositories and stores them (by default) in
${HOME}/.m2/repository
leiningen stores it's own jar in
${HOME}/.lein/self-installs
the default maven repositories searched by leiningen are
maven central (which you can browse at http://search.maven.org)
clojars (which you can browse at http://clojars.org)
What I've found with lein is installing it and then depending on a specific version of Clojure causes that version to be fetched, and the .jar file winds up in the maven repository.
(defproject repl-test "0.0.1-SNAPSHOT"
:description "TODO: add summary of your project"
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/clojure-contrib "1.2.0"]
[clojure-csv/clojure-csv "1.3.2"]
[org.clojure/tools.cli "0.1.0"]
[util "1.0.2-SNAPSHOT"]
[clj-http "0.1.3"]]
:aot [repl-test.core]
:main repl-test.core)
I'm not sure how Clojure is packaged with lein, but I do know from watching a lein build that it causes the version of Clojure in :dependencies to be fetched (downloaded).
lein is so good, that I actually un-installed default Clojure, because having lein is less of a pain when Clojure goes into a new revision.
Leiningen is a tool that manages Clojure (and Java) libraries for you --- including Clojure itself (which is just another Java library (a jar)).
You don't need to manually download any jars when using lein.
Leiningen consists of two parts: the lein script and an implementation jar that it keeps in ~/.lein --- but you don't need to worry about that jar; the lein script takes care of getting it for you.
I wrote a Brief Beginner's Guide which you might find useful.

in leiningen eclipse Could not locate clojure/contrib/duck_streams__init.class or clojure/contrib/duck_streams.clj

I have created one lein project,
than updating its project.clj with dev-dependency of eclips
I ran "lein deps"
it downloaded all dependencies
but into my.m2/repository directory there is no clojure directory.
and this causes me
leiningen.eclipse Problem loading: java.io.FileNotFoundException: Could not locate clojure/contrib/duck_streams__init.class or clojure/contrib/duck_streams.clj on classpath: (eclipse.clj:1)
error when i ran "lein help" which abandons me to develop with eclipse because i cant run my "lein eclipse" command.
Any solution for this???
Thanks in advance.
my project.clj is given below
(
defproject for_test "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"]]
:dev-dependencies [[lein-eclipse "1.0.0"]]
)
Thnks 'n Regards,
chirag ghiyad
clojure.contrib is a separate library, and so it's dependency needs to be stated explicitly
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/contrib "1.2.0"]]
From 1.3 upwards, the monolithic clojure.contrib is no more, and libraries have been split off as separate libraries.
These libraries should be found in /m2/org/clojure/clojure and /m2/org/clojure/clojure/contrib. Be aware these aren't put into your classpath automatically, only by running lein eclipse after running lein deps, which edits your eclipse .classpath and .projects file.
By the way, I would suggest using lein plugin install lein-ccw "1.2.0", which is Clojure 1.3 compatible compared to lein-eclipse. Instead of running lein eclipse after lein deps, you should use lein ccw.
I've always installed either lein-eclipse or lein-ccw plugins into leiningen through a commandline, so I don't know how dev-dependencies should work. In Leiningen 2.0, they separated plugin and dev-dependency functionality.
(Note: both of these plugins are only usable in stable Leiningen 1.7.1)
That answer is out-dated, notice that the package name should be /clojure-contrib rather than /contrib, otherwise
lein deps
won't find the packages
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/clojure-contrib "1.2.0"]]

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.

ring/compojure without jetty

I know it's possible to create a war file using lein ring war, but it seems to still include jetty dependencies. Is there a way to exclude the jetty dependencies when I'm building the war (and deploying on tomcat)?
If I can't does this matter at all or is it just extra jars/class files that are packaged up into the war but never actually used?
Leinigen supports :exclusions in a dependency.
(defproject my-project "1.0.0"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]]
:dev-dependencies [[autodoc "0.7.1" :exclusions [org.apache.ant/ant]]])
See here for details.
Often the problem is working out where the dependencies are coming from. In maven you can do this:
mvn dependency:tree
to get a useful ASCII art representation of the dependency tree.
One option would be to generate a pom.xml for your project using
lein pom
Then runing maven over that.