[ANN] leiningen - a Clojure build tool

105 views
Skip to first unread message

Phil Hagelberg

unread,
Nov 18, 2009, 2:29:35 AM11/18/09
to clo...@googlegroups.com

I'm pleased to announce the initial release of Leiningen.

Leiningen is a build tool for Clojure designed to not set your hair on fire.

Building Clojure projects with tools designed for Java can be an
exercise in frustration. If you use Ant, you end up copying around a
lot of the same tasks around between XML files on all your projects;
there's a lot of repetition. Maven avoids repetition, but provides
very little transparency into what's really going on behind the scenes
and forces you to become a Maven expert to script a nontrivial
build. Either way you end up writing far more XML than is necessary.

With Leiningen, your build is described using Clojure. You can put any
code you like in your project.clj file; the only requirement is that
it includes a call to defproject. You can define your own tasks in
there if you need to, but the majority of projects should be able to
get by on the tasks that are provided with Leiningen. If you do find a
common task that you need to add, you can implement it as a plugin
rather than copying and pasting among each of your projects.

Projects are defined with Clojure syntax, (not XML!) in project.clj:

(defproject leiningen "0.5.0"
:description "A build tool designed not to set your hair on fire."
:main leiningen.core
:dependencies [[org.clojure/clojure "1.1.0-alpha-SNAPSHOT"]
[org.clojure/clojure-contrib "1.0-SNAPSHOT"]
[ant/ant-launcher "1.6.2"]
[org.apache.maven/maven-ant-tasks "2.0.10"]]
:dev-dependencies [[org.clojure/swank-clojure "1.0"]])


A number of tasks are provided:

$ lein deps # install dependencies in lib/

$ lein test [PRED] # run the project's tests, optionally filtered on PRED

$ lein compile # ahead-of-time compile into classes/

$ lein repl # launch a REPL with the project classpath configured

$ lein clean # remove all build artifacts

$ lein jar # create a jar of the project

$ lein uberjar # create a standalone jar that contains all dependencies

$ lein pom # output a pom.xml file for interop with Maven

$ lein install # install in local repo (currently requires mvn)

$ lein help [TASK] # show a list of tasks or help for a given TASK

Leiningen is extensible, you can define new tasks in project.clj or in
plugins. Add your plugin as a dev-dependency of your project, and you'll
be able to call "lein $YOUR_COMMAND". See the lein-swank directory for
an example of a plugin.

To install simply download the shell script, place it somewhere on your
$PATH, and run "lein self-install":

http://github.com/technomancy/leiningen/raw/master/bin/lein

Many people have expressed frustration at trying to use a tool designed
for Java with their Clojure projects, especially when dealing with
dependencies. I hope this can move things forward and ease the
pain. Note that it's still a very young project, (started about two
weeks ago), but in classic Clojure fashion it is able to leverage a lot
of functionality from other JVM tools.

Please try it out and let me know how it works for your project!

thanks,
Phil

Bonus: Leiningen also integrates with the Clojars open-source
clojure-specific repository coming soon at http://clojars.org.

David Nolen

unread,
Nov 18, 2009, 2:41:46 AM11/18/09
to clo...@googlegroups.com
Awesomeness.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

ngocdaothanh

unread,
Nov 18, 2009, 3:15:17 AM11/18/09
to Clojure
Lein is super easy to install and use!

To demonstrate the ease of installation, the "Installation" part in
README should say:
1. Download only one file: wget http://github.com/technomancy/leiningen/raw/master/bin/lein
2. chmod +x lein
3. ./lein self-install

Thanks for the work.


On Nov 18, 4:41 pm, David Nolen <dnolen.li...@gmail.com> wrote:
> Awesomeness.
>
> > clojure-specific repository coming soon athttp://clojars.org.
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clo...@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com>

Shantanu Kumar

unread,
Nov 18, 2009, 3:39:33 AM11/18/09
to Clojure
Is any IDE support planned for this? As it turns out, many people
(including me) stick with Ant just because the IDE support is
fantastic.

Regards,
Shantanu

ngocdaothanh

unread,
Nov 18, 2009, 3:45:04 AM11/18/09
to Clojure
Which IDE and Ant plugin do you use?

I think you can use "lein pom" to have an pom.xml file for use with
Maven. Hope that your fantastic IDE supports Maven.

Shantanu Kumar

unread,
Nov 18, 2009, 4:25:21 AM11/18/09
to Clojure

