haskell/cabal

Cabal uses hardcoded not relative path in package descriptors.

Closed this issue · 12 comments

Hi!
When invoking 'cabal install ' cabal executes ghc-pkg several times, in particular executes 'ghc-pkg update - ' passing package descriptors by stdin.

The problem is, that some fields, like 'import-dirs' use hardcoded paths, like:
/home/myuser/local-ghc-installation/lib/x86_64-linux-ghc-7.6.3/testlib-0.1

instead of:
${pkgroot}/testlib-0.1

the same problem occurs with fields haddock-interfaces and haddock-tml, where we could replace the beggining of the path with "${pkgroot}/../../share/doc/ <...>"

This would make the installation of GHC (with packages installed by cabal) movable on Linux boxes.

I think there's another old ticket somewhere on making relocatable packages. Note that there is a lot more to it than just using the ${pkgroot} spec. You need a --prefix-independent configure flag to request that you want it to be relocatable. Then there's a bunch of checks to see if it's possible to be relocatable on this platform with the choice of compiler and libraries (e.g. shared libs vs static). Then there are changes in the code to find data files at runtime etc etc. Lots of little things.

Can we estimate in which cases replacing hardcoded paths by ${pkgroot} is simply safe? If this is simple, implementing this feature would sometimes help a lot - for example making movable ghc Linux tarbars with preinstalled custom global libraries.

IIUC, if my package DB is located in $HOME/.ghc/i386-linux-7.6.3/package.conf.d, that's what $pkgroot will resolve to. How will you refer to files under $HOME/.cabal in a relocatable fashion?

Plese note, that I was talking mainly about global installed libraries. I do not know how to refer to $HOME/.cabal, but maybe reading the appriopriate field from cabal configuration will be enough? I mean - If you've got a library installed in a pkg-db, then when cabal is using it, it knows exactly what pkg-db is using at the moment, so it can easly provide a variable pointing to this pk-db, cannot it?

I think that the same issue applies to the libraries installed with --global - e.g. on Windows, they are installed under %PROGRAMFILES%/Haskell and we need to communicate that location to GHC somehow.

Perhaps we could solve this by adding a --system install location that'd put packages directly into the GHC's system package DB. So on Windows they'd be installed under c:\ghc\... and on Linux under $GHC_DIR/lib/ghc-$VERSION/package.conf.d or somewhere under /usr/lib if GHC is installed globally.

@23Skidoo note that if we support a relocatable feature, that doesn't mean cabal-install has to use it by default, and indeed it wouldn't make a lot of sense for us, given the ~/.cabal ~/.ghc split. Relocatable packages make more sense for exes and for specifically crafted bundles.

It's not right to "opportunistically" use the ${pkgroot} mechanism. The right thing is to specifically request a relocatable package by configuring with a new --prefix-independent flag, and then doing various checks to make sure that it is possible for the chosen configuration. And then one can go and change pkgname_Paths.hs and register using relative paths etc.

@dcoutts

Relocatable packages make more sense for exes and for specifically crafted bundles.

Right, the reason I'm interested is that this feature would make it easier for me to build the HP installer. Right now I simply copy everything from %PROGRAMFILES%/Haskell to c:\ghc\... and then run a script that replaces the absolute paths with ${pkgroot}-based ones in the .conf files.

It'd be nice if I could just use cabal install --system or --prefix-independent instead.

@23Skidoo : I'm doing exactly the same.

@23Skidoo yes, it makes a lot of sense for ghc core or HP binary bundles.

And starting with Setup.hs configure --prefix-independent is the right way to go imho. It declares the intention of the builder, so you can then actually fail with a good error if they're picking some unsupported platform or are using some other config that is incompatible with relocatable builds. You'll notice that there is already some code in Cabal for relocatable packages, though it only supports Hugs iirc, but the main problem with it is that it is "opportunistic", in that it tries to make it relocatable if all the stars align. That's no good because if you want a relocatable package then it never tells you why it couldn't, it just ends up making it absolute. So declare that's what we want and then do the appropriate checks.

For example:

  • does it make sense to use --prefix with --prefix-independent, perhaps not. Perhaps we should say that you have to use cabal copy --destdir=image in such a situation.
  • all other directory flags (--libdir etc) now have to be relative to $prefix (directly or indirectly via other vars). This requires a check on the InstallDirs.
  • the --package-db also has to be relative to $prefix (directly or indirectly via other vars).
  • libs with data files cannot be supported (for ghc at least)
  • the pkgname_paths.hs module will need to be adapted to do relative lookups. This may be a bit tricky on unix but it is possible. It's reasons like this that we may have to say that --prefix-independent just is not supported on all platforms, especially at first. We can enable them as we can check they work.
  • initially we probably cannot use --prefix-independent when building shared libs
  • relocatable shared libs on linux are possible, using the rpath ${ORIGIN} mechanism.
  • have to deal with the issue of running the code inplace (e.g. finding data files, can override via env vars)
  • finally, there is the ${pkgroot} thing for the package registration

@christiaanb: Is this a duplicate of #462? Does PR#2255 implement all or any of the above?

@mietek: I wouldn't say this is a duplicate of #462, but the solution to #462(which #2255 partially implements) does solve the problem described in this issue. However, some of the use-cases described here, such as creating the HP installer are just out of reach because because GHC installer doesn't use/know the --enable-relocatable flag, but more importantly, because of what I said in #2255 (comment):

One (major) flaw in the current implementation (#2255) is that in handles libraries with data-files poorly. One such example would be pandoc. The reason is that data-files are found relative to the bin-dir. This poses two problems:

  1. data-files cannot be located from within ghc binary (ghci, runhaskell, etc.) when the library is installed in:
    • The global database: The ghc binary (which System.Environment.getExecutablePath will resolve to) is located in lib/ghc-<version>/bin, not bin.
    • Any other database: The ghc binary is definitely not prefix relative to any package database other than the global database.
  2. data-files cannot be located by a binary installed in a location that is not prefix-relative to the library.

Problem 2. could be solved by wrapper schell scripts, such as the ghc script in ghc's bin directory. But I wouldn't know how to solve problem 1 other than embedding the data files in the library (http://hackage.haskell.org/package/file-embed)

See #462.