Cabal and more than one version

I'd like to be able to do something like: if (template-haskell < 2.3) cpp-options: -D TH_THE_YOUNGER else cpp-options: -D TH_THE_ELDER I guess this kind of thing is not possible at present? -- _jsn

On Tue, 2008-11-18 at 01:48 -0800, Jason Dusek wrote:
I'd like to be able to do something like:
if (template-haskell < 2.3) cpp-options: -D TH_THE_YOUNGER else cpp-options: -D TH_THE_ELDER
I guess this kind of thing is not possible at present?
It is possible, in two different ways. The easiest way is that if you're using Cabal-1.6 then it provides cpp macros to test the version number of packages you're using. #if MIN_VERSION_template_haskell(2,3,0) ... #elseif ... #endif The alternative that works back to Cabal-1.2 is to use: flag newer-th ... if flag(newer-th) build-depends: template-haskell >= 2.3 cpp-options: -D TH_THE_ELDER else build-depends: template-haskell < 2.3 cpp-options: -D TH_THE_YOUNGER See also ticket http://hackage.haskell.org/trac/hackage/ticket/209 for a proposal to add syntactic sugar similar to the syntax you first suggested. Duncan

In the ticket, someone says: True though I suspect it looks a bit weird to the uninitiated. We know to read the conditional syntax as an implication constraint which can be applied in either direction but I suspect many people read it in a directed functional way. Does that mean you don't have to actually set 'splitBase' explicitly? -- _jsn

On Tue, 2008-11-18 at 16:53 -0800, Jason Dusek wrote:
In the ticket, someone says:
True though I suspect it looks a bit weird to the uninitiated. We know to read the conditional syntax as an implication constraint which can be applied in either direction but I suspect many people read it in a directed functional way.
Does that mean you don't have to actually set 'splitBase' explicitly?
No, that is the point. You do not have to. The choice for the flag is completely determined automatically by the version of the base package that is chosen. Because in this construct the flag choice is completely determined by another choice by the user/environment (the version of a package) then we do not really need a flag at all. That's why we're considering adding some syntactic sugar for these kinds of common cases. But it really would be just syntactic sugar. The semantics are sufficiently powerful already. Duncan

Duncan Coutts
Jason Dusek wrote:
In the ticket, someone says:
True though I suspect it looks a bit weird to the uninitiated. We know to read the conditional syntax as an implication constraint which can be applied in either direction but I suspect many people read it in a directed functional way.
Does that mean you don't have to actually set 'splitBase' explicitly?
No, that is the point. You do not have to. The choice for the flag is completely determined automatically by the version of the base package that is chosen.
When you say "chosen" is that the same as "detected"? With 6.10, both versions of base are available -- what happens then? The environment chooses the latest one? -- _jsn

On Wed, 2008-11-19 at 02:15 -0800, Jason Dusek wrote:
Duncan Coutts
wrote: Jason Dusek wrote:
In the ticket, someone says:
True though I suspect it looks a bit weird to the uninitiated. We know to read the conditional syntax as an implication constraint which can be applied in either direction but I suspect many people read it in a directed functional way.
Does that mean you don't have to actually set 'splitBase' explicitly?
No, that is the point. You do not have to. The choice for the flag is completely determined automatically by the version of the base package that is chosen.
When you say "chosen" is that the same as "detected"?
No. Each package can only be built against a single version of a dependent package. So chosen really means chosen. It is the single version of the dependent package that we end up building your package against.
With 6.10, both versions of base are available -- what happens then? The environment chooses the latest one?
Good example. So in that case the system (with optional input from the user / package manager) has to choose one of them. Often there will be a constraint from the package so that there will be no real choice. When the choice is not constrained then it is more complicated: * 'rughc Setup configure' and 'cabal configure' use a simple (and occasionally wrong) heuristic to pick the latest version. * 'cabal install' uses a simple constraint solver and some global and local preferences to make the choice. At the moment the global preference is to pick base 3, because many many packages say "build-depends: base >= 3" but in fact fail when built with base-4. So the preference is a kind of patch to keep them building. Duncan

Hi, I'm bringing up an old thread, because it's very relevant to my problem. On Tue, Nov 18, 2008 at 22:30, Duncan Coutts wrote:
On Tue, 2008-11-18 at 01:48 -0800, Jason Dusek wrote:
I'd like to be able to do something like:
if (template-haskell < 2.3) cpp-options: -D TH_THE_YOUNGER else cpp-options: -D TH_THE_ELDER
I guess this kind of thing is not possible at present?
It is possible, in two different ways.
The easiest way is that if you're using Cabal-1.6 then it provides cpp macros to test the version number of packages you're using.
#if MIN_VERSION_template_haskell(2,3,0) ... #elseif ... #endif
The alternative that works back to Cabal-1.2 is to use:
flag newer-th
... if flag(newer-th) build-depends: template-haskell >= 2.3 cpp-options: -D TH_THE_ELDER else build-depends: template-haskell < 2.3 cpp-options: -D TH_THE_YOUNGER
Either I'm doing something wrong or this doesn't work for cabal-install and GHC 6.8.3. I used the "flag newer-th" approach in EMGM: https://svn.cs.uu.nl:12443/viewvc/dgp-haskell/EMGM/tags/emgm-0.2/emgm.cabal?... [...] flag th23 description: Define a CPP flag that enables conditional compilation for template-haskell package version 2.3 and newer. Library [...] build-depends: base >= 3.0 && < 4.0, template-haskell < 2.4 -- Include deriveRep for Loc. This was introduced with -- template-haskell-2.3, included with GHC 6.10. if flag(th23) build-depends: template-haskell >= 2.3 cpp-options: -DTH_LOC_DERIVEREP else build-depends: template-haskell < 2.3 [...] When I run cabal install emgm (with GHC 6.8.3 and either Cabal 1.2 or 1.6), it tries (and fails) to install template-haskell-2.3. That's exactly what I don't want. Any suggestions? Thanks, Sean