On Nov 18, 1:45 pm, ngocdaothanh <ngocdaoth...@gmail.com> wrote:
> Which IDE and Ant plugin do you use?
>
> I think you can use "lein pom" to have an pom.xml file for use with
> Maven. Hope that your fantastic IDE supports Maven.

Earlier I used NetBeans but now I generally use Eclipse -- both of
them support Ant natively and Maven plugins are available.

Regards,
Shantanu

Sean Devlin

unread,
Nov 18, 2009, 9:00:26 AM11/18/09
to Clojure
> I'm pleased to announce the initial release of Leiningen.
>
> Leiningen is a build tool for Clojure designed to not set your hair on fire.
>

Phil -
Will there be a backwards compatibility mode for those of us that like
setting our hair on fire? Perhaps a *set-hair-on-fire* binding that
defaults to false?

(binding [*set-hair-on-fire* true]
;do-stuff)

Sean :)

Teemu Antti-Poika

unread,
Nov 18, 2009, 11:04:16 AM11/18/09
to Clojure
On Nov 18, 4:00 pm, Sean Devlin <francoisdev...@gmail.com> wrote:
> Will there be a backwards compatibility mode for those of us that like
> setting our hair on fire?  Perhaps a *set-hair-on-fire* binding that
> defaults to false?

You could always write a maven plugin for leiningen. That ought to do
it.

Stuart Sierra

unread,
Nov 18, 2009, 12:32:51 PM11/18/09
to Clojure
On Nov 18, 9:00 am, Sean Devlin <francoisdev...@gmail.com> wrote:
> (binding [*set-hair-on-fire* true]
>   ;do-stuff)

I like this just for the Var name.
-SS

Phil Hagelberg

unread,
Nov 19, 2009, 12:20:47 AM11/19/09
to clo...@googlegroups.com
ngocdaothanh <ngocda...@gmail.com> writes:

> Lein is super easy to install and use!
>
> To demonstrate the ease of installation, the "Installation" part in
> README should say:
> 1. Download only one file: wget http://github.com/technomancy/leiningen/raw/master/bin/lein
> 2. chmod +x lein
> 3. ./lein self-install
>
> Thanks for the work.

Good idea; I'll update it.

-Phil

Phil Hagelberg

unread,
Nov 19, 2009, 12:22:09 AM11/19/09
to clo...@googlegroups.com
Shantanu Kumar <kumar.s...@gmail.com> writes:

> Is any IDE support planned for this? As it turns out, many people
> (including me) stick with Ant just because the IDE support is
> fantastic.

I have no plans myself, but if writing the pom is not sufficient a
plugin could be written. I've never used an IDE, so I don't know what
kind of features people expect. Tests and compilation should be easy to
do without a build tool (at least it is Emacs), so are you just looking
for a button on a toolbar for each of lein's tasks?

I must confess I don't understand the "avoid the command-line" mindset
at all, so I need a little extra explanation.

-Phil

Shantanu Kumar

unread,
Nov 19, 2009, 1:45:19 AM11/19/09
to Clojure


On Nov 19, 10:22 am, Phil Hagelberg <p...@hagelb.org> wrote:
I don't use Maven, so can't tell about that. This is how an Ant view
looks like in Eclipse (list of build targets): http://www.easyscreens.info/?v=5109

You can right-click on a build target and run / debug it from the
context menu. Double-clicking a target instantly runs it. Debugging
(stepping through breakpoints etc) is something that may be hard to do
from command line, especially for a large code base.

Regards,
Shantanu

Martin DeMello

unread,
Nov 19, 2009, 2:50:57 AM11/19/09
to clo...@googlegroups.com
On Thu, Nov 19, 2009 at 10:52 AM, Phil Hagelberg <ph...@hagelb.org> wrote:
>
> I must confess I don't understand the "avoid the command-line" mindset
> at all, so I need a little extra explanation.

It's a matter of context switching. If I'm working in an IDE, I want
to compile the code without having to open a new window just to type
'ant' or whatever in.

martin

mac

unread,
Nov 19, 2009, 6:13:09 AM11/19/09
to Clojure
On Nov 19, 8:50 am, Martin DeMello <martindeme...@gmail.com> wrote:
> On Thu, Nov 19, 2009 at 10:52 AM, Phil Hagelberg <p...@hagelb.org> wrote:
>
> > I must confess I don't understand the "avoid the command-line" mindset
> > at all, so I need a little extra explanation.
>
> It's a matter of context switching. If I'm working in an IDE, I want
> to compile the code without having to open a new window just to type
> 'ant' or whatever in.
>
> martin

