How to use local dependencies in Clojure?
Asked Answered
N

3

8

I'm developing a library and an application which uses this library.

I don't have any remote repository for this library, it's only stored on GitHub as a regular project.

In my application I want to use this library as a dependency, what I'm thinking about is to have a structure like that:

.
├── README.md
├── project.clj
├── repo
├── src
├── target
├── libraries
│   └── my-library
└── test

in which my-library is git submodule with my library. How to let my application know about this dependency?

What is 2016 solution for doing that?

Nicky answered 12/1, 2017 at 16:32 Comment(4)
This looks like a duplicate of https://mcmap.net/q/181181/-leiningen-how-to-add-dependencies-for-local-jars. Please clarify if it isn't.Omsk
Possible duplicate of leiningen - how to add dependencies for local jars?Hulsey
It's not a duplicate of that question, because this question is about source code dependencies and that one is specifically about a jar file. This may still be a duplicate, it's just not a duplicate of that oneRushing
Is there any particular reason my-library is included as a git submodule? In particular, is it's relationship to the project such that it is not just another dependency?Stirk
L
12

There is no need to include the lib as a git submodule. You can "release" the my-library project locally.

  1. Just go to my-library project folder and run lein pom; lein jar; lein install. The crucial part here is lein install which installs the jar and pom to the local repository; typically ~/.m2.

  2. Go to your project that uses this library and simply declare it as dependency in your project.clj like :dependencies [[my-library "version"]] and it should work.

EDIT: Simlarly, if you are using Boot, you can run boot pom; boot jar; boot install

Ludly answered 12/1, 2017 at 17:7 Comment(0)
B
5

An even simpler solution is to use lein checkouts as documented here: https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

Create a dir checkouts at the top level of your project (parallel to the src dir). Within checkouts, just create a symbolic link to the directory of the project with the library code. For example, consider a project clj and a library tupelo

drwxrwxr-x 10 alan alan 4096 Jan  5 12:09 clj/
drwxrwxr-x 11 alan alan 4096 Jan  9 20:01 tupelo/

The project clj would look like so:

> d clj clj/* clj/checkouts/*

drwxrwxr-x 10 alan alan  4096 Jan 12 10:36 clj/
drwxrwxr-x  2 alan alan  4096 Oct 14 09:23 clj/checkouts/
lrwxrwxrwx  1 alan alan    17 Oct 30 16:44 clj/checkouts/tupelo -> /home/alan/tupelo/
drwxrwxr-x  2 alan alan  4096 Aug 31 10:05 clj/doc/
-rw-rw-r--  1 alan alan 11219 Aug 31 10:05 clj/LICENSE
-rw-rw-r--  1 alan alan   794 Jan  5 12:09 clj/project.clj
-rw-rw-r--  1 alan alan   457 Aug 31 10:05 clj/README.md
drwxrwxr-x  2 alan alan  4096 Jan  3 09:01 clj/resources/
drwxrwxr-x  3 alan alan  4096 Aug 31 10:05 clj/src/
drwxrwxr-x  8 alan alan  4096 Nov 14 16:26 clj/target/
drwxrwxr-x  3 alan alan  4096 Sep 29 22:31 clj/test/

Now, when building the clj project, it will (always) use source code from ~/tupelo instead of clojars, maven, etc. This means you don't have to make & (re-)install a jar from the lib tupelo everytime you make a change that you want to use in clj.

Bastia answered 12/1, 2017 at 18:39 Comment(2)
The situation is a little worse than your last paragraph implies. It will always use your local code in addition to the code from maven. If you use one version of a library in your local checkouts dir, and a transient dependency loads the same library, then the one from maven is loaded first, then yours is loaded on top of it. so don't use libraries with side-effecting functions at the top level if you ever use checkouts.Rushing
Is this still the case and how to mitigate?Thorncombe
L
2

It is not typical to use git submodules or a local file-based approach to manage libraries in Clojure. Clojure leverages much of the standard Java ecosystem approach to library management. Typically this involves building and deploying libraries to a public Maven repository like Clojars (or Maven Central). If you are only using this within your own organization, there are other options as well for organization-level Maven repositories.

You can then use that library in your own project by declaring it as a dependency in your build tool of choice. In Clojure, the most common tool is Leiningen and you would declare the use of that library as a dependency.

Other alternatives are Maven (very similar to Leiningen, but in XML format) or Boot, which takes a bit different approach.

Leech answered 12/1, 2017 at 17:2 Comment(2)
Is that seriously such a big overhead? Cannot I just include my own library? Do I have to spin off the entire repository for my libraries?Nicky
you don't have to, and I have worked with teams that didn't for a long time. Eventually they all did, because in the long term "doing it right" saves on net-lifetime-frustration-exposure (and effort)Rushing

© 2022 - 2024 — McMap. All rights reserved.