|
Hi, folks -
I'm sure we are all familiar with the phrase "cabal dependency hell" at this point, as the number of projects on Hackage that are intended to hack around the problem slowly grows.
I am currently undergoing a fresh visit to that unhappy realm, as I try to rebuild some of my packages to see if they work with the GHC 7.6 release candidate. A substantial number of the difficulties I am encountering are related to packages specifying upper bounds on their dependencies. This is a recurrent problem, and its source lies in the recommendations of the PVP itself (problematic phrase highlighted in bold):
When publishing a Cabal package, you should ensure that your dependencies in the build-depends field are accurate. This means specifying not only lower bounds, but also upper bounds on every dependency. I understand that the intention behind requiring tight upper bounds was good, but in practice this has worked out terribly, leading to depsolver failures that prevent a package from being installed, when everything goes smoothly with the upper bounds relaxed. The default response has been for a flurry of small updates to packages in which the upper bounds are loosened, thus guaranteeing that the problem will recur in a year or less. This is neither sensible, fun, nor sustainable.
In practice, when an author bumps a version of a depended-upon package, the changes are almost always either benign, or will lead to compilation failure in the depending-upon package. A benign change will obviously have no visible effect, while a compilation failure is actually better than a depsolver failure, because it's more informative.
This leaves the nasty-but-in-my-experience-rare case of runtime failures caused by semantic changes. In these instances, a downstream package should reactively add an upper bound once a problem is discovered.
I propose that the sense of the recommendation around upper bounds in the PVP be reversed: upper bounds should be specified only when there is a known problem with a new version of a depended-upon package.
_______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
On Wed, Aug 15, 2012 at 12:38 PM, Bryan O'Sullivan <[hidden email]> wrote:
> I propose that the sense of the recommendation around upper bounds in the > PVP be reversed: upper bounds should be specified only when there is a known > problem with a new version of a depended-upon package. This argument precisely captures my feelings on this subject. I will be removing upper bounds next time I make releases of my packages. -- Johan _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
On Wed, Aug 15, 2012 at 3:57 PM, Johan Tibell <[hidden email]> wrote:
So we are certain that the rounds of failures that led to their being *added* will never happen again? brandon s allbery [hidden email] wandering unix systems administrator (available) (412) 475-9364 vm/sms _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
On Wed, Aug 15, 2012 at 1:02 PM, Brandon Allbery <[hidden email]> wrote:
Of course I am sure that problems will arise as a result of recommending that upper bounds be added reactively; didn't I say as much? I expect that to be a much lesser problem than the current situation.
_______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Brandon Allbery
On Wed, Aug 15, 2012 at 1:02 PM, Brandon Allbery <[hidden email]> wrote:
> So we are certain that the rounds of failures that led to their being > *added* will never happen again? It would be useful to have some examples of these. I'm not sure we had any when we wrote the policy (but Duncan would know more), but rather reasoned our way to the current policy by saying that things can theoretically break if we don't have upper bounds, therefore we need them. -- Johan _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
Would it make sense to have a known-to-be-stable-though soft upper bound added proactively, and a known-to-break-above hard bound added reactively, so people can loosen gracefully as appropriate? On Aug 15, 2012 1:45 PM, "Johan Tibell" <[hidden email]> wrote:
On Wed, Aug 15, 2012 at 1:02 PM, Brandon Allbery <[hidden email]> wrote: _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
On Wed, Aug 15, 2012 at 1:50 PM, David Thomas <[hidden email]> wrote:
_______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
> it's usual for the existing upper bounds to refer to versions that don't exist at the time of writing (and hence can't be known to be stable).
Well, known to be stable given semantic versioning, then. http://semver.org/ On Wed, Aug 15, 2012 at 1:55 PM, Bryan O'Sullivan <[hidden email]> wrote: > On Wed, Aug 15, 2012 at 1:50 PM, David Thomas <[hidden email]> > wrote: >> >> Would it make sense to have a known-to-be-stable-though soft upper bound >> added proactively, and a known-to-break-above hard bound added reactively, >> so people can loosen gracefully as appropriate? > > I don't think so. It adds complexity, but more importantly it's usual for > the existing upper bounds to refer to versions that don't exist at the time > of writing (and hence can't be known to be stable). > _______________________________________________ > Haskell-Cafe mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/haskell-cafe > _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
As someone who recurrently is nudging a large number of maintainers every major ghc release to bump their bounds, I favor the no upper bounds approach! :)
plus the whole improving ecosystem of build bot tools which play nice with cabal et al that are cropping up mean that "in principal" we could debug missing upper bounds via sort of temporal bisecting over the "event stream" of maximum available versions at a given time to sort that. (but that piece isn't that important)
more pragmatically, cabal when used with hackage doesn't let you override version constraints, it just lets you add additional constraints. This makes sense if we assume that the library author is saying "things will definitely break if you violate them", but in practice upper bounds are made up guesstimation.
YES, its presumably semantic versioning doesn't create a problem, but with the hackage eco system, when dealing with intelligently engineering libs that are regularly maintained, version upper bounds create more problems than than solve. just my two cents. (yes yes yes, please drop upper bounds!) cheers -Carter On Wed, Aug 15, 2012 at 5:04 PM, Michael Blume <[hidden email]> wrote:
_______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Bryan O'Sullivan
I definitely agree!
http://www.reddit.com/r/haskell/comments/x4knd/what_is_the_reason_for_haskells_cabal_package/ L. On Wed, Aug 15, 2012 at 12:38:33PM -0700, Bryan O'Sullivan wrote: > Hi, folks - > > I'm sure we are all familiar with the phrase "cabal dependency hell" at this > point, as the number of projects on Hackage that are intended to hack around > the problem slowly grows. > > I am currently undergoing a fresh visit to that unhappy realm, as I try to > rebuild some of my packages to see if they work with the GHC 7.6 release > candidate. > > A substantial number of the difficulties I am encountering are related to > packages specifying upper bounds on their dependencies. This is a recurrent > problem, and its source lies in the recommendations of the PVP itself > (problematic phrase highlighted in bold): > > > When publishing a Cabal package, you should ensure that your dependencies > in the build-depends field are accurate. This means specifying not only > lower bounds, but also upper bounds on every dependency. > > > I understand that the intention behind requiring tight upper bounds was good, > but in practice this has worked out terribly, leading to depsolver failures > that prevent a package from being installed, when everything goes smoothly with > the upper bounds relaxed. The default response has been for a flurry of small > updates to packages in which the upper bounds are loosened, thus guaranteeing > that the problem will recur in a year or less. This is neither sensible, fun, > nor sustainable. > > In practice, when an author bumps a version of a depended-upon package, the > changes are almost always either benign, or will lead to compilation failure in > the depending-upon package. A benign change will obviously have no visible > effect, while a compilation failure is actually better than a depsolver > failure, because it's more informative. > > This leaves the nasty-but-in-my-experience-rare case of runtime failures caused > by semantic changes. In these instances, a downstream package should reactively > add an upper bound once a problem is discovered. > > I propose that the sense of the recommendation around upper bounds in the PVP > be reversed: upper bounds should be specified only when there is a known > problem with a new version of a depended-upon package. > _______________________________________________ > Haskell-Cafe mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/haskell-cafe -- Lorenzo Bolla http://lbolla.info _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Johan Tibell-2
On Wed, Aug 15, 2012 at 4:44 PM, Johan Tibell <[hidden email]> wrote:
Upper package versions did not originally exist, and nobody wanted them. You can see the result in at least half the packages on Hackage: upper versions came in when base got broken up, and when bytestring was merged into base --- both of which caused massive breakage that apparently even the people around at the time and involved with it no longer remember.
I'm not going to argue the point though; ignore history and remove them if you desire. brandon s allbery [hidden email] wandering unix systems administrator (available) (412) 475-9364 vm/sms _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
no one is disputing that there are conditional changes in dependencies depending on library versions.
an interesting intermediate point would be have a notion of "testing with " constraints in cabal and engineering cabal to support a "--withTestedConstraints" to have a simple composable way of handling constructing build plans.
at the end of the day, its an engineering problem coupled with a social factors problem. Those are hard :) On Wed, Aug 15, 2012 at 5:44 PM, Brandon Allbery <[hidden email]> wrote:
_______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Carter Schonwald
Upper bounds are a bit of a catch-22 when it comes to library authors evolving
their APIs: 1) If library clients aren't encouraged to specify which version of the exported API they target, then changing APIs can lead to opaque compile errors (without any information about which API is intended). This could lead the client to need to search for the appropriate version of the library. If library clients are encouraged to specify which versions of the exported API they target, then changing the API breaks all of the clients. There are a couple of hacky ways to do #1 without having the errors be so opaque 1) Start a tradition of commenting the cabal dependencies with the version of the package that worked for the author. 2) Build in support for these "known good" versions into cabal, perhaps generated on "sdist"release, or with a particular build flag. (they don't need to be stored in the .cabal file) 3) Attempt to post-process GHC error messages to guess when the issue might be caused by the package version being different according to the PVP. This could work alright for scoping but wouldn't work well for type errors (which matter more) I like the idea of doing automated upper-bound-determination! That would be very convenient. It's a bit tricky though - should tests be included? I think the most ideal solution is to attack the core problem: things break when dependencies change their interface. This is pretty expected in the development world at large, but I think that Haskell can do better. The main idea is that package developers should be free to update their API as they realize that new names or interfaces are better. Currently there's the problem that the APIs that actually get used subsequently stagnate due to fear of breakage. The solution that I think makes the most sense is to start exporting modules which express the old interface in terms of the new. What's interesting about this is that most non-semantic changes to things other than ADTs and typeclasses can already be expressed in plain Haskell code. This idea, among other things, inspired the "instance templates" proposal, which is somewhat related to superclass default instances. With this language extension, it would be possible to express compatibility layers for instance definitions, something that is impossible with Superclass Default Instances. https://github.com/mgsloan/instance-templates I've also got a start on a utility for extracting API signatures from packages. Currently it just pretty prints the API in a fashion that attempts to be amenable to textual diffing: https://github.com/mgsloan/api-compat/ https://github.com/mgsloan/api-compat/blob/master/examples/diagrams-core.api.diff The intent is to make the tool interactive, giving the user a chance to let the tool know which exports / modules have been renamed. After the user provides this information, it should be possible to generate almost all of the compatibility code. In order to make it convenient to use these compatibility modules, we'd want to have some cabal- invoked code generation that would generate proxy modules that re-export the appropriate version. This could all happen in a separate hs-source-dir. The next step in this toolchain is something that's very hard to do nicely, because it can change code layout: automated rewriting of user code to target the new version (this is equivalent to "inlining" the compatibility module definitions). However, even a tool that would take you to all of the places that need changing would be invaluable. Wouldn't it be excellent, if the Haskell eco-system managed something that no other language affords?: * Automatic refactoring to target new API versions * Expression of these refactorings in the language itself * Rigorous, structured documentation of inter-version changes. This'd also provide a nice place to put haddocks with further change information. -Michael On Wed, Aug 15, 2012 at 2:34 PM, Carter Schonwald <[hidden email]> wrote: > As someone who recurrently is nudging a large number of maintainers every > major ghc release to bump their bounds, I favor the no upper bounds > approach! :) > > plus the whole improving ecosystem of build bot tools which play nice with > cabal et al that are cropping up mean that "in principal" we could debug > missing upper bounds via sort of temporal bisecting over the "event stream" > of maximum available versions at a given time to sort that. (but that piece > isn't that important) > > more pragmatically, cabal when used with hackage doesn't let you override > version constraints, it just lets you add additional constraints. This makes > sense if we assume that the library author is saying "things will definitely > break if you violate them", but in practice upper bounds are made up > guesstimation. > > YES, its presumably semantic versioning doesn't create a problem, but with > the hackage eco system, when dealing with intelligently engineering libs > that are regularly maintained, version upper bounds create more problems > than than solve. > > just my two cents. (yes yes yes, please drop upper bounds!) > > cheers > -Carter > > > On Wed, Aug 15, 2012 at 5:04 PM, Michael Blume <[hidden email]> wrote: >> >> > it's usual for the existing upper bounds to refer to versions that don't >> > exist at the time of writing (and hence can't be known to be stable). >> >> Well, known to be stable given semantic versioning, then. >> >> http://semver.org/ >> >> On Wed, Aug 15, 2012 at 1:55 PM, Bryan O'Sullivan <[hidden email]> >> wrote: >> > On Wed, Aug 15, 2012 at 1:50 PM, David Thomas <[hidden email]> >> > wrote: >> >> >> >> Would it make sense to have a known-to-be-stable-though soft upper >> >> bound >> >> added proactively, and a known-to-break-above hard bound added >> >> reactively, >> >> so people can loosen gracefully as appropriate? >> > >> > I don't think so. It adds complexity, but more importantly it's usual >> > for >> > the existing upper bounds to refer to versions that don't exist at the >> > time >> > of writing (and hence can't be known to be stable). >> > _______________________________________________ >> > Haskell-Cafe mailing list >> > [hidden email] >> > http://www.haskell.org/mailman/listinfo/haskell-cafe >> > >> >> _______________________________________________ >> Haskell-Cafe mailing list >> [hidden email] >> http://www.haskell.org/mailman/listinfo/haskell-cafe > > > > _______________________________________________ > Haskell-Cafe mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/haskell-cafe > _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Carter Schonwald
On Wed, Aug 15, 2012 at 6:46 PM, Carter Schonwald <[hidden email]> wrote:
no one is disputing that there are conditional changes in dependencies depending on library versions. Indeed. But the ghc release that split up base broke cabalised packages with no warning to users until they failed to compile. Upper bounds were put in place to avoid that kind of breakage in the future.
brandon s allbery [hidden email] wandering unix systems administrator (available) (412) 475-9364 vm/sms _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
On 16 August 2012 08:55, Brandon Allbery <[hidden email]> wrote:
> On Wed, Aug 15, 2012 at 6:46 PM, Carter Schonwald > <[hidden email]> wrote: >> >> no one is disputing that there are conditional changes in dependencies >> depending on library versions. > > > Indeed. But the ghc release that split up base broke cabalised packages > with no warning to users until they failed to compile. Upper bounds were > put in place to avoid that kind of breakage in the future. There's also the case where people blindly put something like "base < 10" in the .cabal file, and then it broke on the next GHC release. This happend with ghc-core-0.5: it completely failed to build with base-4 (and because cabal-install kept defaulting packages to use base-3 I think a lot of people missed cases like this and blindly thought it worked). I like having upper bounds on version numbers... right up until people abuse them. -- Ivan Lazar Miljenovic [hidden email] http://IvanMiljenovic.wordpress.com _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Bryan O'Sullivan
On 16 August 2012 03:38, Bryan O'Sullivan <[hidden email]> wrote:
> Hi, folks - > > I'm sure we are all familiar with the phrase "cabal dependency hell" at this > point, as the number of projects on Hackage that are intended to hack around > the problem slowly grows. > > I am currently undergoing a fresh visit to that unhappy realm, as I try to > rebuild some of my packages to see if they work with the GHC 7.6 release > candidate. Likewise ... > A substantial number of the difficulties I am encountering are related to > packages specifying upper bounds on their dependencies. This is a recurrent > problem, and its source lies in the recommendations of the PVP itself > (problematic phrase highlighted in bold): I think part of the problem might be that some packages (like bytestring, transformers?) have had their major version number incremented even despite being backwards-compatible. Perhaps there are incompatible changes, but most of the cabal churn I've seen recently has involved incrementing the bytestring upper bound to <0.11 without requiring any code changes to modules using Data.ByteString. IMO it'd be better to include a separate versioning entry like libtool's version-info, consisting of Current:Revision:Age (http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html), and leave the published "version" for human, marketing purposes. I remember discussing this with Duncan at ICFP last year, and he suggested that the existing PVP is equivalent to the libtool scheme in that the major release should only be incremented if backwards-compatibility breaks. However I think people also expect to use the published version as a kind of marketing, to indicate that the project has reached some milestone or stability, or is part of some larger, separately versioned group of packages (eg. new compiler or platform release). The PVP pretty much ensures that incrementing a major version for such reasons is going to break your package for all its users. Conrad. _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Ivan Lazar Miljenovic
On Wed, Aug 15, 2012 at 9:19 PM, Ivan Lazar Miljenovic
<[hidden email]> wrote: > On 16 August 2012 08:55, Brandon Allbery <[hidden email]> wrote: >> Indeed. But the ghc release that split up base broke cabalised packages >> with no warning to users until they failed to compile. Upper bounds were >> put in place to avoid that kind of breakage in the future. > > I like having upper bounds on version numbers... right up until people > abuse them. I also tend to favor having upper bounds. Obviously they impose a cost, but it's not clear to me at all that getting rid of them is a better tradeoff. I've had projects that I put aside for awhile only to come back and discover that they would no longer build because I hadn't put upper bounds on all my package dependencies. With no upper bounds, a package might not be very likely to break for incremental version bumps, but eventually it *will* break. And when it does it's a huge pain to get it building again. If I have put effort into making a specific version of my package work properly today, I want it to always work properly in the future (assuming that everyone obeys the PVP). I don't think it's unreasonable that some activation energy be required to allow one's project to work with a new version of some upstream dependency. Is that activation energy too high right now? Almost definitely. But that's a tool problem, not a problem with the existence of upper bounds themselves. One tool-based way to help with this problem would be to add a flag to Cabal/cabal-install that would cause it to ignore upper bounds. (Frankly, I think it would also be great if Cabal/cabal-install enforced upper version bounds automatically if none were specified.) Another approach that has been discussed is detecting dependencies that are only used internally[1], and I'm sure there are many other possibilities. In short, I think we should be moving more towards purely functional builds that reduce the chance that external factors will break things, and it seems like removing upper version bounds is a step in the other direction. [1] http://cdsmith.wordpress.com/2011/01/21/a-recap-about-cabal-and-haskell-libraries/ _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
On Wed, Aug 15, 2012 at 11:02 PM, MightyByte <[hidden email]> wrote:
Ignore, or at least treat them as being like flags... if the versions don't converge with them, start relaxing them and retrying, then print a warning about the versions it slipped and attempt the build.
That said, I'd be in favor of moving toward something based on ABI versioning instead; package versions as used by the PVP are basically a manual switch emulating that. It's not generally done because other parts of the toolchain (notably ld's shared object versioning) don't support it, but given that Cabal has greater control over the build process for Haskell programs it would be worth exploring having Cabal deal with it. (This is not something you can do with existing C or C++ toolchains; the smarts would need to be in make.)
brandon s allbery [hidden email] wandering unix systems administrator (available) (412) 475-9364 vm/sms _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Conrad Parker
On Thu, Aug 16, 2012 at 5:38 AM, Conrad Parker <[hidden email]> wrote:
In general, I've been taking the approach recently that we have two classes of packages: some (like transformers and bytestring) have mostly-stable APIs, and most code I write only relies on those APIs. If I'm just using Data.ByteString for the ByteString type and a few functions like readFile and map, it's highly unlikely that the next version will introduce some breaking change. In those cases, I've been leaving off the upper bound entirely.
For other packages that haven't yet stabilized, I've still been keeping the upper bound. In many cases, even that isn't necessary. I've tried removing the upper bounds on those as well, but I almost always end up getting someone filing a bug report that I left off some upper bound and therefore a compile failed.
I agree with Bryan's argument, but I'd like to keep consistency for most packages on Hackage. If the community goes in this direction, I'll go along too. Michael
_______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
In reply to this post by Michael Sloan
On Wed, Aug 15, 2012 at 03:54:04PM -0700, Michael Sloan wrote: > Upper bounds are a bit of a catch-22 when it comes to library authors evolving > their APIs: > > 1) If library clients aren't encouraged to specify which version of the > exported API they target, then changing APIs can lead to opaque compile > errors (without any information about which API is intended). This could > lead the client to need to search for the appropriate version of the > library. Having the version number A.B.*, than most packages seem to mostly increase B or lower parts of the version number. If an upper bound is missing, than cabal could use any package in the range A.*.* . If an author wants to make breaking changes to his API, than he could indicate this by increasing A. I've nothing against your proposal, I just don't think that it will be done that soon. Greetings, Daniel _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
| Powered by Nabble | Edit this page |