I'm sure it's unnecessary to mention this but I think it's a good idea
to keep the tool working on the command line without any fuss just
like ant or maven. That way it will always work regardless of
environment (e.g. on a continous integration server). IDE frontends
can be made separately and independent of the tool itself.

meb

unread,
Nov 19, 2009, 10:27:35 AM11/19/09
to Clojure
Was the name Leiningen inspired by the Esquire short story "Leiningen
vs. Ants"? That would be a brilliantly obscure way to challenge the
predominance of ant. Or did you have another reference in mind.

Mark

Alex Osborne

unread,
Nov 19, 2009, 4:23:43 PM11/19/09
to clo...@googlegroups.com
meb wrote:
> Was the name Leiningen inspired by the Esquire short story "Leiningen
> vs. Ants"? That would be a brilliantly obscure way to challenge the
> predominance of ant. Or did you have another reference in mind.

From the Leiningen README:

"Leiningen!" he shouted. "You're insane! They're not creatures you can
fight--they're an elemental--an 'act of God!' Ten miles long, two miles
wide--ants, nothing but ants! And every single one of them a fiend from
hell... -- from Leiningen Versus the Ants by Carl Stephenson

For those who haven't heard of it:

http://en.wikipedia.org/wiki/Leiningen_Versus_the_Ants

The story seems to be online in various places, like this one:

http://www.americanliterature.com/Stephenson/SS/LeiningenVersustheAnts.html

Graham Fawcett

unread,
Nov 20, 2009, 11:06:16 AM11/20/09
to clo...@googlegroups.com
On Wed, Nov 18, 2009 at 2:29 AM, Phil Hagelberg <ph...@hagelb.org> wrote:
>
> With Leiningen, your build is described using Clojure. You can put any
> code you like in your project.clj file; the only requirement is that
> it includes a call to defproject. You can define your own tasks in
> there if you need to, but the majority of projects should be able to
> get by on the tasks that are provided with Leiningen. If you do find a
> common task that you need to add, you can implement it as a plugin
> rather than copying and pasting among each of your projects.

This is outstanding; thank you!

I'd love to see a short recipe on how to deploy a simple application
(hello-world) into an executable jar using Leiningen. I've tried, but
seem to be messing something up.

Best,
Graham

Sean Devlin

unread,
Nov 20, 2009, 11:11:42 AM11/20/09
to Clojure
The Incanter guys put something up:

http://incanter-blog.org/2009/11/20/leiningen-clojars/

On Nov 20, 11:06 am, Graham Fawcett <graham.fawc...@gmail.com> wrote:

Graham Fawcett

unread,
Nov 20, 2009, 11:21:31 AM11/20/09
to clo...@googlegroups.com
On Fri, Nov 20, 2009 at 11:11 AM, Sean Devlin <francoi...@gmail.com> wrote:
> The Incanter guys put something up:
>
> http://incanter-blog.org/2009/11/20/leiningen-clojars/

Excellent, thanks!

Leiningen + Clojars is a game-changer for Clojure. I'm very excited.

Will-need-to-practice-spelling-leiningen'ly yours,
Graham
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com

Sean Devlin

unread,
Nov 20, 2009, 11:28:38 AM11/20/09
to Clojure
Something tells me we'll just be calling it 'lein'. Is that okay
Phil?

Sean

On Nov 20, 11:21 am, Graham Fawcett <graham.fawc...@gmail.com> wrote:

Laurent PETIT

unread,
Nov 20, 2009, 12:31:38 PM11/20/09
to clo...@googlegroups.com

Phil Hagelberg

unread,
Nov 20, 2009, 1:40:33 PM11/20/09
to clo...@googlegroups.com
Sean Devlin <francoi...@gmail.com> writes:

> Something tells me we'll just be calling it 'lein'. Is that okay
> Phil?

Yeah, there's a reason the bin script is called "lein"... I was
misspelling it myself for the first few days of working on it. =)

-Phil
Message has been deleted

bOR_

unread,
Nov 22, 2009, 4:09:54 AM11/22/09
to Clojure
Leiningen is very easy to pronounce for the dutch :). We've the word
"Leningen" anyway ("Loans"), and ei is a common vowel combination in
dutch as well (I actually grew up in Leiden).

Ontopic: I might be missing something, but is there an obvious way to
do something like "lein src/chlamydia.clj" when I'm in the projects'
directory ("chlamydia"), to run a script as in "java -server
clojure.main chlamydia.clj"? I didn't see anything in the file "lein"
itself that seemed to point to that, so I added the below bit after
the "if repl" bit.

elif [ ${1: -4} = ".clj" ]; then
# Small hack to use lein to start clojure scripts
java -cp "$CLASSPATH" clojure.main "$1"

which seems to work fine, but as I'm unfamiliar with the whole
building practice of having a project directory, with a src and a
project.clj, I'm not sure if there is a better workflow than using the
above and a few different variants of chlamydia.clj (next to the main
one) in the src directory.

On Nov 20, 7:40 pm, Phil Hagelberg <p...@hagelb.org> wrote:

ajuc

unread,
Nov 22, 2009, 4:18:43 AM11/22/09
to Clojure


On 22 Lis, 13:09, bOR_ <boris.sch...@gmail.com> wrote:
> Ontopic: I might be missing something, but is there an obvious way to
> do something like "lein src/chlamydia.clj" when I'm in the projects'
> directory ("chlamydia"), to run a script as in "java -server
> clojure.main chlamydia.clj"? I didn't see anything in the file "lein"
> itself that seemed to point to that, so I added the below bit after
> the "if repl" bit.

Offtopic: I'm very curious, what are the reasons to call the project
"chlamydia" :)

bOR_

unread,
Nov 22, 2009, 4:54:42 AM11/22/09
to Clojure
I'm currently modeling the spread and prevalence of chlamydia over a
dynamic sexual contact network. Hence the name :-).

Plotting the graphs etc is done with Incanter, and I'm looking into
processing to draw parts of the network. Its my second science project
in Clojure (the first one was called Eden, on evolution of the human
immune system in response to pathogens), and there will be a third one
starting in january on disease spread percolating through a network of
gerbil burrows in Kazachstan (unnamed as of yet).

bOR_

unread,
Nov 22, 2009, 10:14:33 AM11/22/09
to Clojure
What is the normal way to let Leiningen know about local jars? I am
using brics automaton in one of my projects, and that jar is only
downloadable after confirming the bsd licence (http://www.brics.dk/
automaton/), so I have it locally on my disk, but it isn't in clojars
or mvnrepositiory.com.

It being a BSD licence, it allows redistribution. Can I just upload it
to Clojars?

David Brown

unread,
Nov 22, 2009, 12:12:48 PM11/22/09
to clo...@googlegroups.com
On Sun, Nov 22, 2009 at 01:05:43AM -0800, bOR_ wrote:

>elif [ ${1: -4} = ".clj" ]; then
> # Small hack to use lein to start clojure scripts
> java -cp "$CLASSPATH" clojure.main "$1"

How about
elif [ ${1: -4} = ".clj" ]; then
# Small hack to use lein to start clojure scripts
java -cp "$CLASSPATH" clojure.main "$@"

So you can even pass arguments to the script.

BTW, the leiningen.core invocation at the end should also be "$@" so
that arguments with spaces don't get expanded into multiple arguments.

If you add arguments to the 'repl' case, then you can run scripts
using that as well.

David

David Brown

unread,
Nov 22, 2009, 12:16:40 PM11/22/09
to clo...@googlegroups.com
On Sun, Nov 22, 2009 at 07:14:33AM -0800, bOR_ wrote:

>What is the normal way to let Leiningen know about local jars? I am
>using brics automaton in one of my projects, and that jar is only
>downloadable after confirming the bsd licence (http://www.brics.dk/
>automaton/), so I have it locally on my disk, but it isn't in clojars
>or mvnrepositiory.com.

When the maven fails to find the package, it will spew out
instructions on how to install it into your local maven cache.
Something like:

mvn install:install-file -DgroupId=org.domain -DartifactId=package
-Dversion=1.2.3 -Dpackaging=jar
-Dfile=path/to/file.jar

But, on one line.

Having to agree with a BSD license is a bit strange.

David

John Harrop

unread,
Nov 22, 2009, 12:58:32 PM11/22/09
to clo...@googlegroups.com
How is it pronounced anyway, at the start? LINE... or LANE...?

Michael Wood

unread,
Nov 22, 2009, 1:38:15 PM11/22/09
to clo...@googlegroups.com
2009/11/22 John Harrop <jharr...@gmail.com>:
> How is it pronounced anyway, at the start? LINE... or LANE...?

If it's German-ish, it would be the former. If it's more like
Afrikaans (or maybe Dutch?) it would be the latter, although it would
be a very strange sort of Afrikaans word, so I'd go with the German
pronunciation.

--
Michael Wood <esio...@gmail.com>

Alex Osborne

