pan_bindings 1.0.7

FFI bindings for the SCION PAN Path Aware Networking library
extern crate bindgen;

use std::env;
use std::fs;
use std::path::PathBuf;

use bindgen::CargoCallbacks;

fn main() {
/*
idea: let the build script figure out, from where it is invoked

 */

    println!("enter BUILD-SCRIPT");
    let dir = env::current_dir().unwrap();    
    println!( "DIR: {:?}" ,dir );

    // let mut prj_dir = env::var("PROJECT_DIR").or( Ok( String::from(dir.to_str().unwrap()) ) );

   /* let path_to_lib: PathBuf = match env::var("PROJECT_DIR") {
        Ok(p) =>{
            PathBuf::from(p).join("/rust/src")
        },
        Err(e)=>{
            dir.join("/src")
        }
    };
*/


    let mut out_dir = env::var("OUT_DIR").unwrap();
    let out = env::var("OUTER_OUT_DIR");

    match out
    {
        Ok(o)=>{
            // CargoBuild
            println!("cargo-build: {}", o);
            // out_dir = o;
        },
        Err(e)=>{
            // CMakeBuild
            println!("cmake-build");
        }
    }

    match std::process::Command::new("mkdir").arg("tmp").output() {
        Ok(o) => {
            print!("mkdir output: {:?}\n", o);
        }
        Err(e) => {
            panic!("mkdir failed: {}", e);
        }
    }

   

    // This is the directory where the `c` library is located.
    let libdir_path = PathBuf::from("./tmp")
        // Canonicalize the path as `rustc-link-search` requires an absolute
        // path.
        .canonicalize()
        .expect("cannot canonicalize path");

    println!("libdir_path: {}", libdir_path.display());
    // This is the path to the `c` headers file.
    let headers_path_str = "../include/pan/go_handle.hpp"; // headers_path.to_str().expect("Path is not a valid string");

    // This is the path to the intermediate object file for our library.
    let obj_path = libdir_path.join("go_handle.o");
    // This is the path to the static library file.
    let lib_path = libdir_path.join("libgo_handle.a");

    //  clang -c -o tmp/go_handle.o ../cpp/go_handle.cpp -I ../include
    let res = std::process::Command::new("clang++")
        .arg("-c")
        .arg("-I")
        .arg("../include/pan")
        //.arg("-I ../include/pan/pan.h")
        //.arg("-I ../include/pan/go_handle.hpp")
        .arg("-o")
        .arg(&obj_path)
        .arg("../cpp/go_handle.cpp")
        .arg("-DBINDGEN")
        .output();
    // if !res.expect("cannot execute clang").status.success()

    match res {
        Ok(o) => {
            print!("output: {:?}\n", o);
        }
        Err(e) => {
            // doesnt work for some reason :(
            // you have to enter the above command manually

            //panic!("could not compile object file: {}",res.err().unwrap());
            panic!("could not compile object file: {}", e);
        }
    }

    // ar rcs tmp/libgo_handle.a tmp/go_handle.o
    let res1 = std::process::Command::new("ar")
        .arg("rcs")
        .arg(lib_path)
        .arg(obj_path)
        .output();
    if !res1.is_ok() {
        // Panic if the command was not successful.
        panic!("could not emit library file: {}", res1.err().unwrap());
    }

    /* match fs::copy("../build/go/libpand.a","tmp/libpand.a")
    {
        Err( err ) => { panic!("could not copy file"); }
        Ok( o) =>{}
    }
    */

    // println!("cargo:rustc-link-search=all={},../build/go", libdir_path.to_str().unwrap());

    println!("cargo:rustc-link-search=all=tmp");
    println!("cargo:rustc-link-search=all={}", &out_dir);
    println!("cargo:rustc-link-search=all=../build/go");
    println!("cargo:rustc-link-search=all=/lib/x86_64-linux-gnu");

    //  println!("cargo:rustc-link-search=../build/go");

    println!("cargo:rustc-link-lib=static:+bundle=go_handle");
    println!("cargo:rustc-link-lib=static:+bundle=pan");
    println!("cargo:rustc-link-lib=stdc++");
    //println!("cargo:rustc-link-lib=go_handle");
    //println!("cargo:rustc-link-lib=pan");

    // println!("cargo:rustc-flags=-l go_handle.a -l pand.a  -L ../build/go -L tmp "); // -Wl,-Bstatic

    // Tell cargo to invalidate the built crate whenever the header changes.
    println!("cargo:rerun-if-changed={}", headers_path_str);
    println!("cargo:rerun-if-changed=../build");

    // The bindgen::Builder is the main entry point
    // to bindgen, and lets you build up options for
    // the resulting bindings.
    let bindings = bindgen::Builder::default()
        // The input header we would like to generate
        // bindings for.
        .clang_arg("-DBINDGEN")
        .clang_arg("-xc++")
        .clang_arg("-std=c++11")
        .clang_arg("-I ../include")
        .clang_arg("-I ../include/pan")
        .header("../include/pan/pan_cdefs.h")
        .header("../include/pan/pan.h")
        .header(headers_path_str)
        // Tell cargo to invalidate the built crate whenever any of the
        // included header files changed.
        .parse_callbacks(Box::new(CargoCallbacks))
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");


    

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from(out_dir).join("bindings.rs");


    env::set_var("BINDINGS_PATH", &*out_path.to_string_lossy() );

    bindings
        .write_to_file(out_path.clone() )
        .expect("Couldn't write bindings!");

    // copy bindings to PROJECT_DIR/rust/src/bindings.rs where lib.rs expects them
   std::fs::copy(out_path, dir.join("src/bindings.rs")  )
   .expect("cannot copy generated bindings to where lib.rs expects them");
}