Maven (and now Leiningen) provides a capability called "Dependency Management".
The idea is to provide a way to specify a version number for common library
dependencies in a single location, and re-use those version numbers from other
discrete maven/lein projects. This makes it easy to, e.g., update your clj-time
dependency across a large number of projects without having to be mindful
of every common dependency version across all of your libraries.
When using :pedantic? :abort in your projects, to ensure that you are producing
a consistent and predictable build, it can be very cumbersome to play the
"dependency version whack-a-mole" game that arises whenever an upstream library
bumps a version of one of its dependencies. :managed-dependencies can help
alleviate this issue by allowing you to keep the dependency version numbers
centralized.
:managed-dependenciesThe :managed-dependencies section of your project.clj file is just like the
regular :dependencies section, with two exceptions:
:dependencies section,
for any artifact that you've listed in your :managed-dependencies section.Here's an example:
(defproject superfun/happyslide "1.0.0-SNAPSHOT"
:description "A Clojure project with managed dependencies"
:min-lein-version "2.7.0"
:managed-dependencies [[clj-time "0.12.0"]
[me.raynes/fs "1.4.6"]
[ring/ring-codec "1.0.1"]]
:dependencies [[clj-time]
[me.raynes/fs]])
In the example above, the final, resolved project will end up using the specified
versions of clj-time and me.raynes/fs. It will not have an actual dependency
on ring/ring-codec at all, since that is not mentioned in the "real" :dependencies
section.
This feature is not all that useful on its own, because in the example above,
we're specifying the :managed-dependencies and :dependencies sections right
alongside one another, and you could just as easily include the version numbers
directly in the :dependencies section. The feature becomes more powerful
when your build workflow includes some other way of sharing the :managed-dependencies
section across multiple projects.
:exclusions, :classifier, etc.)The managed dependencies support in leiningen does work with modifiers such as
:exclusions and :classifier. There are two legal syntaxes; you can explicitly
specify a nil for the version string, or you can simply omit the version string:
(defproject superfun/happyslide "1.0.0-SNAPSHOT"
:description "A Clojure project with managed dependencies"
:min-lein-version "2.7.0"
:managed-dependencies [[clj-time "0.12.0"]]
:dependencies [[clj-time :exclusions [foo]]])
or
(defproject superfun/happyslide "1.0.0-SNAPSHOT"
:description "A Clojure project with managed dependencies"
:min-lein-version "2.7.0"
:managed-dependencies [[clj-time "0.12.0"]]
:dependencies [[clj-time nil :exclusions [foo]]])
Note that :classifier is actually a part of the maven coordinates for an
artifact, so for :classifier artifacts you will need to specify the :classifier
value in both the :managed-dependencies and the normal :dependencies section:
(defproject superfun/happyslide "1.0.0-SNAPSHOT"
:description "A Clojure project with managed dependencies"
:min-lein-version "2.7.0"
:managed-dependencies [[commons-math "1.2" :classifier "sources"]]
:dependencies [[commons-math :classifier "sources"]])
One way of leveraging :managed-dependencies across multiple projects is to use
the lein-parent plugin. This plugin
will allow you to define a single "parent" project that is inherited by multiple
"child" projects; e.g.:
(defproject superfun/myparent "1.0.0"
:managed-dependencies [[clj-time "0.12.0"]
[me.raynes/fs "1.4.6"]
[ring/ring-codec "1.0.1"]])
(defproject superfun/kid-a "1.0.0-SNAPSHOT"
:parent-project [:coords [superfun/myparent "1.0.0"]
:inherit [:managed-dependencies]]
:dependencies [[clj-time]
[me.raynes/fs]])
(defproject superfun/kid-b "1.0.0-SNAPSHOT"
:parent-project [:coords [superfun/myparent "1.0.0"]
:inherit [:managed-dependencies]]
:dependencies [[clj-time]
[ring/ring-codec]])
In this example, we've consolidated the task of managing common version dependencies in the parent project, and defined two child projects that will inherit those dependency versions from the parent without needing to specify them explicitly.
This makes it easier to ensure that all of your projects are using the same versions of your common dependencies, which can help make sure that your uberjar builds are more predictable and repeatable.
Since the defproject form is a macro, it would be possible to write other plugins
that generated the value for a :managed-dependencies section dynamically. That
could provide other useful ways to take advantage of the :managed-dependencies
functionality without needing to explicitly populate that section in all of your
project.clj files.
It is likely that the functionality provided by the lein-parent plugin may integrated
into the leiningen core in a future release; for now we have added only the :managed-dependencies
functionality because it is necessary in order for the plugin to leverage it. We
will be experimenting with different ideas for implementation / API in plugins and
making sure that we find an API that works well before submitting for inclusion
into core leiningen.
Can you improve this documentation? These fine people already did:
Chris Price & Alan MalloyEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |