Apparently everyone is jumping on the Leiningen bandwagon and deleting their build.xml files. I guess that means I'm moving, too.
Now, I like to keep track of Clojure master. Right now, Clojure reports "Clojure 1.2.0-master-SNAPSHOT".
(I don't see that in Maven Central or in Clojars, so I guess I have to put it in my local repository...?)
Unfortunately, not everybody keeps up-to-date like I do; most of the projects I use demand "1.1.0-alpha-SNAPSHOT". I'm sure there are still projects that demand 1.0.
Adjusting the lein script to use my local Clojure install gave me a great error:
Caused by: java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V at clojure.contrib.with_ns$with_ns__7929.<init>(with_ns.clj:20) at clojure.contrib.with_ns__init.load(Unknown Source) at clojure.contrib.with_ns__init.<clinit>(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at clojure.lang.RT.loadClassForName(RT.java:1523) at clojure.lang.RT.load(RT.java:396) at clojure.lang.RT.load(RT.java:378) at clojure.core$load__4869$fn__4876.invoke(core.clj:4294) at clojure.core$load__4869.doInvoke(core.clj:4293) at clojure.lang.RestFn.invoke(RestFn.java:409) at clojure.core$load_one__4810.invoke(core.clj:4130) at clojure.core$load_lib__4825.doInvoke(core.clj:4167) at clojure.lang.RestFn.applyTo(RestFn.java:143) at clojure.core$apply__3434.invoke(core.clj:478) at clojure.core$load_libs__4841.doInvoke(core.clj:4193) at clojure.lang.RestFn.applyTo(RestFn.java:138) at clojure.core$apply__3434.invoke(core.clj:480) at clojure.core$use__4865.doInvoke(core.clj:4271) at clojure.lang.RestFn.invoke(RestFn.java:409) at leiningen.core$eval__5$loading__4758__auto____6.invoke(core.clj:1) at leiningen.core$eval__5.invoke(core.clj:1) at clojure.lang.Compiler.eval(Compiler.java:5349)
and I saw a similar problem with builds that referred to libraries built with different versions of Clojure.
How do people deal with this? How can one simultaneously use two libraries which have hardwired dependencies on two different Clojure versions, each of which might be mutually incompatible?
What's the community protocol around locally installing Clojure 1.2, and adding that as a dependency for a published library?
What's the right way to get lein itself to use a recent Clojure build, rather than the version with which it ships?
> What's the community protocol around locally installing Clojure 1.2, > and adding that as a dependency for a published library?
I'll take a shot at this question.
Clojure stresses immutability, and dependencies should be no different. I'd say it's bad form to force a dependency on an unreleased version of Clojure, because it's a moving target. Granted, there should be a mechanism for version 1.1.x, or 1.x so that libraries are forward compatible to a certain version.
On Jan 21, 8:37 pm, Sean Devlin <francoisdev...@gmail.com> wrote:
> Clojure stresses immutability, and dependencies should be no > different. I'd say it's bad form to force a dependency on an > unreleased version of Clojure, because it's a moving target. Granted,
BTW, Clojure also stresses *controlled mutability*. I'd say it's bad form to impose a value judgment in place of a technical solution. If some 1.2 features make for a better project development experience, why rule them out?
We're not all jumping on Leiningen, some of us are sticking with maven, using the maven-clojure-compiler plugin, and also the experimental Maven Polyglot Clojure build support:
On Fri, Jan 22, 2010 at 2:21 PM, Richard Newman <holyg...@gmail.com> wrote: > Apparently everyone is jumping on the Leiningen bandwagon and deleting their > build.xml files. I guess that means I'm moving, too.
> We're not all jumping on Leiningen, some of us are sticking with > maven, using the maven-clojure-compiler plugin, and also the > experimental Maven Polyglot Clojure build support:
It's not the "Leiningen" that's important, it's the "jumping": away from Ant, not Maven. Every library I use had an Ant build script. I never saw a POM.
(Apologies for this diversion. Maybe it'll be of interest to some on this list.)
I'm somewhat swayed by Leiningen because it makes doing some things easy (uberjar! starting a REPL! neat!), at the cost of making other things (such as managing dependencies myself) more frustrating. However, if it wasn't for all the people blindly deleting their Ant build scripts, I would be sticking with my Ant workflow for another few months. I don't think Lein is quite targeted at users like me.*
That's OK, and I'm sure it'll change over time. I'm looking forward to more plugins arriving to perhaps allow me to define per-project tasks (for database operations, say).
I'm not at all swayed by Maven itself. XML *and* bloated opaque dependency management! What's not to love?
(Yes, I know it does a lot of cool stuff -- http://blog.lick-me.org/2010/01/maven-sucks/ is a good start on the pros and cons -- I just don't care about most of that stuff, and I do care about the horrible parts.)
That certainly makes Maven's syntax less repellent, but it still has Maven underneath.
-R
* For those who might ask "and what kind of user are you?": * I keep up to date with Clojure master. I don't use binary releases. * I fix bugs and make changes in my local Clojure/contrib/third- party library trees, and I want *all* of my builds to use *those*, not their own choice of versions. With lein/mvn I have to install a custom version of those libraries into my repo, then change all of my libraries to use the custom version. New build = changing every library's project file again (or overwriting the repo version... not sure how acceptable a solution that is). With my previous approach I simply had to overwrite a jar (allowing my VCS to track the old version). * I prefer using Git commit IDs to unambiguously reference versions, not an arbitrary version string which I have to change in a separate commit. * I run arbitrary Ant tasks -- such as SQL scripts -- in my projects. I don't see that in Leiningen. I'd love someone to point me to it. * Not all of my projects are open-source, so I like to store their cross-dependencies in version control, not in some custom repository server. I don't want to have to figure out how to run my own Maven repo somewhere, solving the auth problem again, etc. etc.
> How do people deal with this? How can one simultaneously use two > libraries which have hardwired dependencies on two different Clojure > versions, each of which might be mutually incompatible?
> What's the community protocol around locally installing Clojure 1.2, > and adding that as a dependency for a published library?
It's necessary in these circumstances to use AOT as sparingly as possible. If there's no AOT done, there's no problem with mixing Clojure versions (within reason). So the latest version of Leiningen does zero AOT'ing unless you explicitly ask for it.
> What's the right way to get lein itself to use a recent Clojure build, > rather than the version with which it ships?
Leiningen allows the project to use a different version of Clojure than Leiningen itself, so (modulo a bug in the repl task for which this doesn't apply) this is a non-issue.
>> How do people deal with this? How can one simultaneously use two >> libraries which have hardwired dependencies on two different Clojure >> versions, each of which might be mutually incompatible?
>> What's the community protocol around locally installing Clojure 1.2, >> and adding that as a dependency for a published library?
> It's necessary in these circumstances to use AOT as sparingly as > possible. If there's no AOT done, there's no problem with mixing > Clojure > versions (within reason). So the latest version of Leiningen does zero > AOT'ing unless you explicitly ask for it.
That wasn't quite my question.
Say I rely on a particular feature in 1.2, perhaps
Add agent error handlers and error modes :fail and :continue. Fixes #30
My code doesn't work on 1.1 or earlier.
* How can I express a dependency in a published library for a library which has not been published? Tough question. People will be annoyed if I upload my own build of 1.2, then don't fix my POM when Clojure 1.2 is officialy released.
* What happens when someone else's code -- which explicitly specifies Clojure 1.1 -- wants to use my library? If one uses AOT, you might get some odd stack trace. If one does not use AOT, you get a compile error. Much better solutions are "you get a warning", or "you can specify a range of allowable versions, and the build software chooses the right version".
This is a hard problem, and any dependency management system which requires you to pick a single version of a dependency, when multiple versions exist (and your code might work on more than one) is going to hit it. I don't think "everybody has to upgrade at once" is a good solution.
>> What's the right way to get lein itself to use a recent Clojure >> build, >> rather than the version with which it ships?
> Leiningen allows the project to use a different version of Clojure > than > Leiningen itself, so (modulo a bug in the repl task for which this > doesn't apply) this is a non-issue.
Thanks for clarifying.
It appears that it does not work with 1.2, because running `lein` after changing CLOJURE_JAR to point to my 1.2 build caused that error to occur!
> * For those who might ask "and what kind of user are you?": > * I keep up to date with Clojure master. I don't use binary releases. > * I fix bugs and make changes in my local Clojure/contrib/third- > party library trees, and I want *all* of my builds to use *those*, > not their own choice of versions. With lein/mvn I have to install a > custom version of those libraries into my repo, then change all of > my libraries to use the custom version. New build = changing every > library's project file again (or overwriting the repo version... not > sure how acceptable a solution that is). With my previous approach I > simply had to overwrite a jar (allowing my VCS to track the old > version).
My needs are pretty similar, which is why I have not adopte leiningen either.
I typically work on a set of related projects, all of which are under development at the same time. I don't want anything AOT compiled and I must be able to specify dependencies that exist only as source code on my computer and have no version number. So for the moment, I am managing everything manually; fortunately my projects are small and few enough for that. I'd love to be able to use leiningen for some of the tasks, and I hope it will evolve along those lines.
On Jan 22, 6:40 am, Mark Derricutt <m...@talios.com> wrote:
> We're not all jumping on Leiningen, some of us are sticking with > maven, using the maven-clojure-compiler plugin, and also the > experimental Maven Polyglot Clojure build support:
The problem is AOT compiled code. After that discussion I switched the default in clojuresque from AOT to source. AOT must no explicitly be enabled. Another possibility would be to provide two jars: one AOT'd and one src-only.
As for the snapshots: you can find them on http://build.clojure.org/snapshots. So you (can but) don't have to put them into a local repository.
I got a similar issue, yesteday I tried to update from github to newest version of clojure\clojure-contrib, and clojure-contrib showed me "Caused by: java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V", I checked out lot's of branched in clojure-contrib, but ended up unpacking manually downloaded zip (with 1.1.x probably), anyway it looked like clojure-contrib really not up to date with clojure (master, or new, or any other branch).
On Fri, Jan 22, 2010 at 4:21 AM, Richard Newman <holyg...@gmail.com> wrote: > Hi folks,
> Apparently everyone is jumping on the Leiningen bandwagon and deleting > their build.xml files. I guess that means I'm moving, too.
> Now, I like to keep track of Clojure master. Right now, Clojure reports > "Clojure 1.2.0-master-SNAPSHOT".
> (I don't see that in Maven Central or in Clojars, so I guess I have to put > it in my local repository...?)
> Unfortunately, not everybody keeps up-to-date like I do; most of the > projects I use demand "1.1.0-alpha-SNAPSHOT". I'm sure there are still > projects that demand 1.0.
> Adjusting the lein script to use my local Clojure install gave me a great > error:
> Caused by: java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V > at clojure.contrib.with_ns$with_ns__7929.<init>(with_ns.clj:20) > at clojure.contrib.with_ns__init.load(Unknown Source) > at clojure.contrib.with_ns__init.<clinit>(Unknown Source) > at java.lang.Class.forName0(Native Method) > at java.lang.Class.forName(Class.java:247) > at clojure.lang.RT.loadClassForName(RT.java:1523) > at clojure.lang.RT.load(RT.java:396) > at clojure.lang.RT.load(RT.java:378) > at clojure.core$load__4869$fn__4876.invoke(core.clj:4294) > at clojure.core$load__4869.doInvoke(core.clj:4293) > at clojure.lang.RestFn.invoke(RestFn.java:409) > at clojure.core$load_one__4810.invoke(core.clj:4130) > at clojure.core$load_lib__4825.doInvoke(core.clj:4167) > at clojure.lang.RestFn.applyTo(RestFn.java:143) > at clojure.core$apply__3434.invoke(core.clj:478) > at clojure.core$load_libs__4841.doInvoke(core.clj:4193) > at clojure.lang.RestFn.applyTo(RestFn.java:138) > at clojure.core$apply__3434.invoke(core.clj:480) > at clojure.core$use__4865.doInvoke(core.clj:4271) > at clojure.lang.RestFn.invoke(RestFn.java:409) > at > leiningen.core$eval__5$loading__4758__auto____6.invoke(core.clj:1) > at leiningen.core$eval__5.invoke(core.clj:1) > at clojure.lang.Compiler.eval(Compiler.java:5349)
> and I saw a similar problem with builds that referred to libraries built > with different versions of Clojure.
> How do people deal with this? How can one simultaneously use two libraries > which have hardwired dependencies on two different Clojure versions, each of > which might be mutually incompatible?
> What's the community protocol around locally installing Clojure 1.2, and > adding that as a dependency for a published library?
> What's the right way to get lein itself to use a recent Clojure build, > rather than the version with which it ships?
> Thoughts -- and answers! -- welcome.
> Thanks,
> -R
> -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@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+unsubscribe@googlegroups.com<clojure%2Bunsubscribe@googlegroups.com > > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en
From my googling, the only way to solve this in the general case (IE the java case) is through using OSGi. I have no idea what the state of compatibility is between clojure and OSGi at this time. I'd be curious to find out in fact. Here's the stackoverflow.com page I found that describes the situation as I understand it:
> Apparently everyone is jumping on the Leiningen bandwagon and deleting > their build.xml files. I guess that means I'm moving, too.
> Now, I like to keep track of Clojure master. Right now, Clojure > reports "Clojure 1.2.0-master-SNAPSHOT".
> (I don't see that in Maven Central or in Clojars, so I guess I have to > put it in my local repository...?)
> Unfortunately, not everybody keeps up-to-date like I do; most of the > projects I use demand "1.1.0-alpha-SNAPSHOT". I'm sure there are still > projects that demand 1.0.
> Adjusting the lein script to use my local Clojure install gave me a > great error:
> Caused by: java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V > at clojure.contrib.with_ns$with_ns__7929.<init>(with_ns.clj:20) > at clojure.contrib.with_ns__init.load(Unknown Source) > at clojure.contrib.with_ns__init.<clinit>(Unknown Source) > at java.lang.Class.forName0(Native Method) > at java.lang.Class.forName(Class.java:247) > at clojure.lang.RT.loadClassForName(RT.java:1523) > at clojure.lang.RT.load(RT.java:396) > at clojure.lang.RT.load(RT.java:378) > at clojure.core$load__4869$fn__4876.invoke(core.clj:4294) > at clojure.core$load__4869.doInvoke(core.clj:4293) > at clojure.lang.RestFn.invoke(RestFn.java:409) > at clojure.core$load_one__4810.invoke(core.clj:4130) > at clojure.core$load_lib__4825.doInvoke(core.clj:4167) > at clojure.lang.RestFn.applyTo(RestFn.java:143) > at clojure.core$apply__3434.invoke(core.clj:478) > at clojure.core$load_libs__4841.doInvoke(core.clj:4193) > at clojure.lang.RestFn.applyTo(RestFn.java:138) > at clojure.core$apply__3434.invoke(core.clj:480) > at clojure.core$use__4865.doInvoke(core.clj:4271) > at clojure.lang.RestFn.invoke(RestFn.java:409) > at leiningen.core$eval__5$loading__4758__auto____6.invoke(core.clj:1) > at leiningen.core$eval__5.invoke(core.clj:1) > at clojure.lang.Compiler.eval(Compiler.java:5349)
> and I saw a similar problem with builds that referred to libraries > built with different versions of Clojure.
> How do people deal with this? How can one simultaneously use two > libraries which have hardwired dependencies on two different Clojure > versions, each of which might be mutually incompatible?
> What's the community protocol around locally installing Clojure 1.2, > and adding that as a dependency for a published library?
> What's the right way to get lein itself to use a recent Clojure build, > rather than the version with which it ships?
> * I keep up to date with Clojure master. I don't use binary releases. > * I fix bugs and make changes in my local Clojure/contrib/third- > party library trees, and I want *all* of my builds to use *those*, not > their own choice of versions. With lein/mvn I have to install a custom > version of those libraries into my repo, then change all of my > libraries to use the custom version. New build = changing every > library's project file again (or overwriting the repo version... not > sure how acceptable a solution that is). With my previous approach I > simply had to overwrite a jar (allowing my VCS to track the old > version).
I wrote a Rakefile to support locally juggling various clojure / contrib repos. It pushes symlinks to jars into ~/.clojure and the local maven repo, as well as brings up a repl, pulls changes from GitHub, etc. The only major caveat is that the wipe command doesn't check for local changes before deleting files.
which is a maven repo for clojure & contrib artifacts. At /snapshots, there are builds for Clojure 1.2 (1.2.0-master-SNAPSHOT). Leiningen is aware of this repo by default, so you can specify the 1.2.0-master snapshot as a dependency in your project.clj.
On Jan 21, 8:21 pm, Richard Newman <holyg...@gmail.com> wrote:
> Apparently everyone is jumping on the Leiningen bandwagon and deleting > their build.xml files. I guess that means I'm moving, too.
Deleting build.xml files is good. After that, you've got several options, including Leiningen and clojure-maven-plugin, both of which are based on the Maven dependency model.
> Now, I like to keep track of Clojure master. Right now, Clojure > reports "Clojure 1.2.0-master-SNAPSHOT".
> (I don't see that in Maven Central or in Clojars, so I guess I have to > put it in my local repository...?)
> Unfortunately, not everybody keeps up-to-date like I do; most of the > projects I use demand "1.1.0-alpha-SNAPSHOT". I'm sure there are still > projects that demand 1.0.
This is the problem of a young language and immature libraries. You may need to compile those projects yourself and install them in a local repository.
On Thu, Jan 21, 2010 at 10:23:10PM -0800, Richard Newman wrote: >I'm somewhat swayed by Leiningen because it makes doing some things >easy (uberjar! starting a REPL! neat!), at the cost of making other >things (such as managing dependencies myself) more frustrating. >However, if it wasn't for all the people blindly deleting their Ant >build scripts, I would be sticking with my Ant workflow for another >few months. I don't think Lein is quite targeted at users like me.*
For one project, I have a JNI that needs to be built as part of it. I tried converting this to Maven, and once I realized that I needed numerous fake subprojects to work around Maven's rigid flow model, I ended up going back to ant.
I ended up making a fairly general ant script that I can drop into any project and build java/JNI/clojure source as needed. If anyone is interested, the code is at <http://github.com/d3zd3z/webweight>
The build.xml is at the top, and the support files are under 'etc'.
Is it possible in maven or leiningen to place a dependency not on a specific version of a pre-built artifact, but rather on a specific scm revision (or just head, aka SNAPSHOT for binary releases) of a project's source repository, and having the machinery understand it has to first locally build the dependency into a jar/whatever in the process of compiling one's project ?
Alternatively, is it possible to at least depend on a "source" version of the dependency, having it compiled on the fly locally when compiling the main project ? (so that one could benefit from AOP, and this could also solve the problem of a library mixing java and clojure source) ?
Does all that make sense ?
2010/1/22 Stuart Sierra <the.stuart.sie...@gmail.com>:
> On Jan 21, 8:21 pm, Richard Newman <holyg...@gmail.com> wrote: >> Apparently everyone is jumping on the Leiningen bandwagon and deleting >> their build.xml files. I guess that means I'm moving, too.
> Deleting build.xml files is good. After that, you've got several > options, including Leiningen and clojure-maven-plugin, both of which > are based on the Maven dependency model.
>> Now, I like to keep track of Clojure master. Right now, Clojure >> reports "Clojure 1.2.0-master-SNAPSHOT".
>> (I don't see that in Maven Central or in Clojars, so I guess I have to >> put it in my local repository...?)
>> Unfortunately, not everybody keeps up-to-date like I do; most of the >> projects I use demand "1.1.0-alpha-SNAPSHOT". I'm sure there are still >> projects that demand 1.0.
> This is the problem of a young language and immature libraries. You > may need to compile those projects yourself and install them in a > local repository.
> -SS
> -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@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+unsubscribe@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en
Laurent PETIT <laurent.pe...@gmail.com> writes: > Is it possible in maven or leiningen to place a dependency not on a > specific version of a pre-built artifact, but rather on a specific scm > revision (or just head, aka SNAPSHOT for binary releases) of a > project's source repository, and having the machinery understand it > has to first locally build the dependency into a jar/whatever in the > process of compiling one's project ?
When you upload to clojars a version number ending in SNAPSHOT, I believe it is replaced with the current timestamp on the server.
So if you're just interested in pinning yourself to a specific SNAPSHOT rather than just any one out there, that would be the trick. But there's no mechanism for building it yourself, though it's quite easy to do manually.
> Alternatively, is it possible to at least depend on a "source" version > of the dependency, having it compiled on the fly locally when > compiling the main project ? (so that one could benefit from AOP, and > this could also solve the problem of a library mixing java and clojure > source) ?
I've thought about this, and I think it's a great idea. I will probably implement it eventually, but it might take a while since I don't have any projects that would benefit from it right now. So it's a great opportunity for a potential contributor to step up. =)
> which is a maven repo for clojure & contrib artifacts. At /snapshots, > there are builds for Clojure 1.2 (1.2.0-master-SNAPSHOT). Leiningen is > aware of this repo by default, so you can specify the 1.2.0-master > snapshot as a dependency in your project.clj.
Yup, apparently my own 1.2.0-master-SNAPSHOT was replaced by an upstream version sometime yesterday (that is, Lein found a POM). Contrib still wasn't listed, though.
>> Apparently everyone is jumping on the Leiningen bandwagon and >> deleting >> their build.xml files. I guess that means I'm moving, too.
> Deleting build.xml files is good. After that, you've got several > options, including Leiningen and clojure-maven-plugin, both of which > are based on the Maven dependency model.
It's good *if you want to use Maven*. I don't agree that the removal of that choice is good.
> This is the problem of a young language and immature libraries. You > may need to compile those projects yourself and install them in a > local repository.
... and modify *every* library to make sure they all point to the same local Clojure version, otherwise some of them will still be building with some older release.
Oh, and if I don't want three versions of Commons libs (some want Logging 1.1, some Logging 1.1.1, etc.), I have to modify those projects again. Seems a lot like manual dependency management. :)
>> Alternatively, is it possible to at least depend on a "source" >> version >> of the dependency, having it compiled on the fly locally when >> compiling the main project ? (so that one could benefit from AOP, and >> this could also solve the problem of a library mixing java and >> clojure >> source) ?
> I've thought about this, and I think it's a great idea. I will > probably > implement it eventually, but it might take a while since I don't have > any projects that would benefit from it right now. So it's a great > opportunity for a potential contributor to step up. =)
I'd do it if I knew how!
What I'd like is for Leiningen to know about my ~/repos directory, which contains all of my libraries and a load of other people's. If a project file mentions a library, *look there first*. (And don't look upstream for a POM.)
> >> Apparently everyone is jumping on the Leiningen bandwagon and > >> deleting > >> their build.xml files. I guess that means I'm moving, too.
> > Deleting build.xml files is good. After that, you've got several > > options, including Leiningen and clojure-maven-plugin, both of which > > are based on the Maven dependency model.
> It's good *if you want to use Maven*. I don't agree that the removal > of that choice is good.
> > This is the problem of a young language and immature libraries. You > > may need to compile those projects yourself and install them in a > > local repository.
> ... and modify *every* library to make sure they all point to the same > local Clojure version, otherwise some of them will still be building > with some older release.
> Oh, and if I don't want three versions of Commons libs (some want > Logging 1.1, some Logging 1.1.1, etc.), I have to modify those > projects again. Seems a lot like manual dependency management. :)
On Jan 22, 8:20 am, Richard Newman <holyg...@gmail.com> wrote:
> My code doesn't work on 1.1 or earlier.
In maven specifying eg. 1.1 means "use whatever appropriate but prefer 1.1". Now you specify 1.2 and there is a conflict. By saying "use the newer version", 1.2 will be used. AOT compiled libraries should probably specify [1.1], which means only and only 1.1.
> * How can I express a dependency in a published library for a library > which has not been published? Tough question. People will be annoyed > if I upload my own build of 1.2, then don't fix my POM when Clojure > 1.2 is officialy released.
You can specify [1.2-SNAPSHOT,) as depedency. I *believe* this will work then also, when 1.2 is released.
BTW: commit ids as version numbers break down here, because they are not ordered.
> * What happens when someone else's code -- which explicitly specifies > Clojure 1.1 -- wants to use my library? If one uses AOT, you might get > some odd stack trace. If one does not use AOT, you get a compile > error. Much better solutions are "you get a warning", or "you can > specify a range of allowable versions, and the build software chooses > the right version".
When the specification of your library is [1.2-SNAPSHOT,) and the other is [1.1] maven will complain, I would expect, before you run into strange compile errors.
> This is a hard problem, and any dependency management system which > requires you to pick a single version of a dependency, when multiple > versions exist (and your code might work on more than one) is going to > hit it. I don't think "everybody has to upgrade at once" is a good > solution.
Neither maven nor ivy are so simple-minded to allow only one version. How well ranges work out... I can't really know. I only know the theory for now.
Not only. If my library refer to a function that's first defined in library-X version 1.5, and some other code uses library-X 1.4 *and* my library, then there is a fundamental problem whenever you add a dependency on both my library and the other library. This will happen any time a library's API changes and you have dependencies that cross the line.
AOT compilation might make the problem appear at compile-time in some cases, or more often if the library is a "compiler" (i.e., leaves shreds of its implementation in your compiled code), but you don't eliminate the problem by avoiding AOT compilation.
Using a sophisticated dependency system -- having a library specify its requirements, not a dumb version number -- drastically reduces these problems by resolving the requirements to a particular release, or spotting the error and failing fast. Using a dumb version system screws you whenever this occurs, *and* makes it awkward for you to manually resolve the collision.
(OSGI attempts to address this by allowing multiple library versions, but Clojure needs its own classloader, and also enables code to 'flow' across library boundaries through macroexpansion.)
> As for the snapshots: you can find them on http://build.clojure.org/snapshots > . > So you (can but) don't have to put them into a local repository.
Of course, you still do if you have made changes to Clojure in your local checkout.
> BTW: commit ids as version numbers break down here, because they are > not ordered.
They have a partial ordering wrt a particular repo. Many repos have straight-line histories, and thus have a total ordering.
> Neither maven nor ivy are so simple-minded to allow only one version. > How well ranges work out... I can't really know. I only know the > theory for now.
That the underlying system allows it is no comfort when there seems to be no obvious provision in project.clj for this:
Does that mean "use whatever's appropriate", or "I must use 1.1.0 only"? Do these version strings admit that Maven syntax?
How does one tell Maven/lein "never use two different versions of Clojure"? How does one tell Maven to *rebuild* a library -- e.g., Compojure -- using 1.2, so that I can safely use it in my requires-1.2 project? (Or "look in a repo to find a version of Compojure built using 1.2"?)
These are questions that I think must be addressed, because these problems come up all the time.
Just this week I noticed that Apache HttpComponents 4.0.1 and 4.1 use completely different methods to apply pre-emptive HTTP Basic Auth, and have even changed class hierarchies. A version of clj-apache-http targeted at 4.0.1 won't even run against a 4.1 jar (and vice versa), *even without AOT*, because the package names are different. On the other hand, some libraries -- such as log4j -- preserve API compatibility across versions.
Sorry to be raining on everyone's parade with this...
> Just this week I noticed that Apache HttpComponents 4.0.1 and 4.1 > use completely different methods to apply pre-emptive HTTP Basic > Auth, and have even changed class hierarchies. A version of clj- > apache-http targeted at 4.0.1 won't even run against a 4.1 jar (and > vice versa), *even without AOT*, because the package names are > different. On the other hand, some libraries -- such as log4j -- > preserve API compatibility across versions.
In fact, I just hit a concrete example of this.
clj-apache-http uses httpcomponents 4.0.1. ring uses 4.0-alpha6, which is obsolete.
One of my projects currently will not build because ring's transitive dependency gets pulled into lib, and apparently gets on the classpath first, causing the load of clj-apache-http to fail:
[null] java.lang.IllegalArgumentException: No matching ctor found for class org.apache.http.protocol.BasicHttpContext (http.clj:274)
Now I have to fix Ring, and hope that mmcgrana will accept the fix and deploy to the central repo. That fix might break someone else's code in turn. Oh, the tangled webs we weave.