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

Rust Bindgen因头文件相对路径问题编译失败求助

问题:为VMAF生成Rust绑定时头文件找不到错误

尝试为VMAF生成Rust绑定,遇到头文件查找失败的问题:VMAF仓库的头文件与.c文件分属不同目录,主头文件vmaf.h用相对路径引用同目录下的其他.h文件,导致rust-bindgen报错:'libvmaf/compute_vmaf.h' file not found。

项目目录结构:

.
├── src # lib.rs 所在目录
├── target
│   └── debug
└── vmaf
    ├── libvmaf
    │   ├── doc
    │   ├── include
    │   │   └── libvmaf # vmaf.h及其他.h文件所在目录
    │   ├── src # 其他.h文件所在目录
    │   │   ├── arm
    │   │   ├── compat
    │   │   ├── ext
    │   │   ├── feature
    │   │   └── x86
    │   ├── test
    │   └── tools

当前使用的build.rs代码:

extern crate meson;
use std::env;
use std::path::PathBuf;

fn main() {
    //env::set_var("RUST_BACKTRACE", "1");
    let build_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    _ = build_path.join("build");
    let build_path = build_path.to_str().unwrap();

    println!("cargo:rustc-link-lib=libvmaf");
    println!("cargo:rustc-link-search=native={build_path}");
    meson::build("vmaf/libvmaf", build_path);

    let bindings = bindgen::Builder::default()
    .header("vmaf/libvmaf/include/libvmaf/libvmaf.h")
    .parse_callbacks(Box::new(bindgen::CargoCallbacks))
    .generate()
    .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings.write_to_file(out_path).expect("Couldn't write bindings!");
}

疑问:

  1. 如何让rust-bindgen找到正确的头文件目录?
  2. 使用cargo:rustc-link-search指向该目录是否会影响已通过meson编译的库链接?
解决方案

1. 让bindgen找到正确的头文件目录

bindgen依赖Clang解析头文件,需要明确告诉Clang头文件的搜索路径。针对你的目录结构,需要添加两个关键的搜索路径:

  • vmaf/libvmaf/include:vmaf.h中引用libvmaf/compute_vmaf.h时,Clang需要从这个目录出发找到libvmaf子目录
  • vmaf/libvmaf/src:如果代码中引用了src目录下子文件夹(比如compat、ext)里的头文件,也需要添加这个路径

修改build.rs中的bindgen构建部分,添加.clang_arg()传入这些路径:

let bindings = bindgen::Builder::default()
    .header("vmaf/libvmaf/include/libvmaf/libvmaf.h")
    // 添加include目录到Clang搜索路径
    .clang_arg("-Ivmaf/libvmaf/include")
    // 如果需要src目录下的头文件,添加这一行
    .clang_arg("-Ivmaf/libvmaf/src")
    .parse_callbacks(Box::new(bindgen::CargoCallbacks))
    .generate()
    .expect("Unable to generate bindings");

如果担心相对路径的问题(比如构建时的工作目录变化),可以改用绝对路径:

let include_dir = PathBuf::from(env::current_dir().unwrap()).join("vmaf/libvmaf/include");
let src_dir = PathBuf::from(env::current_dir().unwrap()).join("vmaf/libvmaf/src");

let bindings = bindgen::Builder::default()
    .header("vmaf/libvmaf/include/libvmaf/libvmaf.h")
    .clang_arg(format!("-I{}", include_dir.to_str().unwrap()))
    .clang_arg(format!("-I{}", src_dir.to_str().unwrap()))
    .parse_callbacks(Box::new(bindgen::CargoCallbacks))
    .generate()
    .expect("Unable to generate bindings");

cargo:rustc-link-search=native={path}是告诉Rust编译器去哪里找编译好的库文件(比如.a、.so或.dll),和头文件搜索路径完全无关,不会影响meson编译好的库链接。

不过需要注意:meson编译完成后,库文件通常会放在build_path的子目录(比如lib),你当前的代码直接用build_path可能找不到库。可以调整路径为:

let build_lib_path = build_path.join("lib").to_str().unwrap();
println!("cargo:rustc-link-search=native={build_lib_path}");

具体子目录需要根据meson的编译输出结构调整。


内容的提问来源于stack exchange,提问作者Brandon Piña

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:11:30