Cabal: bindir/libdir/datadir

While I was away last week I hacked into Cabal support for bindir/libdir/datadir, as previously discussed on this list. However, while doing it I changed my mind about the design so thought I'd run it past the list. The problem with bindir/libdir/datadir is that they are specified as absolute pathnames, but in reality most of the time they will be relative to (i.e. subdirectories of) prefix. Specifying them with absolute pathnames is inconvenient because: - The "setup copy" command already has --copy-prefix, and it would need additional arguments --copy-bindir, --copy-libdir etc. if bindir and friends were absoluate paths (actually, I don't know why we have --copy-prefix, when we should really have a --copy-to that is prepended to the existing prefix, that would eliminate the need for --copy-bindir etc.). - On Windows and systems that support querying the pathname of a running binary, we want to support prefix-independent installs, such that a binary can find its files by only knowing the directory layout under $prefix, not the value of prefix itself. If bindir/libdir/datadir are relative to prefix, we can do this. However, specifying bindir/libdir/datadir with absolute pathnames is desirable because: + It's what autoconf does + If the Cabal package is implemented using autoconf+make, then --bindir can be passed direct to ./configure (but implementing the appropriate impedence matching for relative paths isn't hard either). In the end I plumped for relative pathnames, but I renamed the options: --bindirrel=<dir> --libdirrel=<dir> --datadirrel=<dir> --libexecdirrel=<dir> How can the package itself find out what these paths are? As discussed previously, Cabal generates a file Paths.hs-inc containing prefix = "<dir>" binDirRel = "<dir>" libDirRel = "<dir>" ... etc ... which can be #included into Haskell source. Additionally I have the function: getPrefix :: FilePath{-binDirRel-} -> IO (Maybe FilePath) which figures out prefix when called from a binary installed in $prefix/$bindirrel. If it returns Nothing, then you can fall back to the hard-coded value of prefix from Paths.hs-inc. With these changes I've Cabalised Alex (Happy & Haddock to follow). Please shout if you object to the design in any way. I plan to write a section for the documentation describing all this. There's one thing I'm not sure about yet: the default $libdirrel on Unix systems is lib/<pkgid>/<compiler>, eg. lib/pkg-0.2/ghc-6.4, and you might want to change just the "lib" bit, eg. to get lib64/pkg-0.2/ghc-6.4. It's annoying to have to specify the <pkgid> and <compiler> when Cabal knows them, so we might want a simple substitution syntax, such as --libdirrel=lib64/%p/%c. Sound reasonable? We might also want a simple way in the .cabal file to specify some files to be installed in $datadir (I think someone suggested this before). It's quite annoying to do it with hooks. Cheers, Simon

On Thu, Oct 06, 2005 at 11:29:30AM +0100, Simon Marlow wrote:
While I was away last week I hacked into Cabal support for bindir/libdir/datadir, as previously discussed on this list. However, while doing it I changed my mind about the design so thought I'd run it past the list.
The problem with bindir/libdir/datadir is that they are specified as absolute pathnames, but in reality most of the time they will be relative to (i.e. subdirectories of) prefix. [...] In the end I plumped for relative pathnames, but I renamed the options:
--bindirrel=<dir> --libdirrel=<dir> --datadirrel=<dir> --libexecdirrel=<dir> [...] There's one thing I'm not sure about yet: the default $libdirrel on Unix systems is lib/<pkgid>/<compiler>, eg. lib/pkg-0.2/ghc-6.4, and you might want to change just the "lib" bit, eg. to get lib64/pkg-0.2/ghc-6.4. It's annoying to have to specify the <pkgid> and <compiler> when Cabal knows them, so we might want a simple substitution syntax, such as --libdirrel=lib64/%p/%c. Sound reasonable?
Is there a reason not to use --libdir=%prefix/lib/%package/%compiler/ by default, thus making it easy to give either relative or absolute paths? Thanks Ian

