
Cabal defines MIN_VERSION_* macros that allow CPP in a Haskell source file to get information about the versions of the packages that module is being compiled against. Unfortunately, these macros are not available when not compiling with cabal, so packages must either 1. Insist on cabal compilation. This is not very friendly to developers. 2. Make "pessimistic" assumptions, assuming that all the packages are old. This makes it annoying to test new features while also leading to compilation or run-time failures when packages have removed it changed features. 3. Attempt to guess the version based on the GHC version. This works reasonably well for base, ghc-prim, containers, etc., but not so well/at all for others. Would there be some way to get GHC itself to provide these macros to all modules that request CPP? David Feuer

I've been meaning to ask about this as well. It also forces tools like ghc-mod and hdevtools to be cabal-aware, which is an unnecessary source of complexity IMO. GHC certainly has enough information to generate these macros, as it knows which packages (and versions) it's compiling against. I think it's just a matter of adding the logic. I would love to see the MIN_VERSION macros moved to GHC. Eric On Fri, Sep 25, 2015, at 09:06, David Feuer wrote:
Cabal defines MIN_VERSION_* macros that allow CPP in a Haskell source file to get information about the versions of the packages that module is being compiled against. Unfortunately, these macros are not available when not compiling with cabal, so packages must either
1. Insist on cabal compilation. This is not very friendly to developers. 2. Make "pessimistic" assumptions, assuming that all the packages are old. This makes it annoying to test new features while also leading to compilation or run-time failures when packages have removed it changed features. 3. Attempt to guess the version based on the GHC version. This works reasonably well for base, ghc-prim, containers, etc., but not so well/at all for others.
Would there be some way to get GHC itself to provide these macros to all modules that request CPP?
David Feuer _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

I've run into this issue, too. Post a feature request! I can't imagine it's too hard to implement.
Richard
On Sep 25, 2015, at 12:18 PM, Eric Seidel
I've been meaning to ask about this as well. It also forces tools like ghc-mod and hdevtools to be cabal-aware, which is an unnecessary source of complexity IMO.
GHC certainly has enough information to generate these macros, as it knows which packages (and versions) it's compiling against. I think it's just a matter of adding the logic.
I would love to see the MIN_VERSION macros moved to GHC.
Eric
On Fri, Sep 25, 2015, at 09:06, David Feuer wrote:
Cabal defines MIN_VERSION_* macros that allow CPP in a Haskell source file to get information about the versions of the packages that module is being compiled against. Unfortunately, these macros are not available when not compiling with cabal, so packages must either
1. Insist on cabal compilation. This is not very friendly to developers. 2. Make "pessimistic" assumptions, assuming that all the packages are old. This makes it annoying to test new features while also leading to compilation or run-time failures when packages have removed it changed features. 3. Attempt to guess the version based on the GHC version. This works reasonably well for base, ghc-prim, containers, etc., but not so well/at all for others.
Would there be some way to get GHC itself to provide these macros to all modules that request CPP?
David Feuer _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

On 2015-09-25 at 20:48:52 +0200, Richard Eisenberg wrote:
I've run into this issue, too. Post a feature request! I can't imagine it's too hard to implement.
For the current external CPP we'll probably have to create a temporary file with the definitions (just like cabal does) to -include (as afaik you can't easily pass function macros via `-D` to cpp). However, Anthony has mentioned he's working on an embeddable CPP impl over at https://www.reddit.com/r/haskell/comments/3m1wcs/call_for_nominations_haskel... which would allow to keep the currently in-scope MIN_VERSION_...() definitions in-memory w/o a temporary file. Finally, Cabal would have to be adapted to wrap the definitions with `#ifndef`s (or omit those altogether when calling a recent enough GHC)

On Fri, Sep 25, 2015 at 12:18 PM, Eric Seidel
I've been meaning to ask about this as well. It also forces tools like ghc-mod and hdevtools to be cabal-aware, which is an unnecessary source of complexity IMO.
This would certainly be nice, but... GHC certainly has enough information to generate these macros, as it
knows which packages (and versions) it's compiling against.
It knows at some point, but it doesn't necessarily know before parsing the module, at which point it is too late. I can have two versions of a package A, and two other packages B and C that depend on different versions of A, and depending on whether a module M uses package B or package C, M will see different versions of package A automatically. This is all slightly magical, and I have to say I don't entirely understand how GHC decides which versions to expose in general, but that's how GHC works today and it's quite convenient. GHC could provide MIN_VERSION_* macros for packages that have had their versions specified with -package or similar flags (which is how Cabal invokes GHC). That would go only a small way towards the original goals though. (Also, I wonder how MIN_VERSION_* fits into a Backpack world...) Regards, Reid Barton

