use std::env;
use std::path::PathBuf;
fn get_out_dir() -> PathBuf {
let out_dir = env::var("OUT_DIR").expect("OUT_DIR must be set");
if !out_dir.is_empty() {
PathBuf::from(out_dir)
} else {
let out_dir_raw = env::temp_dir();
let out_dir_str = out_dir_raw.to_str().expect("Could not get out_dir");
env::set_var("OUT_DIR", out_dir_str);
PathBuf::from(out_dir_str)
}
}
fn build(out_dir: PathBuf, name: &str, tool: &str) {
let include_dir = PathBuf::from("include")
.canonicalize()
.expect("Cannot canonicalize path");
let (header_path, impl_path) = match tool {
"clang" => (
include_dir.join(format!("{}.h", name)),
include_dir.join(format!("{}.c", name)),
),
"clang++" => (
include_dir.join(format!("{}.hpp", name)),
include_dir.join(format!("{}.cpp", name)),
),
_ => panic!("Only clang and clang++ available."),
};
let obj_path = out_dir.join(format!("{}.o", name));
let lib_path = out_dir.join(format!("lib{}.a", name));
let out_file = out_dir.join(format!("{}_bindings.rs", name));
let header_path_str = header_path.to_str().unwrap();
println!("cargo:rustc-link-search=native={}", out_dir.to_str().unwrap());
println!("cargo:rustc-link-lib=static={}", name);
if !std::process::Command::new(tool)
.arg("-c")
.arg("-o")
.arg(&obj_path)
.arg(&impl_path)
.arg(format!("-I{}", include_dir.to_str().unwrap()))
.output()
.expect(&format!("Could not spawn: {}", tool))
.status
.success()
{
panic!("Could not compile: {}", impl_path.to_str().unwrap());
}
if !std::process::Command::new("ar")
.arg("rcs")
.arg(&lib_path)
.arg(&obj_path)
.output()
.expect(&format!("Could not create library: {}", lib_path.to_str().unwrap()))
.status
.success()
{
panic!("Could not create library: {}", lib_path.to_str().unwrap());
}
let bindings = bindgen::Builder::default()
.header(header_path_str)
.clang_arg(format!("-I{}", include_dir.to_str().unwrap()))
.clang_arg(format!("-L{}", out_dir.to_str().unwrap()))
.clang_arg(format!("-l{}", name));
let bind = bindings.generate().expect("Unable to generate bindings");
bind.write_to_file(out_file).expect("Couldn't write bindings!");
}
fn main() {
let out = get_out_dir();
build(out, "jstring", "clang");
}