rustrust-bindgen

Bindgen failing because of relative paths in header file


I'm trying to build out some bindings for vmaf but i've been running into some issues. The header files and the .c files in the vmaf repository live in seperate folders. I'm having an issue where the main vmaf.h file references other .h files in the same directory:

#ifndef __VMAF_H__
#define __VMAF_H__

#include <stdint.h>
#include <stdio.h>

#include "libvmaf/compute_vmaf.h"
#include "libvmaf/model.h"
#include "libvmaf/picture.h"
#include "libvmaf/feature.h"
...

this results in me getting the following build error: vmaf/libvmaf/include/libvmaf/libvmaf.h:25:10: fatal error: 'libvmaf/compute_vmaf.h' file not found. It looks to me that rust-bindgen is looking in the current working directory for the next header file when in reality it lives in a subdirectory in my project as a git submodule pointing to the vmaf git repository

Here's the folder structure

.
├── src # lib.rs lives here
├── target
│   └── debug
└── vmaf
    ├── libvmaf
    │   ├── doc
    │   ├── include
    │   │   └── libvmaf # vmaf.h lives here along with other .h files
    │   ├── src # various other .h files live here
    │   │   ├── arm
    │   │   ├── compat
    │   │   ├── ext
    │   │   ├── feature
    │   │   └── x86
    │   ├── test
    │   └── tools

and here's my 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!")
}

How can I get rust-bindgen to look in that directory rather than from my current working directory? Should i use cargo:rustc-link-search and point it to the correct directory? Will that mess up linking to the library itself since i've already used that statement earlier to compile the meson project?


Solution

  • The answer ended up being the -I flag to clang arg

    // Path to vendor header files
        let headers_dir = PathBuf::from("vmaf/libvmaf/include");
        let headers_dir_canonical = canonicalize(headers_dir).unwrap();
        let include_path = headers_dir_canonical.to_str().unwrap();
    
        // Generate bindings to libvmaf using rust-bindgen
        let bindings = bindgen::Builder::default()
            .header("vmaf/libvmaf/include/libvmaf/libvmaf.h")
            .clang_arg(format!("-I{include_path}")) // New Stuff!
            .parse_callbacks(Box::new(bindgen::CargoCallbacks))
            .generate()
            .expect("Unable to generate bindings");