Excerpts from Reid Barton's message of 2015-09-25 12:36:48 -0700:
It knows at some point, but it doesn't necessarily know before parsing the module, at which point it is too late. I can have two versions of a package A, and two other packages B and C that depend on different versions of A, and depending on whether a module M uses package B or package C, M will see different versions of package A automatically. This is all slightly magical, and I have to say I don't entirely understand how GHC decides which versions to expose in general, but that's how GHC works today and it's quite convenient.
Well, this is half true. The main "problem" is that GHC is actually a lot more flexible than Cabal's model allows: Cabal enforces that for any package, there is only one version of it in a program. But GHC can link any combination of packages (in GHC 7.8, it could link one instance of a package per package name and version; in GHC 7.10, it can link arbitrary instances together as long as they have distinct version names.) But I don't think this is a problem...
GHC could provide MIN_VERSION_* macros for packages that have had their versions specified with -package or similar flags (which is how Cabal invokes GHC). That would go only a small way towards the original goals though.
This is exactly what the MIN_VERSION_* macros should do, and you can generalize it to work even without -package: you get macros for EXPOSED packages which are available for import. This says *nothing* about the transitive dependencies of the packages you're depending on, but it's more reasonable to have "one package, one version" invariant, because having multiple versions of the package exposed would cause a module name to be ambiguous (and unusable.)
(Also, I wonder how MIN_VERSION_* fits into a Backpack world...)
We have to support version bounds for BC, so... as well as BC can be :) Edward

On Fri, Sep 25, 2015 at 4:09 PM, Edward Z. Yang
Excerpts from Reid Barton's message of 2015-09-25 12:36:48 -0700:
GHC could provide MIN_VERSION_* macros for packages that have had their versions specified with -package or similar flags (which is how Cabal invokes GHC). That would go only a small way towards the original goals though.
This is exactly what the MIN_VERSION_* macros should do, and you can generalize it to work even without -package: you get macros for EXPOSED packages which are available for import. This says *nothing* about the transitive dependencies of the packages you're depending on, but it's more reasonable to have "one package, one version" invariant, because having multiple versions of the package exposed would cause a module name to be ambiguous (and unusable.)
Oh, I see. I had always assumed that GHC had some kind of solver to try to pick compatible versions of packages, but having done some experiments, I see that it always picks the newest exposed version of each direct dependency. So we can indeed define MIN_VERSION_* macros in accordance with the newest exposed version of each package. There are still some edge cases, notably: if package foo reexports the contents of some modules from package bar, and the API of these modules changes between two versions of package bar, then you cannot reliably use MIN_VERSION_bar to detect these API changes in a module that imports the reexports from package foo (since the newest installed foo might not be built against the newest installed bar). In the more restrictive Cabal model, you can reliably do this of course. So it could break in an existing project. However this kind of situation (where the API of a package depends on the version of its dependencies) should hopefully be fairly rare in practice. Regards, Reid Barton

Hi all, I've implemented this: https://phabricator.haskell.org/D1349 Cheers, Edward Excerpts from Reid Barton's message of 2015-09-25 15:15:09 -0700:
On Fri, Sep 25, 2015 at 4:09 PM, Edward Z. Yang
wrote: Excerpts from Reid Barton's message of 2015-09-25 12:36:48 -0700:
GHC could provide MIN_VERSION_* macros for packages that have had their versions specified with -package or similar flags (which is how Cabal invokes GHC). That would go only a small way towards the original goals though.
This is exactly what the MIN_VERSION_* macros should do, and you can generalize it to work even without -package: you get macros for EXPOSED packages which are available for import. This says *nothing* about the transitive dependencies of the packages you're depending on, but it's more reasonable to have "one package, one version" invariant, because having multiple versions of the package exposed would cause a module name to be ambiguous (and unusable.)
Oh, I see. I had always assumed that GHC had some kind of solver to try to pick compatible versions of packages, but having done some experiments, I see that it always picks the newest exposed version of each direct dependency. So we can indeed define MIN_VERSION_* macros in accordance with the newest exposed version of each package.
There are still some edge cases, notably: if package foo reexports the contents of some modules from package bar, and the API of these modules changes between two versions of package bar, then you cannot reliably use MIN_VERSION_bar to detect these API changes in a module that imports the reexports from package foo (since the newest installed foo might not be built against the newest installed bar). In the more restrictive Cabal model, you can reliably do this of course. So it could break in an existing project. However this kind of situation (where the API of a package depends on the version of its dependencies) should hopefully be fairly rare in practice.
Regards, Reid Barton
participants (6)
-
David Feuer
-
Edward Z. Yang
-
Eric Seidel
-
Herbert Valerio Riedel
-
Reid Barton
-
Richard Eisenberg