9

I've got the following situation:

  • Library X is a wrapper over some code in C.
  • Library A depends on library X.
  • Library B uses Template Haskell and depends on library A.

GHC bug #9010 makes it impossible to install library B using GHC 7.6. When TH is processed, GHCi fires up and tries to load library X, which fails with a message like

Loading package charsetdetect-ae-1.0 ... linking ... ghc:
~/.cabal/lib/x86_64-linux-ghc-7.6.3/charsetdetect-ae-1.0/
libHScharsetdetect-ae-1.0.a: unknown symbol `_ZTV15nsCharSetProber'

(the actual name of the “unknown symbol” differs from machine to machine).

Are there any workarounds for this problem (apart from “don't use Template Haskell”, of course)? Maybe library X has to be compiled differently, or there's some way to stop it from loading (as it shouldn't be called during code generation anyway)?

Emily
  • 2,577
  • 18
  • 38
  • Add `-lyourlibname` option to ghci where libyourlibname.so is the library X wraps. – n. m. could be an AI Oct 19 '14 at 09:55
  • @n.m. There's no `libyourlibname.so` – all code that is wrapped by library X is contained in library X itself. – Emily Oct 19 '14 at 10:21
  • Hm, it looks like you're right. The symbol is unknown, not undefined. – n. m. could be an AI Oct 19 '14 at 12:26
  • They say ghci and cabal don't work but `ghc --make` does. You may want to try that. Alternatively, refactor the code so that your TH stuff doesn't depend on anything that contains C code. Pass any wrapped C APIs to the functions in your TH module as parameters. – n. m. could be an AI Oct 19 '14 at 12:36
  • @n.m. It has to be built with cabal (as all 3 libraries are on Hackage and people generally install stuff from Hackage using cabal). As for the 2nd suggestion – ghc tries to load the library (and fails) on *any* module using TH; moreover, the library with TH doesn't depend on the C library directly. – Emily Oct 19 '14 at 13:40
  • I'm not quite sure what you mean. Does any compilation involving TH fail with cabal, even for an empty module with no dependencies? I find it hard to believe. It doesn't matter whether the dependence is direct or indirect, so you would need to refactor B such that it does not depend on A, or refactor A such that it does not depend on X. – n. m. could be an AI Oct 19 '14 at 13:55
  • @n.m. Sorry for confusion! No, I merely meant that GHC fails immediately when it compiles any of modules from B which have TH enabled, even those which don't depend on any of modules from A. – Emily Oct 19 '14 at 14:41
  • It looks like cabal tries to load A (and X) whether a particular module in B needs it or not, and fails. One would need to remove the dwpendency from the .cabal file. – n. m. could be an AI Oct 19 '14 at 14:52
  • 1
    This actually appears to be a "Template Haskell + C++" bug, as _ZTV15nsCharSetProber is a weak symbol, which the GHCi linker doesn't understand (https://ghc.haskell.org/trac/ghc/ticket/3333). – Reid Barton Oct 19 '14 at 17:11

1 Answers1

4

This is really one of the main reasons that 7.8 switched to dynamic GHCi by default. Rather than try to support every feature of every object file format, it builds dynamic libraries and lets the system dynamic loader handle them.

Try building with the g++ option -fno-weak. From the g++ man page:

-fno-weak

Do not use weak symbol support, even if it is provided by the linker. By default, G++ will use weak symbols if they are available. This option exists only for testing, and should not be used by end-users; it will result in inferior code and has no benefits. This option may be removed in a future release of G++.

There is another issue with __dso_handle. I found that you can at least get the library to load and apparently work by linking in a file which defines that symbol. I don't know whether this hack will cause anything to go wrong.

So in X.cabal add

if impl(ghc < 7.8)
    cc-option: -fno-weak
    c-sources: cbits/dso_handle.c

where cbits/dso_handle.c contains

void *__dso_handle;
Community
  • 1
  • 1
Reid Barton
  • 14,951
  • 3
  • 39
  • 49