chibi-scheme 0.1.0

Rust bindings to chibi-scheme
extern crate bindgen;

use std::collections::HashSet;
use std::env;
use std::io;
use std::path::Path;
use std::process::Command;

fn checkout(dir: &Path, tag: &str) -> io::Result<()> {
    Command::new("git")
        .current_dir(dir)
        .arg("clone")
        .args(&["--depth", "100"])
        .arg("--single-branch")
        .arg("https://github.com/ashinn/chibi-scheme")
        .status()?;

    let status = Command::new("git")
        .current_dir(dir.join("chibi-scheme"))
        .arg("checkout")
        .arg(format!("tags/{}", tag))
        .status()?;

    if status.success() {
        Ok(())
    } else {
        Err(io::Error::new(io::ErrorKind::Other, "Failed to checkout"))
    }
}

fn make(dir: &Path) -> io::Result<()> {
    let status = Command::new("make")
        .current_dir(dir.join("chibi-scheme"))
        .status()?;
    if status.success() {
        Ok(())
    } else {
        Err(io::Error::new(io::ErrorKind::Other, "Failed to run make"))
    }
}

// Taken from https://github.com/rust-lang/rust-bindgen/issues/687
#[derive(Debug)]
struct IgnoreMacros(HashSet<String>);

impl bindgen::callbacks::ParseCallbacks for IgnoreMacros {
    fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior {
        if self.0.contains(name) {
            bindgen::callbacks::MacroParsingBehavior::Ignore
        } else {
            bindgen::callbacks::MacroParsingBehavior::Default
        }
    }
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    checkout(Path::new(&out_dir), "0.8").unwrap();
    make(Path::new(&out_dir)).unwrap();
    let ignored_macros = IgnoreMacros(
        vec![
            "FP_INFINITE".into(),
            "FP_NAN".into(),
            "FP_NORMAL".into(),
            "FP_SUBNORMAL".into(),
            "FP_ZERO".into(),
            "IPPORT_RESERVED".into(),
        ].into_iter()
        .collect(),
    );
    let bindings = bindgen::Builder::default()
        .header(format!("{}/chibi-scheme/include/chibi/eval.h", &out_dir))
        .parse_callbacks(Box::new(ignored_macros))
        .generate()
        .expect("Unable to generate bindings");
    bindings
        .write_to_file(format!("{}/bindings.rs", out_dir))
        .expect("Could not write bindings");

    println!(
        "cargo:rustc-link-search=native={}/chibi-scheme/libchibi-scheme.so",
        &out_dir
    );
    println!("cargo:rustc-link-lib=chibi-scheme");
}