Newer
Older
vengine / external / rpmalloc-sys / build.rs
Maple Nebel Maple Nebel 9 days ago 4 KB things
#![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!");
}