2010-06-16 01:58:14 +00:00
|
|
|
# Tutorial
|
|
|
|
|
|
|
|
For those of you new to the JVM who have never touched Ant or Maven in
|
|
|
|
anger: don't panic. Leiningen is designed with you in mind. This
|
2010-06-17 04:10:56 +00:00
|
|
|
tutorial will help you get started and explain Leiningen's take on
|
2011-07-06 03:43:25 +00:00
|
|
|
project automation and JVM-land dependency management.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
## Creating a Project
|
|
|
|
|
|
|
|
We'll assume you've got Leiningen installed as per the
|
2010-12-03 02:16:16 +00:00
|
|
|
[README](https://github.com/technomancy/leiningen/blob/stable/README.md).
|
2010-06-16 01:58:14 +00:00
|
|
|
Generating a new project is easy:
|
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
$ lein new my-stuff
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Generating a project called my-stuff based on the 'default' template.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
$ cd my-stuff
|
2010-06-16 01:58:14 +00:00
|
|
|
$ tree
|
|
|
|
.
|
|
|
|
|-- project.clj
|
2012-01-13 06:48:44 +00:00
|
|
|
|-- README.md
|
2010-06-16 01:58:14 +00:00
|
|
|
|-- src
|
2012-03-06 22:49:39 +00:00
|
|
|
| `-- my_stuff
|
|
|
|
| `-- core.clj
|
2010-06-16 01:58:14 +00:00
|
|
|
`-- test
|
2012-03-06 22:49:39 +00:00
|
|
|
`-- my_stuff
|
|
|
|
`-- core_test.clj
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Here we've got your project's README, a `src/` directory containing the
|
|
|
|
code, a `test/` directory, and a `project.clj` file which describes your
|
|
|
|
project to Leiningen. The `src/my/stuff.clj` file corresponds to
|
|
|
|
the `my.stuff` namespace.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
Note that we use `my-stuff.core` instead of just `my-stuff` since
|
|
|
|
single-segment namespaces are discouraged in Clojure. Also note that
|
|
|
|
namespaces with dashes in the name will have the corresponding file
|
|
|
|
named with underscores instead since the JVM has trouble loading files
|
2011-05-04 02:42:31 +00:00
|
|
|
with dashes in the name.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
## Packaging
|
|
|
|
|
|
|
|
You can package your project up now, even though at this stage it's
|
|
|
|
fairly useless:
|
|
|
|
|
|
|
|
$ lein jar
|
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
Created ~/src/my-stuff/target/my-stuff-0.1.0-SNAPSHOT.jar
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
Libraries for the JVM are packaged up as .jar files, which are
|
2010-06-19 03:56:36 +00:00
|
|
|
basically just .zip files with a little extra JVM-specific metadata.
|
|
|
|
They usually contain .class files (JVM bytecode) and .clj source
|
|
|
|
files, but they can also contain other things like config
|
2011-03-16 01:45:04 +00:00
|
|
|
files. Leiningen downloads jar files of dependencies from remote Maven
|
|
|
|
repositories for you.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
## project.clj
|
|
|
|
|
|
|
|
$ cat project.clj
|
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
```clj
|
2012-01-13 06:48:44 +00:00
|
|
|
(defproject my-stuff "0.1.0-SNAPSHOT"
|
2011-11-11 20:16:52 +00:00
|
|
|
:description "FIXME: write description"
|
2012-03-06 22:49:39 +00:00
|
|
|
:url "http://example.com/FIXME"
|
|
|
|
:license {:name "Eclipse Public License"
|
|
|
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
2012-01-13 06:48:44 +00:00
|
|
|
:dependencies [[org.clojure/clojure "1.3.0"]])
|
2011-11-11 20:16:52 +00:00
|
|
|
```
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Fill in the `:description` with a short sentence so that your project
|
2012-03-06 22:49:39 +00:00
|
|
|
will show up in search results once you publish it, and be sure to fix
|
|
|
|
the `:url` as well. At some point you'll need to flesh out the README
|
|
|
|
too, but for now let's skip ahead to setting `:dependencies`. Note
|
|
|
|
that Clojure is just another dependency here. Unlike most languages,
|
|
|
|
it's easy to swap out any version of Clojure.
|
2010-06-19 03:56:36 +00:00
|
|
|
|
2010-06-16 01:58:14 +00:00
|
|
|
## Dependencies
|
|
|
|
|
2011-06-24 05:49:00 +00:00
|
|
|
By default, Leiningen projects download dependencies from
|
|
|
|
[Clojars](http://clojars.org) and
|
|
|
|
[Maven Central](http://search.maven.org). Clojars is the Clojure
|
|
|
|
community's centralized jar repository, while Maven Central is for the
|
|
|
|
wider JVM community.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
The `lein search` command will search each remote repository:
|
2010-06-29 19:58:23 +00:00
|
|
|
|
2011-06-24 05:49:00 +00:00
|
|
|
$ lein search lancet
|
|
|
|
== Results from clojars - Showing page 1 / 1 total
|
|
|
|
[lancet "1.0.0"] Dependency-based builds, Clojure Style.
|
|
|
|
[lancet "1.0.1"] Dependency-based builds, Clojure Style.
|
2010-06-19 03:56:36 +00:00
|
|
|
|
2011-06-24 05:49:00 +00:00
|
|
|
This shows two versions available with the dependency vector notation
|
2012-01-13 06:48:44 +00:00
|
|
|
for each. You can copy one of these directly into the `:dependencies`
|
2012-03-06 22:49:39 +00:00
|
|
|
vector in `project.clj`.
|
2011-06-24 05:49:00 +00:00
|
|
|
|
|
|
|
The "artifact id" here is "lancet", and "1.0.1" is the version you
|
2011-03-16 01:45:04 +00:00
|
|
|
require. Every library also has a "group id", though for Clojure
|
|
|
|
libraries it is often the same as the artifact-id, in which case you
|
2012-03-06 22:49:39 +00:00
|
|
|
may omit it. For Java libraries often a reversed domain name is used
|
|
|
|
as the group id.
|
2010-06-22 02:21:13 +00:00
|
|
|
|
2010-06-16 01:58:14 +00:00
|
|
|
Sometimes versions will end in "-SNAPSHOT". This means that it is not
|
2010-06-19 03:56:36 +00:00
|
|
|
an official release but a development build. Relying on snapshot
|
|
|
|
dependencies is discouraged but is sometimes necessary if you need bug
|
2010-12-07 18:33:22 +00:00
|
|
|
fixes, etc. that have not made their way into a release yet. However,
|
|
|
|
snapshot versions are not guaranteed to stick around, so it's
|
|
|
|
important that released code never depends upon snapshot versions that
|
|
|
|
you don't control. Adding a snapshot dependency to your project will
|
|
|
|
cause Leiningen to actively go seek out the latest version of the
|
2012-01-13 06:48:44 +00:00
|
|
|
dependency (whereas normal release versions are cached in the local
|
|
|
|
repository) so if you have a lot of snapshots it will slow things
|
|
|
|
down.
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
Speaking of the local repository, all the dependencies you pull in
|
2012-01-13 06:48:44 +00:00
|
|
|
using Leiningen or Maven get cached in `$HOME/.m2/repository` since
|
|
|
|
Leiningen uses the same library as Maven under the covers. You can
|
|
|
|
install the current project in the local repository with this command:
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
$ lein install
|
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
Wrote ~/src/my-stuff/target/pom.xml
|
2012-01-13 06:48:44 +00:00
|
|
|
[INFO] Installing my-stuff-0.1.0-SNAPSHOT.jar to ~/.m2/repository/myproject/myproject/0.1.0-SNAPSHOT/myproject-0.1.0-SNAPSHOT.jar
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2011-05-04 02:42:31 +00:00
|
|
|
Note that some libraries make their group-id and artifact-id
|
|
|
|
correspond with the namespace they provide inside the jar, but this is
|
|
|
|
just a convention. There is no guarantee they will match up at all, so
|
2012-01-13 06:48:44 +00:00
|
|
|
consult the library's documentation before writing your `:require`
|
|
|
|
clauses.
|
2011-05-04 02:42:31 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
You can add third-party repositories by setting the `:repositories` key
|
2011-06-24 05:49:00 +00:00
|
|
|
in project.clj. See the
|
2010-12-03 02:16:16 +00:00
|
|
|
[sample.project.clj](https://github.com/technomancy/leiningen/blob/stable/sample.project.clj).
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
## Profiles
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 18:19:15 +00:00
|
|
|
Sometimes you want to pull in dependencies that are really only
|
|
|
|
necessary while developing; they aren't required for the project to
|
|
|
|
function in production. You can do this by adding a `:dependencies`
|
2012-03-06 22:49:39 +00:00
|
|
|
entry to the `:dev` profile. These will be available unless you
|
|
|
|
specify different profiles using the `with-profiles` task, but they
|
|
|
|
are not brought along when another project depends on your project.
|
2011-05-04 02:42:31 +00:00
|
|
|
|
2011-06-24 05:49:00 +00:00
|
|
|
Using [midje](https://github.com/marick/Midje) for your tests would be
|
2012-01-13 06:48:44 +00:00
|
|
|
a typical example; you would not want it included in production, but it's
|
|
|
|
needed to run the tests:
|
2011-05-04 02:42:31 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
```clj
|
|
|
|
(defproject my-stuff "0.1.0-SNAPSHOT"
|
|
|
|
:description "FIXME: write description"
|
2012-03-06 22:49:39 +00:00
|
|
|
:url "http://example.com/FIXME"
|
|
|
|
:license {:name "Eclipse Public License"
|
|
|
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
|
|
|
:dependencies [[org.clojure/clojure "1.3.0"]]
|
2012-01-13 06:48:44 +00:00
|
|
|
:profiles {:dev {:dependencies [[midje "1.3.1"]]}})
|
|
|
|
```
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Note that profile-specific dependencies are different from plugins in
|
|
|
|
context; plugins run in Leiningen's process while dependencies run in
|
2012-03-06 22:49:39 +00:00
|
|
|
your project itself. (Older versions of Leiningen lacked this distinction.)
|
2012-01-13 06:48:44 +00:00
|
|
|
|
|
|
|
If you have dependencies that are not _necessary_ for developing but
|
2011-06-24 05:49:00 +00:00
|
|
|
just for convenience (things like
|
|
|
|
[Swank Clojure](http://github.com/technomancy/swank-clojure) for Emacs
|
2012-01-13 06:48:44 +00:00
|
|
|
support or [clj-stacktrace](http://github.com/mmcgrana/clj-stacktrace)
|
|
|
|
you should add them to the `:user` profile in `~/.lein/profiles`
|
|
|
|
instead of the `:dev` profile. Both those profiles are active by
|
|
|
|
default; the difference is the convention for where they are specified.
|
2011-06-24 05:49:00 +00:00
|
|
|
|
2010-06-16 01:58:14 +00:00
|
|
|
## Writing the Code
|
|
|
|
|
|
|
|
This is the part Leiningen can't really help you with; you're on your
|
2011-05-04 02:42:31 +00:00
|
|
|
own here. Well—not quite. Leiningen can help you with running your
|
2010-06-16 01:58:14 +00:00
|
|
|
tests.
|
|
|
|
|
|
|
|
$ lein test
|
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Testing my.test.stuff
|
|
|
|
|
|
|
|
FAIL in (a-test) (stuff.clj:7)
|
|
|
|
FIXME, I fail.
|
|
|
|
expected: (= 0 1)
|
|
|
|
actual: (not (= 0 1))
|
|
|
|
|
2010-06-16 01:58:14 +00:00
|
|
|
Ran 1 tests containing 1 assertions.
|
|
|
|
1 failures, 0 errors.
|
|
|
|
|
|
|
|
Of course, we haven't written any tests yet, so we've just got the
|
2012-01-13 06:48:44 +00:00
|
|
|
skeleton failing tests that Leiningen gave us with `lein new`. But
|
|
|
|
once we fill it in the test suite will become more useful. Sometimes
|
|
|
|
if you've got a large test suite you'll want to run just one or two
|
|
|
|
namespaces at a time:
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
$ lein test my.test.stuff.parser
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Testing my.test.stuff.parser
|
2010-06-16 01:58:14 +00:00
|
|
|
Ran 2 tests containing 10 assertions.
|
|
|
|
0 failures, 0 errors.
|
|
|
|
|
2010-11-10 06:20:22 +00:00
|
|
|
Rather than running your whole suite or just a few namespaces at a
|
|
|
|
time, you can run a subset of your tests using test selectors. To do
|
|
|
|
this, you attach metadata to various deftests.
|
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
```clj
|
2012-01-13 06:48:44 +00:00
|
|
|
(deftest ^:integration network-heavy-test
|
2011-11-11 20:16:52 +00:00
|
|
|
(is (= [1 2 3] (:numbers (network-operation)))))
|
|
|
|
```
|
2010-11-10 06:20:22 +00:00
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
Then add a `:test-selectors` map to project.clj:
|
2010-11-10 06:20:22 +00:00
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
```clj
|
2012-01-13 06:48:44 +00:00
|
|
|
:test-selectors {:default (complement :integration)
|
2011-11-11 20:16:52 +00:00
|
|
|
:integration :integration
|
|
|
|
:all (fn [_] true)}
|
|
|
|
```
|
2010-11-10 06:20:22 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Now if you run `lein test` it will only run deftests that don't have
|
|
|
|
`:integration` metadata, while `lein test :integration` will only run
|
|
|
|
the integration tests and `lein test :all` will run everything. You
|
2011-04-10 00:48:45 +00:00
|
|
|
can include test selectors and listing test namespaces in the same
|
2011-06-24 05:49:00 +00:00
|
|
|
run.
|
2010-11-10 06:20:22 +00:00
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
Running `lein test` from the command-line is suitable for regression
|
|
|
|
testing, but the slow startup time of the JVM makes it a poor fit for
|
|
|
|
testing styles that require tighter feedback loops. In these cases,
|
|
|
|
either keep a repl open for running the appropriate call to
|
2012-01-13 06:48:44 +00:00
|
|
|
[clojure.test/run-tests](http://clojuredocs.org/clojure_core/1.3.0/clojure.test/run-tests)
|
|
|
|
or look into editor integration such as
|
|
|
|
[clojure-test-mode](https://github.com/technomancy/clojure-mode).
|
2010-08-11 03:21:19 +00:00
|
|
|
|
2010-11-21 06:22:51 +00:00
|
|
|
Keep in mind that while keeping a single process around is convenient,
|
|
|
|
it's easy for that process to get into a state that doesn't reflect
|
2011-05-04 02:42:31 +00:00
|
|
|
the files on disk—functions that are loaded and then deleted from the
|
2010-11-21 06:22:51 +00:00
|
|
|
file will remain in memory, making it easy to miss problems arising
|
2011-05-04 02:42:31 +00:00
|
|
|
from missing functions (often referred to as "getting
|
2012-01-13 06:48:44 +00:00
|
|
|
slimed"). Because of this it's advised to do a `lein test` run with a
|
2012-03-06 22:49:39 +00:00
|
|
|
fresh instance periodically in any case, perhaps before you commit.
|
2010-11-21 06:22:51 +00:00
|
|
|
|
2011-05-04 02:42:31 +00:00
|
|
|
## AOT Compiling
|
2010-06-16 01:58:14 +00:00
|
|
|
|
|
|
|
If you're lucky you'll be able to get away without doing any AOT
|
2010-06-17 04:10:56 +00:00
|
|
|
(ahead-of-time) compilation. But there are some Java interop features
|
2012-01-13 06:48:44 +00:00
|
|
|
that require it, so if you need to use them you should add an `:aot`
|
|
|
|
option into your `project.clj` file. It should be a seq of namespaces
|
2010-06-17 04:10:56 +00:00
|
|
|
you want AOT-compiled. Again, the
|
2010-12-03 02:16:16 +00:00
|
|
|
[sample.project.clj](https://github.com/technomancy/leiningen/blob/stable/sample.project.clj)
|
2010-06-17 04:10:56 +00:00
|
|
|
has example usage.
|
|
|
|
|
2010-08-20 03:53:40 +00:00
|
|
|
Like dependencies, this should happen for you automatically when
|
|
|
|
needed, but if you need to force it you can:
|
2010-06-17 04:10:56 +00:00
|
|
|
|
|
|
|
$ lein compile
|
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Compiling my.stuff
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2010-06-30 03:31:44 +00:00
|
|
|
For your code to compile, it must be run. This means that you
|
2011-03-16 01:45:04 +00:00
|
|
|
shouldn't have any code with side-effects in the top-level. Anything
|
2012-01-13 06:48:44 +00:00
|
|
|
outside a function definition that doesn't start with "def" is
|
2011-03-16 01:45:04 +00:00
|
|
|
suspect. If you have code that should run on startup, place it in a
|
2012-01-13 06:48:44 +00:00
|
|
|
`-main` function as explained below under "Uberjar".
|
2010-06-30 03:31:44 +00:00
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
<!-- TODO: this hasn't been ported to 2.x yet
|
2011-03-16 01:45:04 +00:00
|
|
|
There's
|
|
|
|
[a problem in Clojure](http://dev.clojure.org/jira/browse/CLJ-322)
|
|
|
|
where AOT-compiling a namespace will also AOT compile all the
|
|
|
|
namespaces it depends upon. This often causes unrelated compilation
|
|
|
|
artifacts to be included in the jars, but you can set
|
2012-01-13 06:48:44 +00:00
|
|
|
`:class-file-whitelist` to a regex which will be matched against
|
|
|
|
.class file names you want to keep in order to remove the unwanted
|
|
|
|
file.
|
2012-03-06 22:49:39 +00:00
|
|
|
-->
|
|
|
|
|
|
|
|
For projects that include some Java code, you can set the
|
|
|
|
`:java-source-paths` key in project.clj to a vector of directories
|
|
|
|
containing Java files. (You can set it to ["src"] to keep Java
|
|
|
|
alongside Clojure source or keep them in a separate directory.) Then
|
|
|
|
the `javac` compiler will run before your Clojure code is AOT-compiled,
|
|
|
|
or you can run it manually with the `javac` task.
|
2010-11-07 23:50:25 +00:00
|
|
|
|
2010-06-29 19:58:23 +00:00
|
|
|
## What to do with it
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2010-06-29 19:58:23 +00:00
|
|
|
Generally speaking, there are three different goals that are typical
|
|
|
|
of Leiningen projects:
|
2010-06-17 04:10:56 +00:00
|
|
|
|
2010-06-29 19:58:23 +00:00
|
|
|
* An application you can distribute to end-users
|
|
|
|
* A server-side application
|
2011-05-13 15:15:54 +00:00
|
|
|
* A library for other Clojure projects to consume
|
2010-06-17 04:10:56 +00:00
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
For the first, you typically either build an uberjar. For libraries,
|
|
|
|
you will want to have them published to a repository like Clojars or a
|
|
|
|
private repository. For server-side applications it varies as
|
|
|
|
described below.
|
2010-06-19 03:56:36 +00:00
|
|
|
|
2010-06-29 19:58:23 +00:00
|
|
|
### Uberjar
|
|
|
|
|
2010-08-18 05:21:53 +00:00
|
|
|
The simplest thing to do is to distribute an uberjar. This is a single
|
2010-09-05 22:19:18 +00:00
|
|
|
standalone executable jar file most suitable for giving to
|
|
|
|
nontechnical users. For this to work you'll need to specify a
|
2012-01-13 06:48:44 +00:00
|
|
|
namespace as your `:main` in `project.clj`. By this point our
|
|
|
|
`project.clj` file should look like this:
|
2010-06-29 19:58:23 +00:00
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
```clj
|
2012-01-13 06:48:44 +00:00
|
|
|
(defproject my-stuff "0.1.0-SNAPSHOT"
|
2012-03-06 22:49:39 +00:00
|
|
|
:description "FIXME: write description"
|
|
|
|
:url "http://example.com/FIXME"
|
|
|
|
:license {:name "Eclipse Public License"
|
|
|
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
2012-01-13 06:48:44 +00:00
|
|
|
:dependencies [[org.clojure/clojure "1.3.0"]
|
2011-11-11 20:16:52 +00:00
|
|
|
[org.apache.lucene/lucene-core "3.0.2"]
|
|
|
|
[lancet "1.0.0"]]
|
2012-03-06 22:49:39 +00:00
|
|
|
:profiles {:dev {:dependencies [[midje "1.3.1"]]}}
|
2012-01-13 06:48:44 +00:00
|
|
|
:test-selectors {:default (complement :integration)
|
|
|
|
:integration :integration
|
|
|
|
:all (fn [_] true)}
|
|
|
|
:main my.stuff)
|
2011-11-11 20:16:52 +00:00
|
|
|
```
|
2010-06-29 19:58:23 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
The namespace you specify will need to contain a `-main` function that
|
|
|
|
will get called when your standalone jar is run. This namespace should
|
|
|
|
have a `(:gen-class)` declaration in the `ns` form at the top. The
|
|
|
|
`-main` function will get passed the command-line arguments. Let's try
|
|
|
|
something simple in `src/my/stuff.clj`:
|
2010-06-17 04:10:56 +00:00
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
```clj
|
2012-01-13 06:48:44 +00:00
|
|
|
(ns my.stuff
|
2011-11-11 20:16:52 +00:00
|
|
|
(:gen-class))
|
2010-06-16 01:58:14 +00:00
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
(defn -main [& args]
|
|
|
|
(println "Welcome to my project! These are your args:" args))
|
|
|
|
```
|
2010-06-17 04:10:56 +00:00
|
|
|
|
2010-06-29 19:58:23 +00:00
|
|
|
Now we're ready to generate your uberjar:
|
2010-06-17 04:10:56 +00:00
|
|
|
|
|
|
|
$ lein uberjar
|
2012-01-13 06:48:44 +00:00
|
|
|
Compiling my.stuff
|
|
|
|
Compilation succeeded.
|
|
|
|
Created /home/phil/src/leiningen/my-stuff/target/my-stuff-0.1.0-SNAPSHOT.jar
|
|
|
|
Including my-stuff-0.1.0-SNAPSHOT.jar
|
2011-03-16 01:45:04 +00:00
|
|
|
Including lancet-1.0.0.jar
|
2010-11-20 18:12:52 +00:00
|
|
|
Including clojure-1.2.0.jar
|
2010-06-29 19:58:23 +00:00
|
|
|
Including lucene-core-3.0.2.jar
|
2012-03-06 22:49:39 +00:00
|
|
|
Created /home/phil/src/leiningen/my-stuff/target/my-stuff-0.1.0-SNAPSHOT-standalone.jar
|
2010-06-17 04:10:56 +00:00
|
|
|
|
|
|
|
This creates a single jar file that contains the contents of all your
|
2012-01-13 06:48:44 +00:00
|
|
|
dependencies. Users can run it with a simple `java` invocation,
|
2010-06-17 04:19:04 +00:00
|
|
|
or on some systems just by double-clicking the jar file.
|
2010-06-17 04:10:56 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
$ java -jar my-stuff-0.1.0-standalone.jar Hello world.
|
2010-06-29 19:58:23 +00:00
|
|
|
Welcome to my project! These are your args: (Hello world.)
|
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
You can run a regular (non-uber) jar with the `java`
|
2010-06-29 19:58:23 +00:00
|
|
|
command-line tool, but that requires constructing the classpath
|
|
|
|
yourself, so it's not a good solution for end-users.
|
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
Invoking `lein run` will launch your project's `-main` function as if
|
2010-11-10 06:20:22 +00:00
|
|
|
from an uberjar, but without going through the packaging process. You
|
2012-01-13 06:48:44 +00:00
|
|
|
can also specify an alternate namespace in which to look for `-main`
|
|
|
|
with `lein run -m my.alternate.namespace ARG1 ARG2`.
|
2010-11-07 23:50:25 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
For long-running `lein run` processes, you may wish to use the
|
2011-06-24 05:49:00 +00:00
|
|
|
trampoline task, which allows the Leiningen JVM process to exit before
|
|
|
|
launching your project's JVM. This can save memory:
|
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
$ lein trampoline run -m my-stuff.server 5000
|
2011-06-24 05:49:00 +00:00
|
|
|
|
2012-03-06 22:49:39 +00:00
|
|
|
<!-- TODO: not ported to 2.x yet
|
2010-08-18 05:21:53 +00:00
|
|
|
### Shell Wrappers
|
|
|
|
|
|
|
|
There are a few downsides to uberjars. It's relatively awkward to
|
|
|
|
invoke them compared to other command-line tools. You also can't
|
|
|
|
control how the JVM is launched. To solve this, you can include a
|
|
|
|
shell script in your jar file that can be used to launch the
|
|
|
|
project. Leiningen places this shell script into the
|
2012-01-13 06:48:44 +00:00
|
|
|
`~/.lein/bin` directory at install time. Of course, this is
|
2010-09-05 22:19:18 +00:00
|
|
|
only suitable if your users already use Leiningen.
|
2010-08-18 05:21:53 +00:00
|
|
|
|
2012-01-13 06:48:44 +00:00
|
|
|
If you simply include `:shell-wrapper true` in your
|
2010-08-18 05:21:53 +00:00
|
|
|
project.clj, Leiningen automatically generates a simple shell script
|
|
|
|
wrapper when you create your jar file. However, if you need more
|
|
|
|
control you can provide a map instead:
|
|
|
|
|
2011-11-11 20:16:52 +00:00
|
|
|
```clj
|
2012-01-13 06:48:44 +00:00
|
|
|
:shell-wrapper {:main my-stuff.core
|
|
|
|
:bin "bin/my-stuff"}
|
2011-11-11 20:16:52 +00:00
|
|
|
```
|
2010-08-18 05:21:53 +00:00
|
|
|
|
|
|
|
Normally the shell wrapper will invoke the -main function in your
|
|
|
|
project's :main namespace, but specifying this option triggers AOT for
|
|
|
|
uberjars, so if you wish to avoid this or use a different :main for
|
|
|
|
the shell wrapper vs uberjar you can specify a :main ns inside the
|
|
|
|
:shell-wrapper map. You may also specify a :bin key, which should
|
2010-08-21 01:59:12 +00:00
|
|
|
point to a file relative to the project's root to use as a shell
|
2012-01-13 06:48:44 +00:00
|
|
|
wrapper template instead of the default. The `format` function
|
2010-08-18 05:21:53 +00:00
|
|
|
is called with the contents of this file along with the necessary
|
|
|
|
classpath and the main namespace, so put %s in the right place. See
|
|
|
|
[the default
|
2010-12-03 02:16:16 +00:00
|
|
|
wrapper](https://github.com/technomancy/leiningen/blob/stable/resources/script-template)
|
2010-08-18 05:21:53 +00:00
|
|
|
for an example.
|
2012-03-06 22:49:39 +00:00
|
|
|
-->
|
2010-08-17 05:05:24 +00:00
|
|
|
|
2011-03-16 01:45:04 +00:00
|
|
|
### Server-side Projects
|
|
|
|
|
|
|
|
There are many ways to get your project deployed as a server-side
|
|
|
|
application. Simple programs can be packaged up as tarballs with
|
|
|
|
accompanied shell scripts using the
|
|
|
|
[lein-tar plugin](https://github.com/technomancy/lein-tar) and then
|
|
|
|
deployed using [pallet](http://hugoduncan.github.com/pallet/),
|
|
|
|
[chef](http://opscode.com/chef/), or other mechanisms. Debian packages
|
|
|
|
can be created with
|
|
|
|
[lein-deb](https://github.com/travis/lein-deb). Web applications may
|
2011-05-13 15:15:54 +00:00
|
|
|
be deployed using .war (web application archive) files created by the
|
2011-03-16 01:45:04 +00:00
|
|
|
[lein-ring plugin](https://github.com/weavejester/lein-ring). You
|
|
|
|
can even create
|
|
|
|
[Hadoop projects](https://github.com/ndimiduk/lein-hadoop). These
|
|
|
|
kinds of deployments are so varied that they are better-handled using
|
|
|
|
plugins rather than tasks that are built-in to Leiningen itself.
|
|
|
|
|
2011-05-13 15:15:54 +00:00
|
|
|
It may be tempting to deploy by just checking out your project and
|
2011-06-24 05:49:00 +00:00
|
|
|
using "lein run" on production servers. However, unless you take steps
|
|
|
|
to freeze all the dependencies before deploying, it could be easy to
|
2012-03-06 22:49:39 +00:00
|
|
|
end up with
|
|
|
|
[unrepeatable deployments](https://github.com/technomancy/leiningen/wiki/Repeatability).
|
|
|
|
It's much better to use Leiningen to create a deployable artifact in a
|
|
|
|
continuous integration setting instead. For example, you could have a
|
2011-05-13 15:15:54 +00:00
|
|
|
[Jenkins](http://jenkins-ci.org) CI server run your project's full
|
|
|
|
test suite, and if it passes, upload a tarball to S3. Then deployment
|
|
|
|
is just a matter of pulling down and extracting the known-good tarball
|
|
|
|
on your production servers.
|
|
|
|
|
2011-03-16 01:45:04 +00:00
|
|
|
### Publishing Libraries
|
2010-06-29 19:58:23 +00:00
|
|
|
|
|
|
|
If your project is a library and you would like others to be able to
|
|
|
|
use it as a dependency in their projects, you will need to get it into
|
2011-05-04 02:42:31 +00:00
|
|
|
a public repository. While it's possible to
|
2011-07-06 16:03:03 +00:00
|
|
|
[maintain your own private repository](https://github.com/technomancy/leiningen/blob/stable/doc/DEPLOY.md)
|
2011-05-04 02:42:31 +00:00
|
|
|
or get it into Maven central, the easiest way is to publish it at
|
|
|
|
[Clojars](http://clojars.org). Once you have created an account there,
|
|
|
|
publishing is easy:
|
2010-06-29 19:58:23 +00:00
|
|
|
|
2011-03-10 03:45:36 +00:00
|
|
|
$ lein jar, pom
|
2012-03-06 22:49:39 +00:00
|
|
|
$ scp target/pom.xml target/my-stuff-0.1.0.jar clojars@clojars.org:
|
2010-06-29 19:58:23 +00:00
|
|
|
|
|
|
|
Once that succeeds it will be available as a package on which other
|
|
|
|
projects may depend. You will need to have permission to publish to
|
|
|
|
the project's group-id under Clojars, though if that group-id doesn't
|
|
|
|
exist yet then Clojars will automatically create it and give you
|
|
|
|
permissions.
|
|
|
|
|
2011-03-16 01:45:04 +00:00
|
|
|
For further details about publishing including setting up private
|
2011-07-06 16:03:03 +00:00
|
|
|
repositories, see the [deploy guide](https://github.com/technomancy/leiningen/blob/stable/doc/DEPLOY.md)
|
2010-06-17 04:10:56 +00:00
|
|
|
|
|
|
|
## That's It!
|
|
|
|
|
2011-03-16 01:45:04 +00:00
|
|
|
Now go start coding your next project!
|