Haskell动态库

时间:2015-01-07 08:45:09

标签: haskell compilation ghc

http://www.vex.net/~trebla/haskell/so.xhtml描述了如何编译共享库。

关于编译命令:

ghc -O2 -dynamic -shared -fPIC -o libEval.so Eval.hs hsbracket.c -lHSrts-ghc7.6.3

它说:

  

(你能否省略-dynamic请求其他软件包的静态库?不是真的,它们不是用-fPIC生成的。特别是在x86_64上它是非法的。)

为什么会这样?如果没有libHS *依赖项,应该怎么做才能编译共享库?

2 个答案:

答案 0 :(得分:10)

由于Kaiko私下与我联系以获得答案,不妨在此发布...

短版

通过省略-dynamic,您将尝试获取所有静态.a库并将它们链接到一个大型.so文件中。那些。libs本身是在没有-fPIC的情况下构建的。最终在.so文件上的所有代码必须使用-fPIC构建(至少在ELF x86-64上)。因此,在这种情况下链接会失败,因为-fPIC是必需的,但是libs不是用-fPIC构建的。

长版

在不同的建筑方式之间有一些不同的东西 静态和动态库:

  1. 是构建为.a存档还是.so(或.dll / .dynlib)对象?
  2. 是否使用-fPIC,位置无关代码构建?
  3. 外部符号是否应位于同一DSO或外部DSO中?
  4. 原则上,这些东西的许多不同组合都是有意义的 但实际上只使用了少数。

    在Linux(ELF)上,​​有两种构建库的标准方法, 完全静态和完全动态。在完全静态的方法答案 问题1,2,3上面是:.a存档,没有-fPIC,相同的DSO。在里面 完全动态的方法答案是:.so lib,-fPIC,外部DSO。

    现在你想要做的是与众不同。您希望构建所有库 as .a文件,但是-fPIC和外部符号应该在 同样的DSO。然后,这将允许您将所有这些库链接到一起 一个巨大的共享库。所以关键的区别是使用-fPIC, 因为在ELF(特别是x86_64)代码中最终存在于共享库中 必须使用-fPIC构建。

    相比之下,在Windows上,GHC可以完全按照你想要的方式进行链接 Haskell库(包括RTS等)成为一个庞大的共享库 (.dll文件)。这是因为在Windows上(与ELF不同),位置无关 代码没关系。所以在Windows上,一个人可以采取静态 库并将它们链接到一个大的共享库。

    原则上,这应该也可以在Linux上实现,如果全部的话 Haskell库是静态构建的,但使用-fPIC。这不是 默认,这就是你不能省略-dynamic的直接原因 在这种情况下在Linux上。

    原则上,人们可以尝试重建ghc和核心库 从源代码使用-fPIC标志,然后查看它是否可以省略 -dynamic并将所有内容链接到一个巨大的共享库中。

答案 1 :(得分:4)

是的,使用-fPIC进行编译有帮助。这是如何做到的。

ghc-7.8.4/mk/build.mk

 SRC_HC_OPTS     = -H64m -O 
 EXTRA_HC_OPTS   = -fPIC    
 SRC_CC_OPTS     = -fPIC -O 
 GhcStage1HcOpts = -fasm -O0
 GhcStage2HcOpts = -fasm -O0
 GhcLibHcOpts    = -fasm -O2
 GhcLibWays      = v dyn    
 DYNAMIC_GHC_PROGRAMS = YES 
 DYNAMIC_BY_DEFAULT   = NO  
 SplitObjs            = NO  
 HADDOCK_DOCS         = NO  
 BUILD_DOCBOOK_HTML   = NO  
 BUILD_DOCBOOK_PS     = NO  
 BUILD_DOCBOOK_PDF    = NO  

编译ghc:

export EXTRA_CONFIGURE_OPTS="--disable-library-profiling --enable-shared"

使用-fPIC构建cabal包:

cabal install --enable-shared --ghc-option=-fPIC text

测试文件foo.hs(Data.Text用于查看cabal包是否也有效):

import Foreign.C as C 
import Data.Text as T
import Data.Text.Foreign as T 
foreign export ccall   len :: CString -> IO CInt 
len t = C.peekCString t >>= return . CInt . fromIntegral . T.length . T.pack  
main = return ()

动态构建:

ghc -dynamic --make foo.hs

动态混合静态构建(不确定是否需要pthread,但它说明了如何添加动态链接):

ghc -fPIC -shared --make -o libfoo.so \
 -optl-Wl,-Bstatic -lHSrts -lCffi \
   -lHSbase-4.7.0.2 -lHSinteger-gmp-0.5.1.0 -lHSghc-prim-0.3.1.0 \
-optl-Wl,-Bdynamic -lpthread foo.hs
相关问题