ghc/cygwin filename resolution issue.

Claus Reinke claus.reinke@talk21.com
Fri, 31 Jan 2003 00:40:13 -0000


>As Simon M says, if you (or anyone else) felt able to write up a
>standalone summary of what the problem is, and what the solution is, I'd love 
>to add it to the GHC FAQ or documentation somewhere.  

Following the worse-is-better approach, here's some text for others
to fiddle with (I'd recommend to keep the result in the GHC FAQ
proper, possibly with a link from the building guide, if necessary).
I've omitted the build-ghc-with-cygwin option, lest readers in search
or solutions rush of to cause themselves even more problems;-).

Cheers,
Claus

Using GHC (and other GHC-compiled executables )with cygwin
================================================

[background]
The cygwin tools aim to provide a unix-style API on top of the windows 
libraries, to facilitate ports of unix software to windows. To this end, they 
introduce a unix-style directory hierarchy under some root directory
(typically / is C:\cygwin\). Moreover, everything built against the cygwin 
API (including the cygwin tools and programs compiled with cygwin's
ghc) will see / as the root of their file system, happily pretending to work
in a typical unix environment, and finding things like /bin and /usr/include
without ever explicitly bothering with their actual location on the windows
system (probably C:\cygwin\bin and C:\cygwin\usr\include).

[the problem]
GHC, by default, no longer depends on cygwin, but is a native windows
program. It is built using mingw, and it uses mingw's ghc while compiling 
your Haskell sources (even if you call it from cygwin's bash), but what 
matters here is that - just like any other normal windows program - neither 
GHC nor the executables it produces are aware of cygwin's pretended 
unix hierarchy. GHC will happily accept either '/' or '\' as path separators, 
but it won't know where to find /home/joe/Main.hs or /bin/bash or the 
like. This causes all kinds of fun when GHC is used from within cygwin's 
bash, or in make-sessions running under cygwin.

[things to do]
0) don't panic!

1) don't use absolute paths in make, configure & co if there is any chance 
  that those might be passed to GHC (or to GHC-compiled programs). Relative
  paths are fine because cygwin tools are happy with them and GHC accepts 
  '/' as path-separator. And relative paths don't depend on where cygwin's
  root directory is located, or on which partition or network drive your source
  tree happens to reside, as long as you 'cd' there first.

2) if you have to use absolute paths (beware of the innocent-looking
  ROOT=`pwd` in makefile hierarchies or configure scripts), cygwin provides
  a tool called 'cygpath' that can convert cygwin's unix-style paths to their
  actual windows-style counterparts. Many cygwin tools actually accept
  absolute windows-style paths (remember, though, that you either need 
  to escape '\' or convert '\' to '/'), so you should be fine just using those 
  everywhere. If you need to use tools that do some kind of path-mangling 
  that depends on unix-style paths (one fun example is trying to interpret ':' 
  as a separator in path lists..), you can still try to convert paths using 
  cygpath just before they are passed to GHC&friends.
  
3) if you don't have cygpath, you probably don't have cygwin and hence
  no problems with it.. unless you want to write one build process for several
  platforms. Again, relative paths are your friend, but if you have to use
  absolute paths, and don't want to use different tools on different platforms,
  you can simply write a short Haskell program to print the current directory
   (thanks to George Russell for this idea): compiled with GHC, this will give 
  you the view of the file system that GHC depends on (which will differ 
  depending on whether GHC is compiled with cygwin's gcc or mingw's
  gcc or on a real unix system..) - that little program can also deal with 
  escaping '\' in paths. Apart from the banner and the startup time, 
  something like this would also do:

  $ echo "Directory.getCurrentDirectory >>= putStrLn . init . tail . show " | ghci

4) panic now.