ogc-sys 0.1.1

Rust bindings for devkitPro's libogc
extern crate bindgen;

use regex::Regex;
use std::env;
use std::process::Command;

 fn get_clang_version() -> String {
    // Check if the clang version env variable exists.
    if env::var("CLANG_VERSION").is_err() {
        // Attempt to retrieve clang version through the command line.
        let clang_output = match Command::new("clang").arg("--version").output() {
            Ok(output) => output,
            Err(_e) => panic!("Could not find clang on the host machine!"),
        };

        // Get the first line of the output, usually containing the version string.
        let output = clang_output.stdout;
        let parsed_output =
            String::from_utf8(output).expect("Clang command output returned a non-utf8 string.");
        let first_line = match parsed_output.lines().next() {
            Some(line) => line,
            None => panic!("Clang command output does not contain split lines."),
        };

        // Parse the version string using Regex.
        let regex = Regex::new(r"(?m)\d+(\.\d+)+").unwrap();
        let result = regex.captures(first_line).unwrap().get(0);

        // Attempt to join together the version string.
        let version = match result {
            Some(v) => v.as_str(),
            None => {
                panic!("Failed to parse version, please export your clang version to CLANG_VERSION")
            }
        };

        // Return the final joined string.
        version.to_string()
    } else {
        // Clang version env variable exists, use that over parsing.
        env::var("CLANG_VERSION").unwrap()
    }
}

fn main() {
    let dkp_path = env::var("DEVKITPRO").expect("devkitPro is needed to use this crate");

    println!(
        "cargo:rustc-link-search=native={}/devkitPPC/powerpc-eabi/lib",
        dkp_path
    );
    println!("cargo:rustc-link-search=native={}/libogc/lib/wii", dkp_path);

    println!("cargo:rustc-link-lib=static=c");
    println!("cargo:rustc-link-lib=static=sysbase");
    println!("cargo:rustc-link-lib=static=m");
    println!("cargo:rustc-link-lib=static=ogc");
    println!("cargo:rustc-link-lib=static=asnd");
    println!("cargo:rustc-link-lib=static=aesnd");

    //Wiipad
    println!("cargo:rustc-link-lib=static=bte");
    println!("cargo:rustc-link-lib=static=wiiuse");


    println!("cargo:rerun-if-changed=wrapper.h");
    let bindings = bindgen::Builder::default()
        .header("wrapper.h")
        .rust_target(bindgen::RustTarget::Nightly)
        .use_core()
        .trust_clang_mangling(false)
        .layout_tests(false)
        .ctypes_prefix("::libc")
        .prepend_enum_name(false)
        .disable_untagged_union()
        .blocklist_type("u(8|16|32|64|128)")
        .blocklist_type("i(8|16|32|64|128)")
        .blocklist_type("f(32|64)")
        .clang_arg("--target=powerpc-none-eabi")
        .clang_arg(format!("--sysroot={}/devkitPPC/powerpc-eabi", dkp_path))
        .clang_arg(format!("-isystem/{}/devkitPPC/powerpc-eabi/include", dkp_path))
        .clang_arg(format!(
            "-isystem/usr/lib/clang/{}/include",
            get_clang_version()
        ))
        .clang_arg(format!("-I{}/libogc/include", dkp_path))
        .clang_arg("-mfloat-abi=hard")
        .clang_arg("-nostdinc")
        .clang_arg("-Wno-macro-redefined")
        .clang_arg("-Wno-incompatible-library-redeclaration")
        .clang_arg("-DHW_RVL")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .generate()
        .expect("Unable to generate bindings");

    bindings
        .write_to_file("./src/ogc.rs")
        .expect("Unable to write bindings to file");
}