如何将 Haskell 库与 Rust 项目静态链接?

Smo*_*key 7 haskell ffi rust

到目前为止,我\xe2\x80\x99ve 还没有将 Haskell 库链接到 Rust 项目。我\xe2\x80\x99ve 有很多错误,最新的是recompile with -fPICfor ghc.

\n

我\xe2\x80\x99已经设法获得动态链接\xe2\x80\x94的功能示例,但无法静态链接它。

\n

现在附上我当前的设置:

\n
    \n
  1. 构建.rs

    \n
    fn main() {\n    println!("cargo:rustc-link-search=native=deps");\n    println!("cargo:rustc-link-lib=static=tesths");\n}\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
  3. src/main.rs

    \n
    extern "C" {\n    pub fn addTwo(x: i32) -> i32;\n    pub fn init();\n    pub fn fin();\n}\n\nfn main() {\n    println!("Hello, world!");\n}\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
  5. src/haskell/Lib.hs

    \n
    module Lib where\n\nimport Foreign.C.Types\n\naddTwo :: CInt -> CInt\naddTwo = (2 + )\n\nforeign export ccall addTwo :: CInt -> CInt\n
    Run Code Online (Sandbox Code Playgroud)\n
  6. \n
  7. cwrapper.c

    \n
    #include <HsFFI.h>\n#ifdef __GLASGOW_HASKELL__\n#include "Lib_stub.h"\n#endif\n#include <stdio.h>\n\nvoid init(void) {\n  static char *argv[] = {"libhs.so", 0}, **argv_ = argv;\n  static int argc = 1;\n\n  hs_init(&argc, &argv_);\n}\n\nvoid fin(void) { hs_exit(); }\n
    Run Code Online (Sandbox Code Playgroud)\n
  8. \n
\n

我用 编译#4 ghc -c -static -lHSrts -lffi cwrapper.c,得到cwrapper.o. 同样,我ghc -c -static -fPIC -lffi Lib.hs也使用 #3 进行编译并获取目标代码。

\n

完成后,我将继续将这两个文件存档ar rcs libtesths.a Lib.o cwrapper.o

\n

cargo build

\n
note: /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x29): undefined reference to `newCAF\'\n          /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x39): undefined reference to `stg_bh_upd_frame_info\'\n          /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x48): undefined reference to `base_ForeignziCziTypes_zdfNumCInt_closure\'\n          /usr/bin/ld: deps/libtesths.a(Lib.o):(.text+0x4f): undefined reference to `stg_ap_p_info\'\n\xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n

我\xe2\x80\x99 有一种预感,libHSrts 不是\xe2\x80\x99t 由于某种原因被静态链接。

\n

更新

\n

我遵循 Shepmaster\xe2\x80\x99s 的建议并成功制作了一个工作示例。但我\xe2\x80\x99m 现在与我的 Rust 执行程序链接时遇到问题。

\n

我使用 stack 和ghc-options: -staticlib -stubdir .c-sources: cwrapper.c构建。当我尝试使用以下命令构建 Rust 项目时cargo rustc \xe2\x80\x94 -C relocation-model=static

\n
/usr/bin/ld: deps/liba.a(Type.o): in function `integerzmwiredzmin_GHCziIntegerziType_zdwplusBigNatWord_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_zdwplusBigNatWord_info+0x128): undefined reference to `__gmpn_add_1\'\n/usr/bin/ld: deps/liba.a(Type.o): in function\n`integerzmwiredzmin_GHCziIntegerziType_zdwminusBigNatWord_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_zdwminusBigNatWord_info+0xdf): undefined reference to `__gmpn_sub_1\'\n/usr/bin/ld: deps/liba.a(Type.o): in function `integerzmwiredzmin_GHCziIntegerziType_complementInteger_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_complementInteger_info+0x138): undefined reference to `__gmpn_sub_1\'\n/usr/bin/ld: deps/liba.a(Type.o): in function `integerzmwiredzmin_GHCziIntegerziType_zdwtimesBigNatWord_info\'\n(.text.integerzmwiredzmin_GHCziIntegerziType_zdwtimesBigNatWord_info+0x158): undefined reference to `__gmpn_mul_1\'\n
Run Code Online (Sandbox Code Playgroud)\n

还提到了一个wrappers.o. 任何帮助表示赞赏。

\n

更新2

\n

我也gmp通过设置build.rs链接解决了问题。libgmp不过,我现在有一个不同的问题。

\n
\nnote: /usr/bin/ld: deps/libhssource.a(Lib.o): in function `testFFI\':\n          (.text+0x88fd): multiple definition of `testFFI\'; deps/libhssource.a(Lib.o):(.text+0x1b66): first defined here\n          /usr/bin/ld: deps/libhssource.a(cwrapper.o): in function `init\':\n          cwrapper.c:(.text+0x0): multiple definition of `init\'; deps/libhssource.a(cwrapper.o):cwrapper.c:(.text+0x0): first defined here\n          /usr/bin/ld: deps/libhssource.a(cwrapper.o): in function `fin\':\n          cwrapper.c:(.text+0x20): multiple definition of `fin\'; deps/libhssource.a(cwrapper.o):cwrapper.c:(.text+0x1a): first defined here\n          collect2: error: ld returned 1 exit status\n
Run Code Online (Sandbox Code Playgroud)\n

更新3

\n

这是完成此任务的最终构建命令:

\n
cargo rustc -- -C relocation-model=static -Clink-arg=-Wl,--allow-multiple-definition\n
Run Code Online (Sandbox Code Playgroud)\n

使用RUSTFLAGS将导致构建崩溃,因为它使用静态重定位模型构建所有依赖项,这在我的情况下无法为 crate \xe2\x80\x94 工作 \xe2\x80\x99 rustversion。它会报告recompile with -fPIC错误。

\n

She*_*ter 6

我立即编译了 Haskell 库和 C shim,并传递了-staticlib标志:

ghc -c -staticlib Lib.hs cwrapper.c -o libtesths.a
Run Code Online (Sandbox Code Playgroud)

然后我调用这些函数:

extern "C" {
    pub fn addTwo(x: i32) -> i32;
    pub fn init();
    pub fn fin();
}

fn main() {
    unsafe {
        init();
        println!("{}", addTwo(40));
        fin();
    }
}
Run Code Online (Sandbox Code Playgroud)
% cargo run -q
42
Run Code Online (Sandbox Code Playgroud)

这对我在使用 GHC 8.10.7 的 Apple Silicon 处理器上的 macOS 12.0.1 上有效。

如果您使用的是 x86_64 Linux,则可能需要添加RUSTFLAGS='-C relocation-model=static'.