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

Rust C++ FFI问题:如何指定链接库文件的路径?

Rust FFI包装C++库时的链接错误问题

问题详情

使用cmake和bindgen crates为支持CMake构建的C++库制作Rust FFI包装器,运行cargo test时触发链接错误:

error: linking with `cc` failed: exit status: 1
  = note: /usr/bin/ld: cannot find -lcppcode: No such file or directory
          collect2: error: ld returned 1 exit status

但在build目录下能看到生成的库文件:

ls ./target/debug/build/myproject-debe94b9fba6ebdb/out/lib
libcppcode.so  libcppcode_static.a

build.rs中已添加链接相关代码,但rustc-link-lib仍无法定位库文件:

println!("cargo:rustc-link-search={}", dst.display());
println!("cargo:rustc-link-lib=cppcode");

项目结构:

.
├── build.rs
├── Cargo.lock
├── Cargo.toml
├── ext
│   └── cppcode
├── src
│   └── lib.rs
└── wrapper.h

相关代码文件

build.rs

extern crate cmake;
use cmake::Config;
use std::env;
use std::path::PathBuf;

fn main()
{
    let mut cfg = Config::new("ext/cppcode");
    let dst = cfg.build();

    println!("cargo:rustc-link-search={}", dst.display());
    println!("cargo:rustc-link-lib=cppcode");

    // Specify the include directory for bindgen
    let include_dir = "ext/cppcode/include";

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

    // The bindgen::Builder is the main entry point to bindgen, and lets you build up options for the resulting bindings.
    let bindings = bindgen::Builder::default()
        // The input header we would like to generate bindings for.
        .header("wrapper.h")
        // Set include directory
        .clang_arg(format!("-I{}", include_dir))
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

wrapper.h

#include "cppcode.h"

lib.rs

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(test)]
mod tests {
    
    #[test]
    fn hello_test() {
        println!("Hello, tests!");   
    }
}

Cargo.toml

[package]
name = "myproject"
version = "0.1.0"
edition = "2021"
build = "build.rs"

[dependencies]



[build-dependencies]
bindgen = "0.58.1"
autotools = "0.2"
cmake = "0.1.50"

解决方案

1. 修正链接路径

当前cargo:rustc-link-search指向的是dst根目录,但库文件实际在dst/lib子目录下,需调整路径:

println!("cargo:rustc-link-search={}", dst.join("lib").display());

2. 明确指定库类型

rustc默认优先查找动态库,但未指定类型时可能出现匹配歧义,需明确声明链接的是静态库还是动态库:

  • 链接静态库:
    println!("cargo:rustc-link-lib=static=cppcode");
    
  • 链接动态库:
    println!("cargo:rustc-link-lib=dylib=cppcode");
    

3. 强制CMake生成目标库类型

如果C++库的CMake配置未默认生成所需库类型,可在构建时添加参数强制生成:

let dst = cfg
    .define("BUILD_SHARED_LIBS", "ON") // 强制生成动态库
    // 或 .define("BUILD_STATIC_LIBS", "ON") 强制生成静态库
    .build();

4. 验证链接路径有效性

在build.rs中添加调试输出,确认路径是否正确指向库文件所在目录:

let lib_path = dst.join("lib");
println!("cargo:rustc-link-search={}", lib_path.display());
println!("DEBUG: Library path exists? {}", lib_path.exists());
println!("DEBUG: Files in lib path: {:?}", std::fs::read_dir(lib_path).unwrap().collect::<Vec<_>>());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:10:16