unread,
Nov 22, 2009, 3:52:48 PM11/22/09
to clo...@googlegroups.com
bOR_ wrote:
> What is the normal way to let Leiningen know about local jars? I am
> using brics automaton in one of my projects, and that jar is only
> downloadable after confirming the bsd licence (http://www.brics.dk/
> automaton/), so I have it locally on my disk, but it isn't in clojars
> or mvnrepositiory.com.
>
> It being a BSD licence, it allows redistribution. Can I just upload it
> to Clojars?

Sure, go for it.

> Having to agree with a BSD license is a bit strange.

Yeah, you see that a lot with university projects for some reason. Even
worse they sometimes force you to join a mailing list or fill in a "what
are you going to use this for?" form.

Gilbert

unread,
Nov 19, 2009, 6:21:04 PM11/19/09
to Clojure
Leiningen and Clojar are

LEGEN...

wait for it...

DARY!

Anyways, just wanted to say thanks.
> http://www.americanliterature.com/Stephenson/SS/LeiningenVersustheAnt...

Krukow

unread,
Nov 23, 2009, 9:10:05 AM11/23/09
to Clojure


On Nov 18, 8:29 am, Phil Hagelberg <p...@hagelb.org> wrote:
> I'm pleased to announce the initial release of Leiningen.
>
> Leiningen is a build tool for Clojure designed to not set your hair on fire.

I really like it so far - particularly the combination of lein and
clojars!

I'm not sure if this is the place for questions and/or bug-reports,
perhaps lein should have its own group?

Anyway, here is my situation. I have a project I want to push to
clojars using lein. The project depends on the newest version of
clojure in the new branch - i.e. commit
75cd05080f7260c54007d7728fb280ae53b56f63 in http://github.com/richhickey/clojure/tree/new

I created a clojar in my group:
[org.clojars.krukow/clojure-1.1.0-alpha-snapshot
"75cd05080f7260c54007d7728fb280ae53b56f63"]

and for my project which depends on this jar i created a project.clj:

(defproject org.clojars.krukow/circuit-breaker "0.1"
:dependencies [[org.clojars.krukow/clojure-1.1.0-alpha-snapshot

"75cd05080f7260c54007d7728fb280ae53b56f63"]])

I ran deps:
krukow:~/Projects/clojure/circuitbreaker$ lein deps
[copy] Copying 1 file to /Users/krukow/Projects/clojure/
circuitbreaker/lib
krukow:~/Projects/clojure/circuitbreaker$ ls lib/
clojure-1.1.0-alpha-
snapshot-75cd05080f7260c54007d7728fb280ae53b56f63.jar
krukow:~/Projects/clojure/circuitbreaker$

But now all lein commands fail. E.g,

krukow:~/Projects/clojure/circuitbreaker$ lein help
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:1516)
at clojure.lang.RT.load(RT.java:389)
at clojure.lang.RT.load(RT.java:371)
...

I suspect it is because I've put another version of clojure on the
classpath.

Any advice on how to do projects that depend on specific versions of
clojure?

/Karl

Alex Osborne

unread,
Nov 23, 2009, 7:12:44 PM11/23/09
to clo...@googlegroups.com
Krukow <karl....@gmail.com> writes:

> On Nov 18, 8:29 am, Phil Hagelberg <p...@hagelb.org> wrote:
>> I'm pleased to announce the initial release of Leiningen.
>>
>> Leiningen is a build tool for Clojure designed to not set your hair on fire.
>
> I really like it so far - particularly the combination of lein and
> clojars!
>
> I'm not sure if this is the place for questions and/or bug-reports,
> perhaps lein should have its own group?

We hadn't gotten around to really telling anyone yet, but there is in
fact a Leiningen group:

http://groups.google.com/group/leiningen

There's also a #leiningen channel on irc.freenode.org.

> I suspect it is because I've put another version of clojure on the
> classpath.
>
> Any advice on how to do projects that depend on specific versions of
> clojure?

I'm afraid that you can't just yet, but we're working on it. The
problem is compilation currently happens in the same JVM as Leiningen
itself runs. Compiling in a separate process or classloader is a
planned Lein 1.0 feature and should fix this up.

Mark Derricutt

unread,
Nov 30, 2009, 4:09:46 PM11/30/09
to clo...@googlegroups.com
When I finally get around to working on my clojure polyglot
implementation for maven 3 I'll probably be basing my project
structure off of leiningen, which should mean anything IDE using maven
should work with the project file. Sadly I'm still trying to nail
down some time to look at this project thou.

--
Pull me down under...
Reply all
Reply to author
Forward
0 new messages