"模板Haskell + C"错误的解决方法?

Art*_*yom 9 haskell ghc template-haskell

我有以下情况:

  • 库X是C中一些代码的包装器.
  • 库A取决于库X.
  • 库B使用模板Haskell并依赖于库A.

GHC bug#9010使用GHC 7.6无法安装库B. 处理TH时,GHCi会启动并尝试加载库X,这会失败并显示消息

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'
Run Code Online (Sandbox Code Playgroud)

("未知符号"的实际名称因机器而异).

有没有解决这个问题的方法(当然除了"不要使用模板Haskell")?也许库X必须以不同的方式编译,或者有一些方法可以阻止它加载(因为它不应该在代码生成期间调用)?

Rei*_*ton 4

这确实是 7.8 默认切换到动态 GHCi 的主要原因之一。它不是尝试支持每种目标文件格式的每个功能,而是构建动态库并让系统动态加载器处理它们。

尝试使用 g++ 选项进行构建-fno-weak。来自 g++ 手册页:

-fno-弱

不要使用弱符号支持,即使它是由链接器提供的。默认情况下,G++ 将使用可用的弱符号。此选项仅用于测试,最终用户不应使用;它将导致劣质代码并且没有任何好处。此选项可能会在 G++ 的未来版本中删除。

还有另一个问题__dso_handle。我发现您至少可以通过链接定义该符号的文件来加载库并显然可以工作。我不知道这个 hack 是否会导致任何问题。

所以在 X.cabal 添加

if impl(ghc < 7.8)
    cc-option: -fno-weak
    c-sources: cbits/dso_handle.c
Run Code Online (Sandbox Code Playgroud)

其中cbits/dso_handle.c包含

void *__dso_handle;
Run Code Online (Sandbox Code Playgroud)