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:
build.rs
fn main() { println!("cargo:rustc-link-search=native=deps"); println!("cargo:rustc-link-lib=static=tesths"); }
src/main.rs
extern "C" { pub fn addTwo(x: i32) -> i32; pub fn init(); pub fn fin(); } fn main() { println!("Hello, world!"); }
src/haskell/Lib.hs
module Lib where import Foreign.C.Types addTwo :: CInt -> CInt addTwo = (2 ) foreign export ccall addTwo :: CInt -> CInt
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'
.