pcanbasic-sys 0.1.0

Rust bindings for the PCAN-Basic library
use std::env;
use std::path::PathBuf;

use bindgen::callbacks::{IntKind, ParseCallbacks};

const PCAN_HEADER: Option<&str> = option_env!("PCAN_HEADER");

fn main() {
    // Tell cargo to tell rustc to link the system libpcanbasic shared library.
    println!("cargo:rustc-link-lib=pcanbasic");

    #[cfg(target_os = "windows")]
    if PCAN_HEADER.is_none() {
        println!(
            "cargo::error=PCAN_HEADER environment variable must point to a valid PCANBasic.h header when compiling on Windows."
        );
        std::process::exit(1);
    }

    // TODO:(linux) when using non-system headers, how to reconcile the inclusion of <pcan.h>?
    // Let the user handle it or allow specifiying an include dir as well?

    let bindings = bindgen::Builder::default()
        .header(PCAN_HEADER.unwrap_or("include/wrapper.h"))
        // Tell cargo to invalidate the built crate whenever any of the included header files changed.
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        // Tell bindgen to correctly assign integer types to constants defined by PCAN.
        .parse_callbacks(Box::new(DefinesCallbacks))
        .blocklist_type("_*")
        .generate()
        .expect("Unable to generate bindings");

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

#[derive(Debug)]
struct DefinesCallbacks;
impl ParseCallbacks for DefinesCallbacks {
    fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
        // TODO: are they the same though? Windows vs. Linux
        match name {
            v if v.starts_with("HW")
                || v.starts_with("PCAN_MODE")
                || v.starts_with("PCAN_MESSAGE") =>
            {
                Some(IntKind::U8)
            }
            v if v.starts_with("PCAN_USBBUS") || v.starts_with("PCAN_BAUD") => Some(IntKind::U16),
            _ => None,
        }
    }
}