118

I want to use leiningen to build and develop my clojure project. Is there a way to modify project.clj to tell it to pick some jars from local directories?

I have some proprietary jars that cannot be uploaded to public repos.

Also, can leiningen be used to maintain a "lib" directory for clojure projects? If a bunch of my clojure projects share the same jars, I don't want to maintain a separate copy for each of them.

Thanks

signalseeker
  • 3,950
  • 6
  • 28
  • 36
  • 1
    Thanks everyone. As it was pointed out my everyone, this is a thorny issue with no clear answer available as yet. – signalseeker Mar 16 '10 at 18:46

11 Answers11

65

Just use :resource-paths in your project.clj file. I use it, e.g. to connect to Siebel servers. Just created a resources directory in my project directory and copied the jar files in there. But of course you could use a more generic directory:

(defproject test-project "0.1.0-SNAPSHOT"
:description "Blah blah blah"
...
:resource-paths ["resources/Siebel.jar" "resources/SiebelJI_enu.jar"])

Then from the lein repl I can create Siebel Data Bean instances, e.g.

(def sbl (com.siebel.data.SiebelDataBean.))
(.login sbl "siebelServer" "user" "password")
...

If you have a newer Java version you can of course use wildcards in your path specification like this for a more general directory:

:resource-paths ["/tmp/SiebelJars/*"]
Hans-J.
  • 689
  • 5
  • 6
  • Lein 2 doesn't support globbing, but the https://github.com/dchelimsky/lein-expand-resource-paths plugin in available if you need to. – pondermatic Sep 13 '13 at 01:40
  • 2
    This is the best answer I've seen so far. The local mvn install doesn't appear to work for me anymore. – David Williams Sep 30 '14 at 05:12
  • 7
    This doesn't work with uberjar, as uberjar will add the dependency jars in the jar, instead of adding the dependencies class files. – Tobias Domhan Feb 18 '15 at 12:36
51
  1. Create a directory in the project:

    mkdir maven_repository

  2. Add local jars to this repository:

    For example, this command adds the jaad-0.8.3.jar file to the maven repository:

    mvn deploy:deploy-file -Dfile=jaad-0.8.3.jar -DartifactId=jaad -Dversion=0.8.3 -DgroupId=jaad -Dpackaging=jar -Durl=file:maven_repository

  3. Add the following to project.clj

    :repositories {"local" "file:maven_repository"}

  4. Now a regular lein deps should work:

    $ lein deps Downloading: jaad/jaad/0.8.3/jaad-0.8.3.pom from local Transferring 0K from local [WARNING] *** CHECKSUM FAILED - Error retrieving checksum file for jaad/jaad/0.8.3/jaad-0.8.3.pom - IGNORING

The warning can be ignored, since the jar will be checked into the project and not downloaded from the internet.

Original source: Using local JAR's with Leiningen (changed since copying)

Janus Troelsen
  • 17,537
  • 13
  • 121
  • 177
  • Nice steps at this link. This was very helpful to me. – goger May 14 '12 at 13:49
  • 2
    with newer versions you might want to use mvn deploy:deploy-file instead of install:install-file and to specify -Durl=file:repo instead of -DlocalRepositoryPath=repo. In projects.clj you can then use: :repositories {"local" "file:maven_repository"} See: https://gist.github.com/stuartsierra/3062743 (I edited the question, but still needs to be approved) – Tobias Domhan Feb 18 '15 at 12:52
39

You could put your private jars in lib/ and they'd be on the classpath for the purposes of lein swank and the like; this does seem to defeat the point of using a dependency management tool, though if you don't actually want those dependencies managed, you could treat Leiningen as an "open source dependencies management tool" and maybe be careful with lein clean.

As the situation becomes more complex -- there's a larger number of private jars involved, they evolve and you need to take some versioning info on them into account -- Arthur's idea of creating a private Maven repo may be more appropriate.


(The HR signifies Leiningen-specific part cut-off point... Continue below for information on the general build / dependency management tooling story in Clojure land, including some links which I think could come in very handy in your situation.)

Also, as of yet, there is no universal agreement on the question of which is the best build tool for Clojure, and Leiningen, while gaining in mindshare, is also constantly gaining in the areas features and polish -- meaning, in particular, that it's not yet complete. Here's a quote from Stuart Halloway, the author of Pragmatic Bookshelf's "Programming Clojure": "My 2c: Leiningen is an important step, but there is still plenty to do." For the full posting and a very interesting discussion re: build tools and the like in Clojure space, see the Leiningen, Clojure and libraries: what am I missing? thread on the Clojure Google group. Many participants specifically mention the need to have local dependencies not contained in any repositories, local or otherwise, and elaborate on the solutions they've come up with for such scenarios. Perhaps you could see if there's anything over there which can solve your problem now / might solve it in the future, when feature sets mature?

Anyway, it is possible that Leiningen may not in fact have a good story ready yet for some complex scenarios. If you feel this may be true of your case (and I mean after you consider the private repo idea), here's some links to maven-based alternatives taken from the above mentioned thread: polyglot maven, clojure-maven-plugin; this blog posting aims to be useful to people trying to use maven with Clojure. As I recall, Meikel Brandmeyer (also on SO under his online handle of kotarak) uses Gradle (a Groovy build system) with a plugin to accomodate Clojure called Clojuresque; I never tried it myself, as don't know the first thing about Groovy, but he claims to run a very nice building act with it and I believe it's got nothing to do with maven -- something which is a plus in and of itself for some of us. :-)

