Maven dependencies for Clojure libraries on GitHub - clojure

I'm developing some applications in Clojure + Java using Eclipse and Maven with m2eclipse.
This works great when my dependencies are in a Maven repository. However there are some libraries that I would like to use that aren't in any repository - e.g. small open source Clojure libraries hosted on GitHub.
These projects typically have a build.xml or a project.clj but not a pom.xml.
Is there a any way to set up Maven to handle these dependencies automatically? Or do I need to manually download and build all of these?

Unfortunately no, you'll either have to:
find a repository containing those libraries
manually add these to your repository using mvn install (and if you're kind enough, ask for those to be published in the central maven repo)
ask the developers if they would be so kind to propose a mavenized version and publish it in some maven repository

Clojure libraries often provide their artifacts in clojars, you might solve your issues just by adding it as a repository in your pom.xml.
Another option available when integrating leiningen and maven builds is to automatically generate a POM out of a project.clj via lein pom
This would allow to include the libraries in your build as long as you checked them out locally.

Related

How to use a local repository for a Clojure library during initial development?

I have a question about developing a Clojure library which is not answered in the suggested workflow for Library Development and Distribution as described here: http://clojure-doc.org/articles/ecosystem/libraries_authoring.html
I am developing a library and want to test this in a clojure project. In this project I will have to add the library under development as a dependency. Is there an alternative for 'lein deploy clojars' which will deploy my library to a local repository? If so how would I setup :dependencies for this in the test project? Note that I will be using libraries in clojars as well in the project which I use to test the library under development.
So where should I deploy a Clojure library in development to, a local repository perhaps, such that it can be used by projects which alpha test the library. How should the test projects address this. I would like to know how this affects 1) the project.clj file for the library development project and 2) the project.clj file for the project which tests the library in development.
lein install does the job:
$ lein install -h
Install jar and pom to the local repository; typically ~/.m2.
In your library project execute lein install and your library jar and pom files will be installed under the ~/.m2 directory.
After that when you build another project that depends on your library, lein will find its binaries in ~/.m2.
~/.m2 is a default location of the local Maven repository which is one of the locations used by lein during dependency resolution. It also works as a cache for remote repositories where artifacts downloaded from Maven Central or Clojars are stored.
What you are looking for is Leigningen's hard to find unless you know what to look for "checkouts" features.
Documentation: https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

Leiningen 'lein install' without writing pom.xml?

I've been contributing to a project in which there's a fixed pom.xml, but I tend to modify project.clj, temporarily, for various purposes. Most of the time, Leiningen seems to ignore pom.xml, but lein install and lein deploy rewrite pom.xml. Is this necessary to Leiningen's functioning? If not, can I stop it? Haven't found anything about this in the online docs yet.
It's not a big problem, but I'd rather not deal with having to restore the official pom.xml in my project before doing a 'git commit', for example.
EDIT: I discovered a solution for my situation, which is to create a 'checkouts' directory with a link to the other project. This causes the other project to be pulled in, without creating a new jar. However, I'm still curious: Does Leiningen need to create pom.xml e.g. for lein install? Why? I'd like to understand the process.
I'm unsure of whether lein install can be run without generating a pom.xml.
The reason it generates a pom is that leiningen uses maven to grab all the dependencies. In fact, maven is able to get dependencies from clojars and leiningen uses it for the clojure dependencies as well as the java ones. Maven requires a pom.xml to specify repository locations and other configuration necessary to run javac (or any other build commands) in addition to a groupId and artifactId to deploy your library to a (potentially local) repository
Another possible workaround to your issue is to use changelists (specifically, if using tortoiseSVN, I'd use the ignore-on-commit changelist) to ignore your pom.xml in most situations commitwise. I believe this stackoverflow answer may assist you with how to do that in git.

Does lein include a maven executable?

I need to perform a mvn install. From what I know, Leiningen (which I already have) is built on Maven so perhaps I don't need to install Maven separately - or do I?
Leiningen uses pomegranate, a Clojure wrapper for Eclipse Aether, a library for working with artifact repositories. Since there were many more products that needed repository access, Aether's functionality was split off from Maven into a separate project, and Maven was changed to make use of Aether.
Pomegranate has an install functionality
install
"Install the jar-file kwarg using the pom-file kwarg and coordinates kwarg.
:coordinates - [group/name \"version\"]
:jar-file - a file pointing to the jar
:pom-file - a file pointing to the pom
:local-repo - path to the local repository (defaults to ~/.m2/repository)
:transfer-listener - same as provided to resolve-dependencies"
I believe there is a lein install task.

leiningen how to specify dependency for clojure without duplicating jar

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.

For a lein project, why is lib/ in .gitignore?

I'm relatively new to Clojure and Java. Why is the lib folder in a lein project not added to the git repo of a lein project? I would think it that would be convenient to have all the necessary jars there for distributed development.
In a Leiningen project, the project.clj file dictates the project's dependencies, and when you run 'lein deps', all dependencies listed in the project.clj file are downloaded to lib/. Therefore, there's no need to check in the jars because the project.clj in combination with the 'lein deps' command is all that's necessary for another person to reproduce the same lib/ that you have. Checking in all the jars is redundant and a waste of space.
Moreover, as mblinn points out, it's better to pull jars from artifact repositories designed for the purpose of distributing and updating dependencies, rather than constantly changing and committing new jars whenever a dependency gets updated. This is especially true when your project depends on snapshot jars, which are subject to frequent change; if you checked in the jars, you'd have to check in a new jar every time the snapshot gets updated, but if you rely on 'lein deps' to pull jars from artifact repos, then you'll stay up to date with no effort. But even for non-snapshot jars, updating a dependency by changing its version in project.clj and then running 'lein deps' is a lot easier and faster than manually placing the jar in lib/ and checking it in.
I hope the above explanation was accessible. If not, and you don't understand some of the concepts discussed, like artifact repositories or dependencies, let me know and I'll explain.
Git is astonishingly bad at storing binary files. If you check in your jars and then have to perform upgrades down the line, soon your repository will be hundreds of megabytes.
One of the biggest advantage of automatic dependency management is that your libraries are not stored in your VCS, along with all its subtle implications when it comes to versioning.
As leiningen internally uses maven artifact resolution, you need to manually specify which artifact repositories in case the required dependency is not found in the default repository, namely maven central repository, clojure releases and clojars
E.g. in case of rome v1.0 which is not yet deployed on maven central but it's found on java.net project kenai repo you'll have to type in your project.clj something along these lines:
...
:dependencies [[rome/rome "1.0"] ...]
:repositories {"kenai" "http://download.java.net/maven/2/"}
...
Well the whole point of Leiningen or any other dependency management tool is that it manages your dependencies for you. Those dependencies are located in separate artifact repositories that are better suited to dealing with public releases of software artifacts than source control systems are. Leiningen piggybacks off Maven's (a populate java build/dependency management tool) repository system; however, there are Clojure-specific artifact repos as well.
Anyhow, the whole point is that you declare the dependencies that your project has in your project.clj, and check that project.clj file into source control. Other developers check it out and run 'lein deps' to pull those dependencies down, and voila!