Home > database >  How do I statically link a Haskell library with a Rust project?
How do I statically link a Haskell library with a Rust project?

Time:11-26

I’ve had no luck so far with linking a Haskell library to a Rust project. I’ve had a lot of errors, the latest being the recompile with -fPIC for ghc.

I’ve managed to get a functional example of dynamically linking — but have been unable to get it linked statically.

Attaching my current setup right now:

  1. build.rs

    fn main() {
        println!("cargo:rustc-link-search=native=deps");
        println!("cargo:rustc-link-lib=static=tesths");
    }
    
  2. src/main.rs

    extern "C" {
        pub fn addTwo(x: i32) -> i32;
        pub fn init();
        pub fn fin();
    }
    
    fn main() {
        println!("Hello, world!");
    }
    
  3. src/haskell/Lib.hs

    module Lib where
    
    import Foreign.C.Types
    
    addTwo :: CInt -> CInt
    addTwo = (2   )
    
    foreign export ccall addTwo :: CInt -> CInt
    
  4. cwrapper.c

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

I compile #4 with ghc -c -static -lHSrts -lffi cwrapper.c, getting cwrapper.o. Similarly, I compile #3 with ghc -c -static -fPIC -lffi Lib.hs and get object code for that as well.

Once that is done, I go ahead and archive the two with ar rcs libtesths.a Lib.o cwrapper.o.

On cargo build:

note: /usr/bin/ld: deps/libtesths.a(Lib.o):(.text 0x29): undefined reference to `newCAF'
          /usr/bin/ld: deps/libtesths.a(Lib.o):(.text 0x39): undefined reference to `stg_bh_upd_frame_info'
          /usr/bin/ld: deps/libtesths.a(Lib.o):(.text 0x48): undefined reference to `base_ForeignziCziTypes_zdfNumCInt_closure'
          /usr/bin/ld: deps/libtesths.a(Lib.o):(.text 0x4f): undefined reference to `stg_ap_p_info'
…

I’ve got a hunch that libHSrts isn’t being linked statically for some reason.

CodePudding user response:

I compiled the Haskell library and C shim at once, passing the -staticlib flag:

ghc -c -staticlib Lib.hs cwrapper.c -o libtesths.a

I then called the functions:

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

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

This worked for me on macOS 12.0.1 on an Apple Silicon processor using GHC 8.10.7.

If you are on x86_64 Linux, you may need to add RUSTFLAGS='-C relocation-model=static'.

  • Related