Michał Marczyk
  • 80,820
  • 11
  • 195
  • 208
  • 2
    Re: "there is no universal agreement on the question of which is the best build tool for Clojure"... As of today, it would seem that Leiningen is the run-away standard now. 2013 survey results: https://lein-survey-2013.herokuapp.com/results – David J. Jul 14 '13 at 23:41
  • 8
    As of Leiningen v2, the lib/ directory functionality has been removed. See: https://github.com/technomancy/leiningen/wiki/Repeatability#free-floating-jars – Jared314 Oct 29 '13 at 14:53
  • As of today, Leiningen is probably still the most popular, but Boot is also popular. – Mars Nov 30 '16 at 17:00
34

I find lein pom; lein jar; lein install works well when developing libraries.

Do this in the library being developed and your application requiring it will use it without any :repositories foo required.


Alternatively, lein do pom, jar, install is slightly more concise.


This allows calling the library like any other :dependencies [[project-name "version"]]

ben rudgers
  • 3,509
  • 2
  • 17
  • 29
Greg B
  • 531
  • 4
  • 10
  • 3
    Compared to the other solutions this is so simple and it works! No need to install maven. Thanks. – dkinzer Jul 28 '13 at 00:16
  • 1
    How do you reference the resulting jar in a lein project file? – interstar Sep 04 '14 at 07:46
  • Like any other `:dependencies [[project-name "version"]]` – roboli Sep 04 '14 at 17:09
  • 1
    This works great on Windows as well. No need to install maven as has already been mentioned. I have tried it with IntelliJ + Cursive on Windows and it work perfectly. Did a "lein pom; lein jar; lein install" on the Windows command line. – endbegin Apr 11 '16 at 13:59
  • This blog post describes how to do it: http://www.spacjer.com/blog/2015/03/23/leiningen-working-with-local-repository/ – Tyler Apr 04 '17 at 20:40
  • 4
    You only need to do `lein install`. It will build the jar and pom for you. – neverfox Oct 25 '17 at 00:19
15

I believe the "correct" approach is to create a private Maven Repository so that you can store the jars in a single location and all your branches etc will pick up the changes. This may be overkill for what your doing. I'm curious if these is an easier way.

Arthur Ulfeldt
  • 87,736
  • 24
  • 197
  • 278
  • 5
    Thanks, I will look into it. Although I have to say maven strikes fear in my heart. If you know any simple step-by-step examples to do that, please point me to it. Why are builds so damn complicated in the java world? – signalseeker Mar 08 '10 at 21:55
9

You may like to use the plugin lein-localrepo: https://github.com/kumarshantanu/lein-localrepo

Shantanu Kumar
  • 1,110
  • 1
  • 11
  • 14
4

A recent development is Phil's s3-wagon-private plugin for Leiningen: https://github.com/technomancy/s3-wagon-private

This should allow you to publish artifacts to a private remote repo.

treat your mods well
  • 2,556
  • 1
  • 23
  • 33
3

None of these solutions worked me. Instead I have installed a local repository, and used maven to install the jar file in the local repo, and added the local repo to my project.clj

In command line:

mvn deploy:deploy-file -DgroupId=local -DartifactId=bar \
    -Dversion=1.0.0 -Dpackaging=jar -Dfile=bar.jar \
    -Durl=file:repo

And I write my project.clj like this:

(defproject foo "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [local/bar "1.0.0"]]
  :repositories {"project" "file:repo"})

Hope it helps.

[REFERENCE: https://gist.github.com/stuartsierra/3062743 ]

Roozbeh Zabihollahi
  • 6,557
  • 41
  • 36
2

Maybe have a look at this previous answer, I provide step by step instructions to setup a repository local to the project (accessed through file://) in which you could install your jars.

Community
  • 1
  • 1
Pascal Thivent
  • 535,937
  • 127
  • 1,027
  • 1,106
0

Try my solution how to build jar file with dependencies http://middlesphere-1.blogspot.ru/2014/06/how-to-make-jar-with-dependencies-using.html

mike
  • 509
  • 4
  • 7
0

Best option is to setup a private JFrog/Nexus artifactory and deploy your snapshots/releases there and then add that artifiactory as repositories in you project.clj

Other simpler ways are

Static HTTP The simplest kind of private repository is a web server pointed at a directory full of static files. You can use a file:/// URL in your :repositories to deploy that way if the directory is local to the machine on which Leiningen is running.

SCP If you already have a server set up with your SSH public keys, the scp transport is a simple way to publish and consume private dependencies. Place the following inside defproject:

:plugins [[org.apache.maven.wagon/wagon-ssh-external "2.6"]]
:repositories [["releases" "scp://somerepo.com/home/repo/"]]

Then place the following outside the defproject:

(cemerick.pomegranate.aether/register-wagon-factory!
 "scp" #(let [c (resolve 'org.apache.maven.wagon.providers.ssh.external.ScpExternalWagon)]
          (clojure.lang.Reflector/invokeConstructor c (into-array []))))

It's also possible to deploy to a repository using the scp transport and consume from it over http if you set up nginx or something similar to serve the repository directory over HTTP.

N.B. SCP deploys to Clojars are no longer supported

Original source is here https://github.com/technomancy/leiningen/blob/stable/doc/DEPLOY.md

Robin
  • 5,551
  • 7
  • 32
  • 33