blob: 9e4dff5b0fd8d6a9c0a286c4cced486914da3209 [file] [log] [blame]
extern crate cc;
use std::env;
use std::fs::File;
use std::path::PathBuf;
fn main() {
let target = env::var("TARGET").unwrap();
if target.contains("msvc") || // libbacktrace isn't used on MSVC windows
target.contains("emscripten") || // no way this will ever compile for emscripten
target.contains("cloudabi") ||
target.contains("wasm32") ||
target.contains("fuchsia")
// fuchsia uses external out-of-process symbolization
{
println!("cargo:rustc-cfg=empty");
return;
}
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let mut build = cc::Build::new();
build
.include("src/libbacktrace")
.include(&out_dir)
.warnings(false)
.file("src/libbacktrace/alloc.c")
.file("src/libbacktrace/dwarf.c")
.file("src/libbacktrace/fileline.c")
.file("src/libbacktrace/posix.c")
.file("src/libbacktrace/read.c")
.file("src/libbacktrace/sort.c")
.file("src/libbacktrace/state.c");
// No need to have any symbols reexported form shared objects
build.flag("-fvisibility=hidden");
if target.contains("darwin") {
build.file("src/libbacktrace/macho.c");
} else if target.contains("windows") {
build.file("src/libbacktrace/pecoff.c");
} else {
build.file("src/libbacktrace/elf.c");
let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
if pointer_width == "64" {
build.define("BACKTRACE_ELF_SIZE", "64");
} else {
build.define("BACKTRACE_ELF_SIZE", "32");
}
}
File::create(out_dir.join("backtrace-supported.h")).unwrap();
build.define("BACKTRACE_SUPPORTED", "1");
build.define("BACKTRACE_USES_MALLOC", "1");
build.define("BACKTRACE_SUPPORTS_THREADS", "0");
build.define("BACKTRACE_SUPPORTS_DATA", "0");
File::create(out_dir.join("config.h")).unwrap();
if target.contains("android") {
maybe_enable_dl_iterate_phdr_android(&mut build);
} else if !target.contains("apple-ios")
&& !target.contains("solaris")
&& !target.contains("redox")
&& !target.contains("haiku")
&& !target.contains("vxworks")
{
build.define("HAVE_DL_ITERATE_PHDR", "1");
}
build.define("_GNU_SOURCE", "1");
build.define("_LARGE_FILES", "1");
// When we're built as part of the Rust compiler, this is used to enable
// debug information in libbacktrace itself.
let any_debug = env::var("RUSTC_DEBUGINFO").unwrap_or_default() == "true"
|| env::var("RUSTC_DEBUGINFO_LINES").unwrap_or_default() == "true";
build.debug(any_debug);
let syms = [
"backtrace_full",
"backtrace_dwarf_add",
"backtrace_initialize",
"backtrace_pcinfo",
"backtrace_syminfo",
"backtrace_get_view",
"backtrace_release_view",
"backtrace_alloc",
"backtrace_free",
"backtrace_vector_finish",
"backtrace_vector_grow",
"backtrace_vector_release",
"backtrace_close",
"backtrace_open",
"backtrace_print",
"backtrace_simple",
"backtrace_qsort",
"backtrace_create_state",
"backtrace_uncompress_zdebug",
// These should be `static` in C, but they aren't...
"macho_get_view",
"macho_symbol_type_relevant",
"macho_get_commands",
"macho_try_dsym",
"macho_try_dwarf",
"macho_get_addr_range",
"macho_get_uuid",
"macho_add",
"macho_add_symtab",
"macho_file_to_host_u64",
"macho_file_to_host_u32",
"macho_file_to_host_u16",
];
let prefix = if cfg!(feature = "rustc-dep-of-std") {
println!("cargo:rustc-cfg=rdos");
"__rdos_"
} else {
println!("cargo:rustc-cfg=rbt");
"__rbt_"
};
for sym in syms.iter() {
build.define(sym, &format!("{}{}", prefix, sym)[..]);
}
build.compile("backtrace");
}
// The `dl_iterate_phdr` API was added in Android API 21+ (according to #227),
// so if we can dynamically detect an appropriately configured C compiler for
// that then let's enable the `dl_iterate_phdr` API, otherwise Android just
// won't have any information.
fn maybe_enable_dl_iterate_phdr_android(build: &mut cc::Build) {
let expansion = cc::Build::new().file("src/android-api.c").expand();
let expansion = match std::str::from_utf8(&expansion) {
Ok(s) => s,
Err(_) => return,
};
println!("expanded android version detection:\n{}", expansion);
let marker = "APIVERSION";
let i = match expansion.find(marker) {
Some(i) => i,
None => return,
};
let version = match expansion[i + marker.len() + 1..].split_whitespace().next() {
Some(s) => s,
None => return,
};
let version = match version.parse::<u32>() {
Ok(n) => n,
Err(_) => return,
};
if version >= 21 {
build.define("HAVE_DL_ITERATE_PHDR", "1");
}
}