|  | use std::env; | 
|  | use std::fs; | 
|  | use std::path::Path; | 
|  | use std::process::{Command, ExitStatus, Stdio}; | 
|  | use std::str; | 
|  |  | 
|  | // This code exercises the surface area that we expect of the std Backtrace | 
|  | // type. If the current toolchain is able to compile it, we go ahead and use | 
|  | // backtrace in anyhow. | 
|  | const PROBE: &str = r#" | 
|  | #![feature(backtrace)] | 
|  | #![allow(dead_code)] | 
|  |  | 
|  | use std::backtrace::{Backtrace, BacktraceStatus}; | 
|  | use std::error::Error; | 
|  | use std::fmt::{self, Display}; | 
|  |  | 
|  | #[derive(Debug)] | 
|  | struct E; | 
|  |  | 
|  | impl Display for E { | 
|  | fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { | 
|  | unimplemented!() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Error for E { | 
|  | fn backtrace(&self) -> Option<&Backtrace> { | 
|  | let backtrace = Backtrace::capture(); | 
|  | match backtrace.status() { | 
|  | BacktraceStatus::Captured | BacktraceStatus::Disabled | _ => {} | 
|  | } | 
|  | unimplemented!() | 
|  | } | 
|  | } | 
|  | "#; | 
|  |  | 
|  | fn main() { | 
|  | if cfg!(feature = "std") { | 
|  | match compile_probe() { | 
|  | Some(status) if status.success() => println!("cargo:rustc-cfg=backtrace"), | 
|  | _ => {} | 
|  | } | 
|  | } | 
|  |  | 
|  | let rustc = match rustc_minor_version() { | 
|  | Some(rustc) => rustc, | 
|  | None => return, | 
|  | }; | 
|  |  | 
|  | if rustc < 38 { | 
|  | println!("cargo:rustc-cfg=anyhow_no_macro_reexport"); | 
|  | } | 
|  | } | 
|  |  | 
|  | fn compile_probe() -> Option<ExitStatus> { | 
|  | let rustc = env::var_os("RUSTC")?; | 
|  | let out_dir = env::var_os("OUT_DIR")?; | 
|  | let probefile = Path::new(&out_dir).join("probe.rs"); | 
|  | fs::write(&probefile, PROBE).ok()?; | 
|  | Command::new(rustc) | 
|  | .stderr(Stdio::null()) | 
|  | .arg("--edition=2018") | 
|  | .arg("--crate-name=anyhow_build") | 
|  | .arg("--crate-type=lib") | 
|  | .arg("--emit=metadata") | 
|  | .arg("--out-dir") | 
|  | .arg(out_dir) | 
|  | .arg(probefile) | 
|  | .status() | 
|  | .ok() | 
|  | } | 
|  |  | 
|  | fn rustc_minor_version() -> Option<u32> { | 
|  | let rustc = env::var_os("RUSTC")?; | 
|  | let output = Command::new(rustc).arg("--version").output().ok()?; | 
|  | let version = str::from_utf8(&output.stdout).ok()?; | 
|  | let mut pieces = version.split('.'); | 
|  | if pieces.next() != Some("rustc 1") { | 
|  | return None; | 
|  | } | 
|  | pieces.next()?.parse().ok() | 
|  | } |