extern crate gcc;
use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use std::process::Command;
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}", stringify!($e), e),
})
}
fn main() {
let src = env::current_dir().unwrap();
let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
if target.contains("darwin") {
return
}
if target.contains("windows") {
return
}
if target.contains("emscripten") {
return
}
let cfg = gcc::Config::new();
let compiler = cfg.get_compiler();
let mut flags = OsString::new();
for (i, flag) in compiler.args().iter().enumerate() {
if i > 0 {
flags.push(" ");
}
flags.push(flag);
}
run(Command::new(src.join("src/libbacktrace/configure"))
.current_dir(&dst)
.env("CC", compiler.path())
.env("CFLAGS", flags)
.arg("--with-pic")
.arg("--disable-multilib")
.arg("--disable-shared")
.arg("--disable-host-shared")
.arg(format!("--target={}", target))
.arg(format!("--host={}", host)));
run(Command::new("make")
.current_dir(&dst)
.arg(format!("INCDIR={}",
src.join("src/libbacktrace").display())));
println!("cargo:rustc-link-search=native={}/.libs", dst.display());
println!("cargo:rustc-link-lib=static=backtrace");
let lib = dst.join(".libs/libbacktrace.a");
let tmpdir = dst.join("__tmp");
drop(fs::remove_dir_all(&tmpdir));
t!(fs::create_dir_all(&tmpdir));
run(Command::new("ar").arg("x").arg(&lib).current_dir(&tmpdir));
t!(fs::remove_file(&lib));
let mut objs = Vec::new();
for obj in t!(tmpdir.read_dir()) {
let obj = t!(obj);
run(Command::new("objcopy")
.arg("--redefine-syms=symbol-map")
.arg(obj.path()));
objs.push(obj.path());
}
run(Command::new("ar").arg("crus").arg(&lib).args(&objs));
}
fn run(cmd: &mut Command) {
println!("running: {:?}", cmd);
let status = match cmd.status() {
Ok(s) => s,
Err(e) => panic!("failed to get status: {}", e),
};
if !status.success() {
panic!("failed with: {}", status);
}
}