Solving GHC iconv problems on OS X 10.6
A problem that has plagued my GHC installation for a while is that whenever I tried to install any non-trivial package I would get a horrible link error like this:
Undefined symbols:
"_iconv_close", referenced from:
_hs_iconv_close in libHSbase-4.3.1.0.a(iconv.o)
(maybe you meant: _hs_iconv_close)
"_iconv_open", referenced from:
_hs_iconv_open in libHSbase-4.3.1.0.a(iconv.o)
(maybe you meant: _hs_iconv_open)
"_iconv", referenced from:
_hs_iconv in libHSbase-4.3.1.0.a(iconv.o)
(maybe you meant: _hs_iconv_open, _hs_iconv_close , _hs_iconv )
"_locale_charset", referenced from:
_localeEncoding in libHSbase-4.3.1.0.a(PrelIOUtils.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
The reason for this is a combination of several factors:
-
The base library that comes with the GHC binary distribution wants to link against the standard Mac iconv
-
I have installed MacPorts libiconv, which renames the function that is named iconv_open in the standard iconv to libiconv_open
-
The Haskell library being installed by cabal depends transitively on some library that was built with something like
extra-lib-dirs: /opt/local/lib
, which causes-L/opt/local/lib
to be passed to the linker -
The linker’s
-L/opt/local/lib
option occurs before-L/usr/lib
, so the linker prefers to link against the MacPorts libiconv instead of the system one
In my case, it was the Haskell readline wrapper that was causing /opt/local/lib
to be pulled in. I had to link the Haskell readline against MacPorts readline because the standard Mac libreadline
is actually libeditline
, which is almost-but-not-quite compatible and misses some crucial features.
There are several ways to fix the problem:
-
Perhaps you don’t really need the MacPorts
libiconv
. In this case, you can stop it from being used by just doingport deactivate libiconv
. This is the route I took. -
Perhaps it’s OK to link this particular library against the system libraries in preference to the MacPorts one. In this case, you can configure the package with
cabal configure --extra-lib-dir=/usr/lib
, so/usr/lib
is searched before the MacPorts directory. This may fail if the package that needed-L/opt/local/lib
requires a MacPorts version of some library that is also present in/usr/lib
, though. -
You could build GHC yourself and link it against the MacPorts library versions. This is not for the faint-hearted, but if the version of GHC you need is in MacPorts I imagine that you can just do
port install ghc
I’m glad I’ve finally got this sorted out. If you are still having trouble, you might find some helpful information in the threads that finally helped me to overcome the issue and prompted this writeup.