% Managing and Using Libraries
% John Gabriele
Clojure programs typically rely on external libraries in order to
run. If you're writing such a Clojure program, your users would of
course need to have these libraries available in order to run your
program.
Clojure *libraries* may make use of and rely on *other* libraries. If
you're writing such a Clojure library, other programmers who would
like to use your library would need some way to install it *as well
as* install any other libs that yours depends upon.
The way these issues are handled with Clojure is:
1. A Clojure application is typically distributed as a jar file which
includes *all* of the app's dependencies, including the Clojure
jar itself.
2. A Clojure library is distributed by itself as a jar file. In
practice, libraries are available at and automatically fetched as
needed from Clojars or Maven Central (or some other repository) by
the Leiningen tool (see below), which *also* recursively fetches
any dependencies.
Leiningen
=========
As discussed briefly [in the dev environment
chapter](development-env.html#clojure-projects), the tool most
commonly used for managing your Clojure projects is called
"Leiningen". Lein automates a number of project-related tasks. It can:
* create new projects
* fetch dependencies for your project (storing them in your ~/.m2
dir)
* build and run your project's code
* run your project's tests
* start a Clojure REPL (either specifically for your project or
else not associated with any project in particular)
* package your project as a jar (whether it's a library or an app)
* show you your project's classpath
* generate a maven-style "pom" file for your project
* package and upload your library projects to Clojars
There's also a number of [available
plug-ins](https://github.com/technomancy/leiningen/wiki/Plugins) that
extend lein to support additional commands/tasks.
The Leiningen [readme](https://github.com/technomancy/leiningen) and
[tutorial](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md)
explain the details of installing and using lein. A few comments I'd
add:
* `lein` is a standalone program (a shell script which fetches and
uses the lein jar, which it installs into ~/.lein/self-installs).
You quite often run `lein` from inside a project directory.
* When you create a new project (ex. `lein new my-lib`), lein
starts you off by creating a "project.clj" file in your
newly-created project directory. This is the project-specific
"config file" that lein uses to manage your project.
* When you install lein, it creates ~/.lein and ~/.m2/repository
directories for its own use. The ~/.m2/repository dir is used for
caching jars which lein fetches for use by your projects, and the
lein documentation refers to that dir as "the local repository".
* The lein tutorial mentions Ant and Maven. These are Java-land
tools for building Java projects (recall, Java files also get
compiled to Java bytecode). Lein actually uses the Maven library
under the hood. Managing your Clojure projects may entail
compiling/ahead-of-time-compiling Clojure (and possibly even Java)
code, or making use of Java libraries ... and lein automatically
manages all of this for you.
* The Leiningen github project contains a large [sample project.clj
file](https://github.com/technomancy/leiningen/blob/master/sample.project.clj)
which you may find informative when looking for details on using a
particular `:option` in your project.clj.
* Some quick notes on a few of the lein tasks/commands (see `lein help`
for the list of all of them):
lein install
: is for installing a lib you're developing into your own
~/.m2/repository, such that some *other* project you're developing
— which depends upon this lib — can use it even though it
hasn't yet been made available at Clojars.
lein deps
: causes lein to download your project's dependencies,
though, you should never need to run this command
explicitly (except for [viewing the dependency
tree](#viewing-the-dependency-tree)), as lein takes care of it
for you automatically.
lein search
: If you use this command, it will take a while to run the
first time (since it must download the rather large search
index). I recommend instead using the Clojars/Maven-Central
search forms.
In addition to `lein deps`, you should also never need to
explicitly run the `compile` or `javac` tasks. Lein will take care
of running them automatically, if necessary.
Finding the Libraries You Want
==============================
If you don't see what you need in clojure.core, the [standard
library](libs-available.html#standard-library), or
[contrib](libs-available.html#contrib), have a look at
the [Clojure Toolbox](http://www.clojure-toolbox.com/).
And, of course, don't be afraid to ask for recommendations on IRC or
the [Clojure mailing
list](https://groups.google.com/forum/?fromgroups#!forum/clojure).
Library Identification
======================
If you've found a library you wish to use in your project, unless it's
in the Clojure standard library you'll need to edit your project.clj
file and add it to the `:dependencies` there so that lein knows your
project depends upon it (and will download it for you). The format for
specifying a library dependency looks like this:
[*group-id*/*artifact-id version-string*]
and is sometimes referred to as the "coordinates" of the library.
The group-id indicates who's associated with that particular library.
The artifact-id is the library name. The group-id is optional if it's
the same as the artifact-id (and this is in fact quite common). The
version string follows the common "major.minor.patch" pattern
(ex. "1.0.2"; see [semantic versioning](http://semver.org/)).
Here are some examples of project coordinates:
~~~{.clojure}
[org.clojure/clojure "1.8.0"]
[org.clojure/java.jdbc "0.6.1"]
[sonian/carica "1.0.0"]
[clj-time "0.4.4"]
[environ "0.3.0"]
~~~
> The convention for most libs at Clojars (the canonical ones that
> you'll usually be using) is to have the group-id be the same as the
> artifact-id. And in that case, the group-id is omitted from the
> coordinates.
>
> If you see a project at clojars with a group-id like
> "org.clojars.*username*", it usually indicates that the project is a
> forked version of the canonical one.
A Note on Names
---------------
There are four names associated with a given library:
* **Its artifact-id.** This is at the top of the library's
project.clj file, first argument to "defproject" (sometimes also
preceeded by a group-id then a slash). It's the "name" of the
library.
To use a library, you need its artifact-id (and group-id, if it
differs) in your project.clj :dependencies.
* **Its group-id.** This is optionally at the top of the library's
project.clj file, part of the first argument to "defproject"
(before the artifact-id and separated from it by a slash). If only
an artifact-id is present (no slash), that means the group-id is
the same as the artifact-id. Might be the same as the github
username.
* **Its github project name.** Most Clojure lib repos are hosted at
github, and most of those github projects are named the same as
their artifact-id (though this isn't required). The url for its
github project page should usually be used for the project.clj's
:url.
* **The namespace(s) it provides.** A given library's source code
files will each contain an `ns` macro at the top, the first
argument of which is the namespace that file provides. The
namespace name mirrors the directory structure (for example,
my-proj's my-proj.core namespace is represented by
my-proj/src/my_proj/core.clj).
So, when using a library:
* the group-id/artifact-id's you want to pull in go into your
project.clj's :dependencies.
* the namespaces you make use of in your source code files go into
those source code file's ns :require.
### Some Conventions
**For standard and contrib Clojure libraries:** the namespaces
provided all start with "clojure.". For contrib libs, the artifact-id
and github project name are the same. (For the standard libs, there
are of course no github project names or artifact-ids.)
**For other libraries, which are part of an umbrella project:** the
typical pattern is: group-id == github org == umbrella project name.
The namespace(s) provided *may* be group-id.artifact-id.\*. The github
project url is usually github.com/group-id/artifact-id.
**For other libraries:** the artifact-id, top-level namespace provided,
and github project name are all often the same.
### Additional Observations
* Although a given library's group-id *might* be the same as the
github username the project is under (if it is indeed hosted at
github), the group-id and github username are not necessarily
related. They very often are though, for example:
the library coordinates its github url
------------------------------------ --------------------------------------------
[**sonian**/carica "1.0.0"] https://github.com/**sonian**/carica
[**clojurewerkz**/spyglass "1.0.2"] https://github.com/**clojurewerkz**/spyglass
* Note that Clojars page url paths follow the group-id/artifact-id
pattern (and leaves out the group-id when it's the same as the
artifact-id).
Using Libraries
===============
Using Standard Libraries
------------------------
To use standard libraries in your code you don't need to touch
your project.clj file, since these libs already come with Clojure.
Just edit your core.clj file. For example, you can use the
clojure.string standard lib like this:
~~~{.clojure}
(ns my-proj.core
(:require [clojure.string :as str]))
(defn -main
"docstring goes here"
[& args]
(println (str/reverse "encoded secret!")))
~~~
(Note that we're using "str" here as an alias for clojure.string to
save ourselves some typing.)
Using Contrib Libraries
-----------------------
All the contrib libraries have project pages at github (under
), with artifacts (jars) hosted at [Maven
Central](http://search.maven.org/). To use a contrib lib --- for
example, [java.jdbc](https://github.com/clojure/java.jdbc) --- we
first need to look up its coordinates (which will go into our
project.clj). You can find its coordinates on the contrib lib's
github project page (in the README.md). If the info isn't there,
that's a documentation bug.
> Incidentally, if you'd like to see this contrib lib listed at Maven
> Central, visit there and search for "java.jdbc". This will tell you
> that the group-id is "org.clojure", the artifact-id is "java.jdbc",
> and the latest version is "0.6.1" (or whatever the most recent
> version is).
Add those coordinates to your project.clj's :dependencies list, for
example:
~~~{.clojure}
(defproject my-proj "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/java.jdbc "0.6.1"]]
:main my-proj.core)
~~~
and make your core.clj's ns macro look like:
~~~{.clojure}
(ns my-proj.core
(:require [clojure.java.jdbc :as j]))
~~~
(Note that we're using "j" here as an alias for clojure.java.jdbc
to save ourselves some typing.)
Using Libraries from Clojars
----------------------------
If you've found a library you're interested in at
[Clojars](http://clojars.org/), the Clojars page for the lib should
show you exactly what you need to add to your project.clj's
:dependencies list (it shows info on the most-recently released
version).
> As noted above: for canonical 3rd-party libs at Clojars, it's common
> for the group-id to be the same as the artifact-id, and so there
> would be no group-id in the coordinates string you add to your
> project.clj.
In your core.clj file, you'll often put something like "`(:require
[lib-name.core :as foo])`" into your ns macro (where "`foo`" is some
well-chosen short name), and then later use a function from that
library like so: `(foo/func-name ...)`.
The Clojars page for the lib should also contain a link to the github
(or other home) page for the library, which in turn should contain a
README showing some example usage. If there is no such link, consider
searching for the lib at github and then filing a bug report at the
lib's project page about the issue.
### Manually downloading jars from Clojars
If you want to directly download jar files from Clojars, look
in .
Using Various Java Libraries
----------------------------
Search [Maven Central](http://search.maven.org/) for the library
you're interested in, and adjust your project.clj's :dependencies
according to the *GroupID*, *ArtifactID*, and *Latest Version* info
shown in the search results. In your `ns` macro you'll use whatever
namespaces you need which the library provides.
As for using Java libs which are *not* registered at Maven Central,
see the lein [repeatability
doc's](https://github.com/technomancy/leiningen/wiki/Repeatability)
"Free-Floating Jars" section.
Viewing the Dependency Tree
===========================
For a given project, to see the which libraries depend upon which,
print out the dependency tree like so:
lein deps :tree
Keeping Dependencies up to date
===============================
To check if there are newer versions available of your project's
various dependencies, use the
[lein-ancient](https://github.com/xsc/lein-ancient) lein plug-in.
Instructions for use are in its README.