Haskell 动态库
Haskell dynamic library
http://www.vex.net/~trebla/haskell/so.xhtml描述了如何编译共享库。
关于编译命令:
ghc -O2 -dynamic -shared -fPIC -o libEval.so Eval.hs hsbracket.c -lHSrts-ghc7.6.3
它说:
(Could you omit -dynamic to request static libraries of other packages? Not really, they were not generated with -fPIC. In particular it is illegal on x86_64.)
为什么会这样?在没有 libHS* 依赖项的情况下编译共享库应该怎么做?
既然Kaiko私下联系我解答,不妨post这里...
简短版
通过省略 -dynamic,您将尝试将所有静态 .a 库和 link 它们放入一个巨大的 .so 文件中。那些 .a 库本身是在没有 -fPIC 的情况下构建的。所有以 .so 文件结束的代码都必须使用 -fPIC 构建(至少在 ELF x86-64 上)。因此在这种情况下 linking 会失败,因为需要 -fPIC 但库不是用 -fPIC 构建的。
长版
不同的构建方式之间存在一些差异
静态和动态库:
- 它是构建为 .a 存档还是构建为 .so(或 .dll/.dynlib)对象?
- 它是否使用-fPIC 构建,位置无关代码?
- 外部符号是希望在同一个 DSO 中还是在外部 DSO 中?
原则上,这些东西的许多不同组合是有意义的
但实际上只有少数被使用。
在 Linux (ELF) 上,有两种构建库的标准方法,
全静态和全动态。在完全静态的方法中答案
上面的问题 1、2、3 是:.a 存档,没有 -fPIC,相同的 DSO。在里面
完全动态的方法答案是:.so lib、-fPIC、外部 DSO。
现在你想做的不一样了。您希望构建所有库
作为 .a 文件,但带有 -fPIC 和预期位于
同一个 DSO。这会让你 link 所有这些库一起进入
一个巨大的共享库。所以关键的区别是使用-fPIC,
因为在 ELF(特别是 x86_64)上,代码最终出现在共享库中
必须使用 -fPIC 构建。
相比之下,在 Windows 上,GHC 可以做你想做的,link 所有
Haskell 库(包括 RTS 等)到一个巨大的共享库中
(.dll)。这是因为在 Windows 上(不像 ELF),位置无关
代码无关紧要。所以在 Windows 上,可以采取静态
图书馆和link他们进入一个大的共享图书馆。
原则上这在 Linux 上也应该是可能的,如果所有
Haskell 库是静态构建的,但带有 -fPIC。这不是
默认值,这是您不能省略 -dynamic 的直接原因
在这种情况下 Linux.
所以原则上,可以尝试重建 ghc 和核心库
使用 -fPIC 标志从源代码开始,然后查看它是否可以忽略
-dynamic 和 link 一切都在一个巨大的共享库中。
是的,使用 -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
http://www.vex.net/~trebla/haskell/so.xhtml描述了如何编译共享库。
关于编译命令:
ghc -O2 -dynamic -shared -fPIC -o libEval.so Eval.hs hsbracket.c -lHSrts-ghc7.6.3
它说:
(Could you omit -dynamic to request static libraries of other packages? Not really, they were not generated with -fPIC. In particular it is illegal on x86_64.)
为什么会这样?在没有 libHS* 依赖项的情况下编译共享库应该怎么做?
既然Kaiko私下联系我解答,不妨post这里...
简短版
通过省略 -dynamic,您将尝试将所有静态 .a 库和 link 它们放入一个巨大的 .so 文件中。那些 .a 库本身是在没有 -fPIC 的情况下构建的。所有以 .so 文件结束的代码都必须使用 -fPIC 构建(至少在 ELF x86-64 上)。因此在这种情况下 linking 会失败,因为需要 -fPIC 但库不是用 -fPIC 构建的。
长版
不同的构建方式之间存在一些差异 静态和动态库:
- 它是构建为 .a 存档还是构建为 .so(或 .dll/.dynlib)对象?
- 它是否使用-fPIC 构建,位置无关代码?
- 外部符号是希望在同一个 DSO 中还是在外部 DSO 中?
原则上,这些东西的许多不同组合是有意义的 但实际上只有少数被使用。
在 Linux (ELF) 上,有两种构建库的标准方法, 全静态和全动态。在完全静态的方法中答案 上面的问题 1、2、3 是:.a 存档,没有 -fPIC,相同的 DSO。在里面 完全动态的方法答案是:.so lib、-fPIC、外部 DSO。
现在你想做的不一样了。您希望构建所有库 作为 .a 文件,但带有 -fPIC 和预期位于 同一个 DSO。这会让你 link 所有这些库一起进入 一个巨大的共享库。所以关键的区别是使用-fPIC, 因为在 ELF(特别是 x86_64)上,代码最终出现在共享库中 必须使用 -fPIC 构建。
相比之下,在 Windows 上,GHC 可以做你想做的,link 所有 Haskell 库(包括 RTS 等)到一个巨大的共享库中 (.dll)。这是因为在 Windows 上(不像 ELF),位置无关 代码无关紧要。所以在 Windows 上,可以采取静态 图书馆和link他们进入一个大的共享图书馆。
原则上这在 Linux 上也应该是可能的,如果所有 Haskell 库是静态构建的,但带有 -fPIC。这不是 默认值,这是您不能省略 -dynamic 的直接原因 在这种情况下 Linux.
所以原则上,可以尝试重建 ghc 和核心库 使用 -fPIC 标志从源代码开始,然后查看它是否可以忽略 -dynamic 和 link 一切都在一个巨大的共享库中。
是的,使用 -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