这不是一个完整的答案,但大部分都是这样。这不是太复杂:
Haskell 运行时只是一个可以在 GHC 安装中找到的库。在我的 Mac 上,它位于 $PREFIX/lib/ghc-$VERSION/rts 中,其中 $PREFIX 是 GHC 的安装前缀(例如 /、/usr、/usr/local 等——编译器可执行文件应该是 $PREFIX/bin/ghc)。您需要使用其中一个共享库(对我来说,它们被称为.dylibs)。但是,Haskell 运行时和已编译的 Haskell 代码都不包含 main。 GHC 生成一个存根 C 文件:
#include "Rts.h"
extern StgClosure ZCMain_main_closure;
int main(int argc, char *argv[])
{
RtsConfig __conf = defaultRtsConfig;
__conf.rts_opts_enabled = RtsOptsSafeOnly;
__conf.rts_opts_suggestions = true;
__conf.rts_hs_main = true;
return hs_main(argc,argv,&ZCMain_main_closure,__conf);
}
其中ZCMain_main_closure 指的是用Haskell 编写的main 动作,hs_main 指的是来自RTS 的符号。你需要用clang将它编译成bitcode,用ghc、llvm-link将Haskell代码编译成一个大的.bc,然后把它交给GraalVM的lli。将上面的c_main.c 中的内容放在Main.hs 中:
main = putStrLn "Hello, World!"
编译链接:
$ clang -emit-llvm -I/usr/local/lib/ghc-8.6.5/include -c c_main.c
# Change -I path as needed
$ ghc -fllvm -keep-llvm-files -S Main.hs
$ llvm-link Main.ll c_main.bc -o prog.bc
现在,在一个完美的世界中,以下方法会起作用:
$ lli --lib /usr/local/lib/ghc-8.6.5/rts/libHSrts-ghc8.6.5.dylib \
--lib /usr/local/lib/ghc-8.6.5/base-4.12.0.0/libHSbase-4.12.0.0-ghc8.6.5.dylib \
prog.bc
# Maybe you need more of the base libraries
# It's kind of hard to test because it doesn't work, anyway
但是,这不起作用,因为库具有相互依赖关系。 base,主要用 Haskell 编写,需要 RTS。 RTS 挂钩到 base 以与 Haskell 通信(例如,有异常)。 GraalVM 尝试使用RTLD_NOW 一次一个地处理dlopen 它们,它尝试并未能严格解析符号。它需要使用RTLD_LAZY。这在 GraalVM 中应该是一个很容易解决的问题。