📄 kinect2-sys/build.rs
//! Build script: locate an installed libfreenect2, compile the C++
//! shim, and link.
//!
//! Discovery order:
//!
//! 1. `FREENECT2_DIR` — a libfreenect2 install prefix with
//!    `include/libfreenect2/` and `lib/` (the CMake default layout).
//!    On Windows this is how the sink finds the library built per the
//!    README (or vcpkg's installed tree).
//! 2. `pkg-config freenect2` — standard on Linux.
//! 3. `/usr/local` — the CMake default install prefix.

use std::env;
use std::path::PathBuf;

fn main() -> anyhow::Result<()> {
    println!("cargo:rerun-if-env-changed=FREENECT2_DIR");

    let mut include_dirs: Vec<PathBuf> = Vec::new();
    let mut lib_dirs: Vec<PathBuf> = Vec::new();

    let explicit = env::var_os("FREENECT2_DIR").map(PathBuf::from);
    if let Some(dir) = explicit {
        let include = dir.join("include");
        let lib = dir.join("lib");
        if !include.join("libfreenect2").exists() {
            anyhow::bail!(
                "FREENECT2_DIR={} has no include/libfreenect2 — point it at a \
                 libfreenect2 install prefix",
                dir.display()
            );
        }
        println!(
            "cargo:warning=using libfreenect2 from FREENECT2_DIR={}",
            dir.display()
        );
        include_dirs.push(include);
        lib_dirs.push(lib);
    } else if env::var_os("FREENECT2_NO_PKG_CONFIG").is_none()
        && pkg_config::probe_library("freenect2").is_ok()
    {
        let library = pkg_config::find_library("freenect2")
            .map_err(|e| anyhow::anyhow!("pkg-config freenect2: {e}"))?;
        // The pkg-config crate emits the link flags itself.
        for path in &library.include_paths {
            include_dirs.push(path.clone());
        }
        for path in &library.link_paths {
            println!("cargo:rustc-link-search=native={}", path.display());
        }
    } else {
        // The CMake default install prefix.
        let prefix = PathBuf::from("/usr/local");
        if prefix.join("include/libfreenect2").exists() {
            include_dirs.push(prefix.join("include"));
            lib_dirs.push(prefix.join("lib"));
        } else {
            anyhow::bail!(
                "libfreenect2 not found. Install it (see the kinect-view README's \
                 'Kinect v2 capture' section) and either set FREENECT2_DIR to its \
                 install prefix or make it visible to pkg-config."
            );
        }
    }

    // The shim.
    for dir in &include_dirs {
        println!("cargo:include={}", dir.display());
    }
    let mut build = cc::Build::new();
    build.cpp(true);
    build.file("csrc/shim.cpp");
    build.warnings(false);
    for dir in &include_dirs {
        build.include(dir);
    }
    build.compile("lf2shim");

    for dir in &lib_dirs {
        println!("cargo:rustc-link-search=native={}", dir.display());
    }
    println!("cargo:rustc-link-lib=freenect2");
    Ok(())
}