web-dev-qa-db-fra.com

Comment puis-je lier statiquement une bibliothèque HASKELLL avec A Rust?

Je n'ai pas eu de chance jusqu'à présent avec la liaison d'une bibliothèque Haskell à un Rust. J'ai eu beaucoup d'erreurs, la dernière étant la recompile with -fPIC pour ghc.

J'ai réussi à obtenir un exemple fonctionnel de relier dynamiquement - mais j'ai été incapable de le faire lier de manière statique.

Joindre ma configuration actuelle en ce moment:

  1. construire.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(); }
    

Je compile # 4 avec ghc -c -static -lHSrts -lffi cwrapper.c, obtenir cwrapper.o. De même, je compile # 3 avec ghc -c -static -fPIC -lffi Lib.hs et obtenir le code objet pour cela aussi.

Une fois que cela est fait, je vais de l'avant et archivez les deux avec ar rcs libtesths.a Lib.o cwrapper.o.

Au 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'
…

J'ai un hunch que libhsrts ne soit pas lié de manière statique pour une raison quelconque.

Mettre à jour

J'ai suivi les conseils de Shepmaster et j'ai effectué un exemple de travail avec succès. Mais j'ai des problèmes liés à mon Rust EXEC maintenant.

J'ai utilisé la pile avec ghc-options: -staticlib -stubdir . et c-sources: cwrapper.c construire. Quand j'essaie de construire le Rust Project avec cargo rustc — -C relocation-model=static:

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

Il y a aussi une mention d'un wrappers.o. Toute aide est appréciée.

Mise à jour 2

J'ai résolu les problèmes gmp en définissant build.rs Pour lier libgmp aussi. J'ai un problème différent maintenant, cependant.


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

Mise à jour 3

Ceci la commande finale de construction qui fait l'affaire:

cargo rustc -- -C relocation-model=static -Clink-arg=-Wl,--allow-multiple-definition

L'utilisation de RUSTFLAGS provoquera la construction de la construction car elle construit toutes les dépendances avec un modèle de relocalisation statique, qui ne fonctionnera pas - dans mon cas - pour la caisse rustversion. Il signalera un recompile with -fPIC Erreur.

7
SmokedTurkey

J'ai compilé la bibliothèque Haskell et C Shim à la fois, passant le -staticlib Drapeau:

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

J'ai ensuite appelé les fonctions:

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

Cela a fonctionné pour moi sur MacOS 12.0.1 sur un Apple Processeur de silicium utilisant GHC 8.10.7.

Si vous êtes sur X86_64 Linux, vous devrez peut-être ajouter RUSTFLAGS='-C relocation-model=static'.

4
Shepmaster