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

构建依赖libcuda多依赖项的Rust crate时解决链接错误

问题描述

我有一个名为foo的Rust crate,依赖两个库:

  • cudarc:对应CUDA驱动API的libcuda的sys crate
  • rs-smctrl:我为调用libcuda的C库libsmctrl编写的sys crate

单独构建cudarc或rs-smctrl都能成功,foo只依赖其中一个时也可正常编译,但同时引入两个依赖就会触发链接器错误。我的目标是让foo静态链接libsmctrl,动态链接libcuda。

链接错误详情

...
  = note: /usr/bin/ld: /h/bez/work/rs-smctrl/target/debug/deps/librs_smctrl-ee6526e2da5cab52.rlib(libsmctrl.o): in function `setup_g_sm_control_10':
          /h/bez/work/rs-smctrl/src/libsmctrl.c:53: undefined reference to `cudbgReportDriverApiErrorFlags'
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
          
  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

error: could not compile `rs-smctrl` (bin "rs-smctrl") due to previous error

rs-smctrl的build.rs代码

# `build.rs` for `rs-smctrl`
fn main() {
    println!("cargo:rustc-link-lib=dylib=cuda");

    let src = ["src/libsmctrl.c"];
    let mut builder = cc::Build::new();
    let build = builder
        .files(src.iter())
        .include("/usr/local/cuda/include")
        .flag("-Wno-unused-parameter")
        .flag("-Wno-parentheses")
        .flag("-Wno-sign-compare");
    build.compile("libsmctrl");
}

foo的配置(注释cudarc即可正常构建)

Cargo.toml

# `Cargo.toml` for `foo`:
[package]
name = "foo"
version = "0.1.0"
edition = "2021"

[dependencies]
cudarc = { version="0.9.15", features=["std", "driver"], default-features = false }
rs-smctrl = { git = "https://github.com/atomicapple0/rs-smctrl.git" }

main.rs

# `main.rs` for `foo`
fn main() {
    unsafe { rs_smctrl::libsmctrl_set_global_mask(0) };
    println!("Hello, world!");
}
解决方案

这个问题本质是链接顺序冲突:同时引入两个依赖时,Cargo自动排序的链接顺序可能导致libcuda的符号在rs-smctrl之后被处理,导致rs-smctrl找不到cudbgReportDriverApiErrorFlags这类符号。以下是几个实用解法:

方法1:强制调整libcuda的链接顺序

修改rs-smctrl的build.rs,把原来的cargo:rustc-link-lib=dylib=cuda换成直接指定链接参数,强制让libcuda排在前面:

fn main() {
    // 用link-arg强制指定链接顺序,确保libcuda先被处理
    println!("cargo:rustc-link-arg=-lcuda");

    let src = ["src/libsmctrl.c"];
    let mut builder = cc::Build::new();
    let build = builder
        .files(src.iter())
        .include("/usr/local/cuda/include")
        .flag("-Wno-unused-parameter")
        .flag("-Wno-parentheses")
        .flag("-Wno-sign-compare");
    build.compile("libsmctrl");
}

方法2:全局声明libcuda链接

在foo的根目录新建build.rs,添加全局的libcuda链接指令,确保所有依赖都能找到完整的符号:

// foo的build.rs
fn main() {
    println!("cargo:rustc-link-lib=dylib=cuda");
}

方法3:让rs-smctrl依赖cudarc调整链接顺序

在rs-smctrl的Cargo.toml中添加cudarc作为构建依赖,让Cargo自动调整链接顺序:

[build-dependencies]
cudarc = { version="0.9.15", features=["driver"], default-features = false }

同时保留原build.rs中的cargo:rustc-link-lib=dylib=cuda即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:37:03