[Haskell-cafe] Cabal doesn't reset the search-path when invoking GHC: potential subtleties
Phil Ruffwind
rf at rufflewind.com
Wed Sep 10 21:35:52 UTC 2014
It seems that even when invoked via Cabal, GHC will look in the local
directory *first* and then in the list of modules and dependencies supplied by
Cabal. I was aware of this behavior subconsciously but I hadn't realized the
implications until now.
Normally, it's not a big problem, other than for the occasional situation
where I forget to add those local modules to 'other-modules'. This would
cause 'cabal sdist' to generate an incomplete package, even though 'cabal
build && cabal install' works just fine!
But there are more subtle "bugs": it breaks if the executable and library
share the same directory, but the library has some hidden modules stashed away
in a different directory! The conditions required to reproduce this is
somewhat difficult to explain, so let me show a simple example:
1. Make a Cabal package:
-- ./foo.cabal
name: foo
version: 0.0.0.0
build-type: Simple
cabal-version: >=1.8
library
exposed-modules: Exposed
other-modules: Hidden
build-depends: base
hs-source-dirs: ., hidden
executable main
main-is: Main.hs
build-depends: base, foo
2. Add a library with two modules at the given paths:
-- ./Exposed.hs
module Exposed where
import Hidden
-- ./hidden/Hidden.hs
module Hidden where
3. Add an executable:
-- ./Main.hs
module Main where
import Exposed
main = return ()
4. Now run `cabal build`. This would cause an error message akin to:
> Could not find module Hidden
The problem is that despite the dependency on the library `foo` being
specified in Cabal, GHC still chose the *local* `Exposed` module over the
`Exposed` module in the library `foo`. This means when it tries to recompile
the `Exposed` module, it is unaware that `Hidden` is located in another
directory.
The error message is unhelpful because it doesn't point to the actual cause of
the problem and led me astray thinking that something was wrong with my Cabal
configuration.
In the end, the problem has to do with GHC deciding to look up packages in
locations outside Cabal's control. There are many other ways to trigger this
problem -- the above was only one that I just happened to run into.
For now, a workaround would be to use `-i` with all the executables to avoid
this subtle issue in the future.
RF
More information about the Haskell-Cafe
mailing list