On Mon, 2009-02-02 at 13:18 +0100, Sean Leather wrote:
Either I'm doing something wrong or this doesn't work for cabal-install and GHC 6.8.3. I used the "flag newer-th" approach in EMGM:
https://svn.cs.uu.nl:12443/viewvc/dgp-haskell/EMGM/tags/emgm-0.2/emgm.cabal?...
[...]
flag th23 description: Define a CPP flag that enables conditional compilation for template-haskell package version 2.3 and newer.
Library
[...]
build-depends: base >= 3.0 && < 4.0, template-haskell < 2.4
-- Include deriveRep for Loc. This was introduced with -- template-haskell-2.3, included with GHC 6.10. if flag(th23) build-depends: template-haskell >= 2.3 cpp-options: -DTH_LOC_DERIVEREP else build-depends: template-haskell < 2.3
[...]
When I run cabal install emgm (with GHC 6.8.3 and either Cabal 1.2 or 1.6), it tries (and fails) to install template-haskell-2.3. That's exactly what I don't want. Any suggestions?
No immediate workarounds, though you could perhaps try reversing the condition or the default of the flag. Though that might just reverse the problem case. Presumably the template-haskell-2.3 package does not build with ghc-6.8 but fails to correctly specify the version of base or ghc that it requires. If it did then we would have a better chance to get this right. In general this is going to be hard. The solver is not that smart and it deliberately does no backtracking (as a defence against searching too much given that it has no smart methods for pruning the search space). This is just the kind of situation where we need a proper solver which is probably a couple months work. Another possible workaround... If you avoid using the flag hack then the solver would not have to choose so early which version of template-haskell to commit to and it would be able to pick the right version later. Though then you need an alternative method of finding which version of template-haskell you ended up with. You could do it with some custom code in Setup.hs. Duncan

Presumably the template-haskell-2.3 package does not build with ghc-6.8 but fails to correctly specify the version of base or ghc that it requires. If it did then we would have a better chance to get this right.
Yes, this is certainly an issue in general with template-haskell-2.3. How do we fix this?
Another possible workaround...
If you avoid using the flag hack then the solver would not have to choose so early which version of template-haskell to commit to and it would be able to pick the right version later. Though then you need an alternative method of finding which version of template-haskell you ended up with. You could do it with some custom code in Setup.hs.
I don't mind using a different approach. How do I detect which version of template-haskell I'm using in Setup.lhs that is backwords compatible to Cabal 1.2? I would like to support both template-haskell-2.2 and -2.3 by deriving EMGM type representations for it, but the later has the 'Loc' datatype. So, I'm currently using the CPP flag to determine whether 'Loc' is available or not: *#ifdef TH_LOC_DERIVEREP **-- This type is only provided in template-haskell-2.3 (included with GHC 6.10) **-- and up. *$(derive ''Loc) *#endif * Thanks, Sean

On Tue, 2009-02-03 at 10:38 +0100, Sean Leather wrote:
Presumably the template-haskell-2.3 package does not build with ghc-6.8 but fails to correctly specify the version of base or ghc that it requires. If it did then we would have a better chance to get this right.
Yes, this is certainly an issue in general with template-haskell-2.3. How do we fix this?
We patch the .cabal file in the current darcs version so that its fixed in the next release.
Another possible workaround...
If you avoid using the flag hack then the solver would not have to choose so early which version of template-haskell to commit to and it would be able to pick the right version later. Though then you need an alternative method of finding which version of template-haskell you ended up with. You could do it with some custom code in Setup.hs.
I don't mind using a different approach. How do I detect which version of template-haskell I'm using in Setup.lhs that is backwords compatible to Cabal 1.2?
You get access to the LocalBuildInfo which contains the packageDeps, the exact package identifiers. You can find the package you're after and find its version. Then you can do one of two things. You could generate a .h file either during post-conf or pre-build or you could add a cpp option by updating the localPkgDescr in the LocalBuildInfo to add an extra cpp option. It's not necessarily short or pretty, but it should be possible to make it work with Cabal-1.2 and 1.6. Duncan
participants (3)
-
Duncan Coutts
-
Jason Dusek
-
Sean Leather