use std::{fs::File, io::Write}; #[cfg(feature = "__bindgen")] use bindgen::callbacks::{EnumVariantValue, ParseCallbacks}; #[cfg(feature = "__bindgen")] extern crate bindgen; //#[cfg(feature = "__bindgen")] //#[path = "src/gen.rs"] //mod gen; // //#[cfg(feature = "__bindgen")] //#[derive(Debug)] //struct Processor; //#[cfg(feature = "__bindgen")] //impl ParseCallbacks for Processor { // fn enum_variant_name( // &self, // enum_name: Option<&str>, // original_variant_name: &str, // variant_value: bindgen::callbacks::EnumVariantValue, // ) -> Option { // match enum_name { // Some("enum AVCodecID") => { // if let Some(varname) = original_variant_name.strip_prefix("AV_CODEC_ID_") { // if let EnumVariantValue::Unsigned(val) = variant_value { // if val == gen::FIRST_AUDIO // || val == gen::FIRST_SUBTITLE // || val == gen::FIRST_UNKNOWN // { // None // } else { // Some(if val > gen::FIRST_UNKNOWN || val == 0 { // varname.to_string() // } else if val > gen::FIRST_SUBTITLE { // format!("Sub{varname}") // } else if val > gen::FIRST_AUDIO { // format!("Audio{varname}") // } else { // format!("Video{varname}") // }) // } // } else { // None // } // } else { // panic!() // } // } // _ => None, // } // } //} fn main() { // Only run bindgen if the super special feature is enabled // // libav is MASSIVE and not everybody needs to generate the bindings themself. // Regenerating the bindings while developing FFerris gets old FAST. #[cfg(feature = "__bindgen")] { std::process::Command::new("clang") .args(["-lavutil", "-lavcodec", "src/codec.c"]) .output() .unwrap(); let out = std::process::Command::new("./a.out") .output() .unwrap() .stdout; let mut f = File::options() .write(true) .create(true) .truncate(true) .open("src/gen.rs") .unwrap(); f.write_all(out.as_slice()).unwrap(); const VALID_ENUMS: &'static [&'static str] = &["AVMediaType", "AVPixelFormat", "AVClassCategory"]; let mut b = bindgen::builder() // Use core for no_std compatibility .use_core() // TODO: Do I need this...? .generate_cstr(true) // Dynamic linking sucks .dynamic_link_require_all(true) .sort_semantically(true) .enable_function_attribute_detection() // It was causing me trouble, so I got rid of it. // Something related to floating point numbers I think? // TODO: Look into this you idiot .blocklist_item("FP_.*") // Break now; fix later .rustified_enum(".*") .newtype_enum("AVPixelFormat") .translate_enum_integer_types(true); // .parse_callbacks(Box::new(Processor)); // Includes are conditional, based on Rust features // Need to let clang know { #[cfg(feature = "avformat")] { b = b.clang_arg("-D__FFERRIS_ENABLE_AVFORMAT"); } #[cfg(feature = "avcodec")] { b = b.clang_arg("-D__FFERRIS_ENABLE_AVCODEC"); } #[cfg(feature = "avfilter")] { b = b.clang_arg("-D__FFERRIS_ENABLE_AVFILTER"); } #[cfg(feature = "avdevice")] { b = b.clang_arg("-D__FFERRIS_ENABLE_AVDEVICE"); } } b // All the comments because I like LSP autocomplete .clang_arg("-fretain-comments-from-system-headers") .clang_arg("-fparse-all-comments") // Include the include header file with my includes in it .header("src/include.h") // Finally generate the bindings :) .generate() .unwrap() .write_to_file("src/bindings.rs") .unwrap(); } for f in ["src/include.h", "src/gen.c"] { println!("cargo::rerun-if-changed={f}"); } println!("cargo::rustc-link-search=/usr/lib"); println!("cargo::rustc-link-lib=avutil"); #[cfg(feature = "avformat")] println!("cargo::rustc-link-lib=avformat"); #[cfg(feature = "avcodec")] println!("cargo::rustc-link-lib=avcodec"); #[cfg(feature = "avfilter")] println!("cargo::rustc-link-lib=avfilter"); #[cfg(feature = "avdevice")] println!("cargo::rustc-link-lib=avdevice"); }