You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Haskell库静态链接到Rust项目?链接报错问题排查

Rust项目静态链接Haskell库问题与完整解决方案

问题背景

目标为将Haskell库静态链接到Rust项目,动态链接已有可运行示例,但静态链接始终失败,最初报错提示ghc需要recompile with -fPIC,后续多轮调整后仍出现不同链接错误。

初始配置与首轮报错

初始项目配置

  1. build.rs
fn main() {
    println!("cargo:rustc-link-search=native=deps");
    println!("cargo:rustc-link-lib=static=tesths");
}
  1. src/main.rs
extern "C" {
    pub fn addTwo(x: i32) -> i32;
    pub fn init();
    pub fn fin();
}

fn main() {
    println!("Hello, world!");
}
  1. src/haskell/Lib.hs
module Lib where

import Foreign.C.Types

addTwo :: CInt -> CInt
addTwo = (2 + )

foreign export ccall addTwo :: CInt -> CInt
  1. 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(); }

初始编译步骤与报错

使用ghc -c -static -lHSrts -lffi cwrapper.c编译C包装层得到cwrapper.o,使用ghc -c -static -fPIC -lffi Lib.hs编译Haskell代码得到对应目标文件,执行ar rcs libtesths.a Lib.o cwrapper.o将两个目标文件打包为静态库。
执行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'
…

错误原因为GHC运行时(RTS)相关依赖未被正确打包进静态库,导致链接时缺失符号。


阶段1:GMP依赖缺失报错

调整GHC编译参数,在stack配置中添加ghc-options: -staticlib -stubdir .和c-sources: cwrapper.c完成Haskell侧构建后,执行cargo rustc — -C relocation-model=static构建Rust项目时出现新报错:

/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'

错误原因为Haskell的Integer类型实现依赖GMP数学库,未将该库加入链接配置。在build.rs中新增libgmp的静态链接配置即可解决该问题。


阶段2:符号多重定义报错

解决GMP依赖问题后,出现符号重复定义报错:

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

错误原因为静态库打包或编译阶段重复引入了相同目标文件,导致同一个符号被多次定义。


最终可行方案

最终可用的构建命令如下:

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

注意事项:不要通过全局RUSTFLAGS配置上述参数,该配置会对项目所有依赖启用静态重定位模型,若项目依赖rustversion这类不支持该配置的crate,会再次抛出recompile with -fPIC错误。


内容的提问来源于stack exchange,提问作者SmokedTurkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 10:15:07