// SPDX-License-Identifier: AGPL-3.0-or-later use std::env; use std::path::PathBuf; fn main() { let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); if target_os != "windows" { println!("cargo:rerun-if-changed=build.rs"); return; } println!("cargo:rerun-if-env-changed=BINDGEN_NVENC_HEADERS"); println!("cargo:rerun-if-env-changed=BINDGEN_AMF_HEADERS"); println!("cargo:rerun-if-env-changed=BINDGEN_QSV_HEADERS"); println!("cargo:rerun-if-changed=build.rs"); #[cfg(feature = "bindgen-sdk")] { if let Some(path) = sdk_path("BINDGEN_NVENC_HEADERS", DEFAULT_NVENC_INCLUDE) { generate_nvenc_bindings(path); } if let Some(path) = sdk_path("BINDGEN_AMF_HEADERS", DEFAULT_AMF_INCLUDE) { generate_amf_bindings(path); } if let Some(path) = sdk_path("BINDGEN_QSV_HEADERS", DEFAULT_QSV_INCLUDE) { generate_qsv_bindings(path); } } } #[allow(dead_code)] const DEFAULT_NVENC_INCLUDE: &str = r"C:\Users\Hampus\sdk\nv-codec-headers\include"; #[allow(dead_code)] const DEFAULT_AMF_INCLUDE: &str = r"C:\Users\Hampus\sdk\AMF\amf\public\include"; #[allow(dead_code)] const DEFAULT_QSV_INCLUDE: &str = r"C:\Users\Hampus\sdk\libvpl\api\vpl"; #[allow(dead_code)] fn sdk_path(env_var: &str, default: &str) -> Option { let value = env::var(env_var).unwrap_or_else(|_| default.to_string()); let path = PathBuf::from(&value); if path.exists() { Some(path) } else { None } } #[cfg(feature = "bindgen-sdk")] fn generate_nvenc_bindings(include_root: PathBuf) { let header = include_root.join("ffnvcodec").join("nvEncodeAPI.h"); if !header.exists() { println!("cargo:warning=NVENC header missing at {}", header.display()); return; } let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR")); let bindings = bindgen::Builder::default() .header(header.to_string_lossy()) .clang_arg(format!("-I{}", include_root.display())) .allowlist_type("NV_ENC.*") .allowlist_function("NvEncodeAPI.*") .allowlist_var("NV_ENC.*") .layout_tests(false) .generate() .expect("nvenc bindgen"); bindings .write_to_file(out_dir.join("nvenc_bindings.rs")) .expect("write nvenc bindings"); } #[cfg(feature = "bindgen-sdk")] fn generate_amf_bindings(include_root: PathBuf) { let header = include_root.join("components").join("VideoEncoderVCE.h"); if !header.exists() { println!("cargo:warning=AMF header missing at {}", header.display()); return; } let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR")); let bindings = bindgen::Builder::default() .header(header.to_string_lossy()) .clang_arg(format!("-I{}", include_root.display())) .allowlist_type("AMF.*") .layout_tests(false) .generate() .expect("amf bindgen"); bindings .write_to_file(out_dir.join("amf_bindings.rs")) .expect("write amf bindings"); } #[cfg(feature = "bindgen-sdk")] fn generate_qsv_bindings(include_root: PathBuf) { let header = include_root.join("mfxvideo.h"); if !header.exists() { println!("cargo:warning=QSV header missing at {}", header.display()); return; } let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR")); let bindings = bindgen::Builder::default() .header(header.to_string_lossy()) .clang_arg(format!("-I{}", include_root.display())) .allowlist_type("mfx.*") .allowlist_function("MFX.*") .layout_tests(false) .generate() .expect("qsv bindgen"); bindings .write_to_file(out_dir.join("qsv_bindings.rs")) .expect("write qsv bindings"); }