On Thu, Oct 06, 2005 at 11:29:30AM +0100, Simon Marlow wrote:
- The "setup copy" command already has --copy-prefix, and it would need additional arguments --copy-bindir, --copy-libdir etc. if bindir and friends were absoluate paths (actually, I don't know why we have --copy-prefix, when we should really have a --copy-to that is prepended to the existing prefix, that would eliminate the need for --copy-bindir etc.).
We did have that for a while, but someone objected to it: http://www.haskell.org//pipermail/cvs-libraries/2005-January/003175.html

2005/10/6, Simon Marlow
--bindirrel=<dir> --libdirrel=<dir> --datadirrel=<dir> --libexecdirrel=<dir>
bindirrel, libdirrel, ... looks a little bit verbose. Why not just bindir/libdir?
How can the package itself find out what these paths are? As discussed previously, Cabal generates a file Paths.hs-inc containing
prefix = "<dir>" binDirRel = "<dir>" libDirRel = "<dir>" ... etc ...
which can be #included into Haskell source. Additionally I have the function:
getPrefix :: FilePath{-binDirRel-} -> IO (Maybe FilePath)
which figures out prefix when called from a binary installed in $prefix/$bindirrel. If it returns Nothing, then you can fall back to the hard-coded value of prefix from Paths.hs-inc.
What does the argument of getPrefix mean? Is it the --bindirrel value? With this semantic I should write something like this each time: getDataDir :: IO FilePath getDataDir = do mb_path <- getPrefix bindir case mb_path of Just path -> return (path ++ datadir) Nothing -> return (prefix ++ datadir) I think that is better to add these templates to Paths.hs-inc. The prefix constant doesn't make sense under Windows. The program shouldn't assume that it is installed at any specific place. Paths.hs-inc should contain: getBinDir, getLibDir and getDataDir functions where under Unix they should return any hard coded value while under Windows they should compute the real value. I am worried about the meaning of these directories for the library packages. Under Unix the getDataDir will return any constant value, so that all executables which are linked to the given library will share the same data files. Under Windows if datadir is relative to the executable directory then each application will need its own copy of the shared files. It is even tricky to compute datadir for libraries under Windows. There will be two getDataDir functions. One in the Paths.hs-inc for the library and second for the executable to which the library is linked. The getDataDir in the library should know the bindir value specified for the executable in order to work properly. Instead of this I think that the right place for the library specific data files is: C:\Program Files\Common Files\<package> This might sense for Unix too. For some libraries it might be prefered to use /etc/<package>, so the datadir isn't necessary relative to the prefix. Cheers, Krasimir

On Thu, Oct 06, 2005 at 11:29:30AM +0100, Simon Marlow wrote:
[...] How can the package itself find out what these paths are? As discussed previously, Cabal generates a file Paths.hs-inc containing
prefix = "<dir>" binDirRel = "<dir>" libDirRel = "<dir>" ... etc ...
which can be #included into Haskell source. Additionally I have the function:
getPrefix :: FilePath{-binDirRel-} -> IO (Maybe FilePath)
which figures out prefix when called from a binary installed in $prefix/$bindirrel. If it returns Nothing, then you can fall back to the hard-coded value of prefix from Paths.hs-inc.
Can you show the client code to find data files under any system and compiler?
There's one thing I'm not sure about yet: the default $libdirrel on Unix systems is lib/<pkgid>/<compiler>, eg. lib/pkg-0.2/ghc-6.4, and you might want to change just the "lib" bit, eg. to get lib64/pkg-0.2/ghc-6.4. It's annoying to have to specify the <pkgid> and <compiler> when Cabal knows them, so we might want a simple substitution syntax, such as --libdirrel=lib64/%p/%c. Sound reasonable?
There's a difference between the package libdir's you're talking about (e.g. $prefix/lib/$PackageId/$CompilerId) and --libdir in autoconf (default $prefix/lib). You couldn't easily generate the options to configure from *dirrel. But do we really need an option to specify the package libdir, or just --libdir (in the autoconf sense)? "lib64/%p/%c" is easier than the full thing, but it still exposes Cabal's placement policy to lots of installers. Similarly bindir, datadir, libexecdir and maybe includedir. There would be no problem with generalizing the autoconf options, though, say to allow substitutions (e.g. of prefix). Of course I'm being Unix-centric. I've seen a couple of proposals for layouts on Windows, and am unsure which is preferred.
We might also want a simple way in the .cabal file to specify some files to be installed in $datadir (I think someone suggested this before). It's quite annoying to do it with hooks.
Yes indeed.
participants (4)
-
Ian Lynagh
-
Krasimir Angelov
-
Ross Paterson
-
Simon Marlow