gpt4 book ai didi

haskell - 如何将Haskell编译成静态库?

转载 作者:行者123 更新时间:2023-12-03 01:35:58 25 4
gpt4 key购买 nike

嘿,我正在学习 Haskell,我有兴趣使用它来制作静态库,以便在 Python 和 C 中使用。经过一番谷歌搜索后,我发现如何让 GHC 输出共享对象,但它动态地依赖于 GHC 的库。在 GHC 中编译生成的 ELF 是动态依赖的,仅依赖于 C 库,并且大小略低于 1 MB - 它已与 GHC 的库静态链接。对于共享对象如何以及是否可以实现这一点?

当前状态示例:

$ ghc --make -dynamic -shared -fPIC foo.hs -o libfoo.so
$ ldd libfoo.so
linux-vdso.so.1 => (0x00007fff125ff000)
libHSbase-4.2.0.2-ghc6.12.3.so => /usr/lib/ghc-6.12.3/base-4.2.0.2/libHSbase-4.2.0.2-ghc6.12.3.so (0x00007f7d5fcbe000)
libHSinteger-gmp-0.2.0.1-ghc6.12.3.so => /usr/lib/ghc-6.12.3/integer-gmp-0.2.0.1/libHSinteger-gmp-0.2.0.1-ghc6.12.3.so (0x00007f7d5faac000)
libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007f7d5f816000)
libHSghc-prim-0.2.0.0-ghc6.12.3.so => /usr/lib/ghc-6.12.3/ghc-prim-0.2.0.0/libHSghc-prim-0.2.0.0-ghc6.12.3.so (0x00007f7d5f591000)
libHSffi-ghc6.12.3.so => /usr/lib/ghc-6.12.3/libHSffi-ghc6.12.3.so (0x00007f7d5f383000)
libc.so.6 => /lib/libc.so.6 (0x00007f7d5f022000)
/lib/ld-linux-x86-64.so.2 (0x00007f7d60661000)

$ ghc foo.hs
$ ldd foo
linux-vdso.so.1 => (0x00007fff2d3ff000)
libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007f50014ec000)
libm.so.6 => /lib/libm.so.6 (0x00007f5001269000)
librt.so.1 => /lib/librt.so.1 (0x00007f5001061000)
libdl.so.2 => /lib/libdl.so.2 (0x00007f5000e5d000)
libc.so.6 => /lib/libc.so.6 (0x00007f5000afc000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007f50008df000)
/lib/ld-linux-x86-64.so.2 (0x00007f5001759000)

如果我尝试使用(不带“-dynamic”)编译它:

$ ghc --make -shared -fPIC foo.hs -o libfoo.so
Linking libfoo.so ...
/usr/bin/ld: foo.o: relocation R_X86_64_32S against `stg_CAF_BLACKHOLE_info' can not be used when making a shared object; recompile with -fPIC
foo.o: could not read symbols: Bad value
collect2: ld returned 1 exit status

当谷歌搜索时,我发现了关于整个问题的一些信息 - 它可能来自于 GHC 是以特定方式编译的事实(动态/静态?),因此静态链接是不可能的。如果这是真的,ELF 二进制文件怎么可能是静态链接的?

无论如何,我希望有人能够阐明这一点,因为大量的谷歌搜索给我留下了比开始时更多的问题。

非常感谢。

最佳答案

规范的方式是这样的:

  1. 导出函数(通过 FFI)以由外部程序初始化 RTS(运行时系统)
  2. 导出您想要在 Haskell 中实现的实际函数

手册的以下部分对此进行了描述:[1] [2]

另一方面,您可以尝试这篇博文中描述的技术(顺便说一下,这是我的):

http://mostlycode.wordpress.com/2010/01/03/shared-haskell-so-library-with-ghc-6-10-4-and-cabal/

它归结为创建一个小 C 文件,该文件在加载库后立即自动调用。它应该链接到库中。

#define CAT(a,b) XCAT(a,b)
#define XCAT(a,b) a ## b
#define STR(a) XSTR(a)
#define XSTR(a) #a

#include

extern void CAT (__stginit_, MODULE) (void);

static void library_init (void) __attribute__ ((constructor));
static void
library_init (void)
{
/* This seems to be a no-op, but it makes the GHCRTS envvar work. */
static char *argv[] = { STR (MODULE) ".so", 0 }, **argv_ = argv;
static int argc = 1;

hs_init (&argc, &argv_);
hs_add_root (CAT (__stginit_, MODULE));
}

static void library_exit (void) __attribute__ ((destructor));
static void
library_exit (void)
{
hs_exit ();
}

编辑:描述此技术的原始博客文章是这样的:http://weblog.haskell.cz/pivnik/building-a-shared-library-in-haskell/

关于haskell - 如何将Haskell编译成静态库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5131182/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com