|  | 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"); | 
|  | } | 
|  | } |