haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.62k stars 694 forks source link

Cabal should support Cabal-version-dependent Setup.hs #319

Closed bos closed 10 years ago

bos commented 12 years ago

(Imported from Trac #326, reported by claus on 2008-08-16)

The manual says about non-standard Setup.hs: "good luck". But there are packages that need non-standard Setup.hs, often just very small ones. And all of them risk breakage when Cabal changes.

The first issue is to specify the dependency on a particular Cabal version (#284).

The next issue is that package authors often know how to write their Setup.hs for different versions of Cabal, but have to pick one or the other. It would be better to have Setup.hs code adapt to as many Cabal versions as possible. Since version mismatch leads to compile errors, that seems to imply either

If I read [Add auto-generated CPP macros for package version testing](http://www.haskell.org/pipermail/cabal-devel/2008-August/003576.html) correctly, that almost provides package version info via CPP. It would only need to provide precise versions instead of lower bounds, and for the Cabal package.
bos commented 12 years ago

(Imported comment by @dcoutts on 2008-08-16)

I'm not sure I understand why exact versions are needed and why testing lower bounds is not enough. Testing multi-component versions in CPP macro language is not very easy.

bos commented 12 years ago

(Imported comment by claus on 2008-08-17)

Replying to @dcoutts:

I'm not sure I understand why exact versions are needed and why testing lower bounds is not enough. Testing multi-component versions in CPP macro language is not very easy.

In this case, there is only one component to version-test: Cabal, as implicitly available in Setup.hs code. Exact versions are needed because later versions of Cabal are highly likely to break the code.

A small example package with that issue is ghc-paths, I think. One version works with ghc head's Cabal (1.5?), another version works with hackage's Cabal (1.4?). So there is code that could be made to work with both, if Cabal provided its version as a CPP macro. But just as the 1.4 version doesn't work with 1.5, so I wouldn't bet on the 1.5 version working with 1.7. Hence the need for exact versions.

bos commented 12 years ago

(Imported comment by @dcoutts on 2008-08-18)

Though one can do:

#if MIN_VERSION_CABAL(1,4,0)
#if MIN_VERSION_CABAL(1,6,0)
-- stuff for 1.6
#else
-- stuff for 1.4
#endif
#endif
bos commented 12 years ago

(Imported comment by claus on 2008-08-18)

shouldn't that be:

#ifdef MIN_VERSION_CABAL
#if MIN_VERSION_CABAL(1,6,0) && !MIN_VERSION_CABAL(1,7,0)
-- stuff for 1.6
#else
-- not supported/not yet tested
#endif
#else
-- stuff for 1.4
#endif
But yes, those macros should help. So much so that it might be good to advertize their existence to library authors/hackage users, to start reducing Setup compile errors.
bos commented 12 years ago

(Imported comment by @dcoutts on 2008-08-18)

We don't make these macros available to Setup.hs scripts and it's not entirely clear that we should as it'd then be much harder to compile the scripts using anything other than cabal-install. For example distro packaging scripts need to be able to compile the Setup.hs scripts.

bos commented 12 years ago

(Imported comment by claus on 2008-08-18)

Ah, I see - the macros are only temporarily available while building. I had assumed that Cabal would generate them permanently for each package, so that not only cabal-install could profit from them.

A CABAL_VERSION macro could just as well be part of the cabal package, without auto-generation, but if cabal doesn't have an include directory yet, I certainly don't insist on a CPP-based solution, as long as we can find something else.

What about the other suggestion? Standardise a format for including the Cabal-version in the Setup file name, and make cabal-install select the right one (that is something even users might manage to do manually, but it'd be nice if automated scripts could handle it as well).

One could even code that up in Haskell, at the expense of interpreting Setup-<version>. However, Cabal should provide that code, and check that the required versions exist, just as it ought to provide a default Setup for build-type Simple.

-- sketch of Cabal-version-dependent Setup:
-- get Cabal version
-- execute Setup-<version>
No CPP, and it can be started without changing Cabal, just standardizing the file name format. Since it is unlikely that the code for getting the Cabal version or for executing processes is going to be stable for long, such a Setup.hs file should really come with Cabal, for a build-type Setup-select or something, hiding the implementation details.
bos commented 12 years ago

(Imported comment by @dcoutts on 2008-08-18)

Replying to claus:

Ah, I see - the macros are only temporarily available while building. I had assumed that Cabal would generate them permanently for each package, so that not only cabal-install could profit from them.

Cabal makes them available while building, a macro for testing the version of each dependency. It's not just cabal-install, it's done in the Cabal lib. I'm not sure what you're suggesting as an alternative, that we install the .h files too? I guess that would let packages that build without using Cabal to use the version macros of packages that were built with Cabal. Is that what you mean? Is that a major advantage?

The problem with using these macros for compiling Setup.hs is that that would only help cabal-install and would actively hinder everyone else. runghc Setup would stop working.

bos commented 12 years ago

(Imported comment by claus on 2008-08-18)

Cabal makes them available while building, a macro for testing the version of each dependency. It's not just cabal-install, it's done in the Cabal lib. I'm not sure what you're suggesting as an alternative, that we install the .h files too? I guess that would let packages that build without using Cabal to use the version macros of packages that were built with Cabal. Is that what you mean? Is that a major advantage?

Yes, I had assumed that the .h files would be installed with the package. Then it would be available to all importers, anytime, not just during building with Cabal. One might think that all Haskell code should be build via Cabal, always, but that isn't true, and Setup.hs seems to be our first exception to that scheme.

The problem with using these macros for compiling Setup.hs is that that would only help cabal-install and would actively hinder everyone else. runghc Setup would stop working.

I don't understand? If I have a pragma in Setup.hs that enables CPP, and there is a macro giving the version number for the installed cabal package that Setup.hs is using, why would runhaskell Setup not work?

bos commented 12 years ago

(Imported comment by @dcoutts on 2008-08-19)

Replying to claus:

I don't understand? If I have a pragma in Setup.hs that enables CPP, and there is a macro giving the version number for the installed cabal package that Setup.hs is using, why would runhaskell Setup not work?

You're right, if we also installed the .h file along with Cabal itself and put a suitable entry into the include-dirs for Cabal's registration then with a CPP pragma and a #include in your Setup.hs it would work for runghc. It would not work for hugs or nhc98 because hugs does not grok the CPP pragma and neither let us specify extra info like include-dirs in the package resistration, so even if they did cpp they would not be able to find the header file.

bos commented 12 years ago

(Imported comment by claus on 2008-08-19)

Replying to @dcoutts:

It would not work for hugs or nhc98 because hugs does not grok the CPP pragma and neither let us specify extra info like include-dirs in the package resistration, so even if they did cpp they would not be able to find the header file.

Interesting. How do hugs and nhc98 survive processing base without CPP and include-dir?

Anyway, that brings us back to a CPP-less approach. Here is that sketch again, this time in code:

import System.IO
import System.Process
import Text.Regex
import System.Exit
import Control.Monad
import System.Directory
die last_words = do
  hPrint stderr last_words
  exitFailure
condition `orElse` action = do
  c <\- condition
  unless c action
main = do
  (_,o,_,_) <\- runInteractiveCommand "ghc-pkg field Cabal version"
  field <\- hGetContents o
  case matchRegex (mkRegex "version: ([0-9.]_)") field of
    Just [version] -> do
      let setup = "Setup-"++version++".hs"
      doesFileExist setup `orElse` die ("can't find version-specific Setup source: "++setup)
      runCommand $ "runhaskell "++setup
    _ -> die $ "can't determine Cabal version: "++field
I'm sure something less inelegant can be hacked up within Cabal, but I can never find what I'm looking for in Distribution._ (in spite of the many pieces of functionality available, it seems they are only really meant to be used in one specific context/order/framework, not in isolation).
bos commented 12 years ago

(Imported comment by guest on 2008-08-19)

I'm also not sure what you mean about nhc98 not specifying info like include-dirs at package registration.

FWIW, nhc98 uses the cabal-file's spec for include-dirs at package-build time, and the whole cabal-file (including this information) is copied to the installed location at registration time. When using the package, hmake/nhc98 could certainly read the include-dirs field and turn it into -Idir command-line options, if that is the correct thing to do.

bos commented 12 years ago

(Imported comment by @dcoutts on 2008-08-20)

Yes, it could be done for nhc98 just as it is done for ghc if the InstalledPackageInfo files were installed. This depends on changes in nhc's build system to provide these files for all the libs that come with nhc98. It's all just work.

tibbe commented 10 years ago

Closing as there's been no activity in years.

We're cleaning up the bug tracker to make it useful again and are thus closing bugs that haven't seen any activity in a long time. Please re-open (or file a new bug) if the problem reappears.

23Skidoo commented 7 years ago

IIUC, this is now fixed with setup-depends.