#![feature(path_absolute_method)]
use std::collections::HashSet;
use std::env;
use std::fs::create_dir_all;
use std::path::PathBuf;
use std::process::Command;
use git2::Repository;
fn get_repo(url: &str, refspec: &str) -> Repository {
let name = url.rsplit_once("/").map(|l| l.1).unwrap_or(url);
let path = {
let mut tmp = env::current_dir().expect("invalid working dir");
tmp.push(".external-store");
create_dir_all(&tmp).expect("unable to create directory");
tmp.push(name);
tmp
};
let repo = Repository::open(&path)
.unwrap_or_else(|_| Repository::clone(url, &path).expect("failed to clone"));
repo.remote("origin", url).ok();
repo.remote_set_url("origin", url).ok();
let mut remote = repo.find_remote("origin").expect("no origin remote");
remote
.fetch(&[refspec], None, None)
.expect("unable to fetch from remote");
let (object, reference) = repo.revparse_ext(refspec).expect("unable to find refspec");
repo.checkout_tree(&object, None)
.expect("failed to checkout");
if let Some(reference) = reference.as_ref() {
repo.set_head(reference.name().expect("unable to get name of reference"))
.ok();
} else {
repo.set_head_detached(object.id()).ok();
}
drop(reference);
drop(remote);
drop(object);
repo
}
fn main() {
println!("cargo:rerun-if-env-changed=CARGO_CFG_FEATURE");
println!("cargo:rerun-if-changes=Cargo.toml");
println!("cargo:rerun-if-changes=build.rs");
let featureset: HashSet<String> = env::var("CARGO_CFG_FEATURE")
.unwrap()
.split(",")
.map(|v| v.to_owned())
.collect();
if featureset.contains("statistics") {
unsafe { env::set_var("ENABLE_STATISTICS", "1") };
}
let repo = get_repo("https://github.com/mjansson/rpmalloc.git", "2.0.1");
let path = {
let mut path = PathBuf::from(repo.path());
path.pop();
path
};
//let tmp_curdir = env::current_dir().expect("unable to get current dir");
env::set_current_dir(&path).expect("failed to set dir");
let os = env::var("CARGO_CFG_TARGET_OS").expect("os not set");
let arch = env::var("CARGO_CFG_TARGET_ARCH")
.expect("architecture not set")
.replace("_", "-");
let cmd = Command::new("python3")
.args(["./configure.py", "--toolchain", "clang", "--lto", "-a"])
.arg(&arch)
.arg("-t")
.arg(&os)
.args(["-c", "release"])
.spawn()
.expect("failed to start configure")
.wait()
.expect("failed to run configure");
if cmd.code() != Some(0) {
panic!("failed to configure with exit code: {:?}", cmd.code());
}
let cmd = Command::new("ninja")
.arg("-j")
.arg(format!("{}", num_cpus::get()))
.spawn()
.expect("failed to spawn ninja")
.wait()
.expect("failed to wait on ninja");
if cmd.code() != Some(0) {
panic!("failed to compile with exit code: {:?}", cmd.code());
}
let libpath = {
let mut path = path.clone();
path.push("lib");
path.push(&os);
path.push("release");
path.push(&arch);
path
};
println!(
"cargo:rustc-link-search={}",
libpath
.absolute()
.unwrap()
.to_str()
.expect("unable to convert path to string")
);
println!("cargo:rustc-link-lib=rpmalloc");
let headerpath = {
let mut path = path.clone();
path.push("rpmalloc");
path.push("rpmalloc.h");
path
};
let bindings = bindgen::Builder::default().header(
headerpath
.to_str()
.expect("unable to convert path to string"),
);
let bindings = if featureset.contains("statistics") {
bindings.clang_arg("-DENABLE_STATISTICS=1")
} else {
bindings
};
let bindings = bindings
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}