use std::env;
use std::ffi::OsString;
use std::path::Path;
use std::process::{self, Command, Stdio};
use std::str;
use std::u32;
fn main() {
let rustc = rustc_minor_version().unwrap_or(u32::MAX);
let docs_rs = env::var_os("DOCS_RS").is_some();
let semver_exempt = cfg!(procmacro2_semver_exempt) || docs_rs;
if semver_exempt {
println!("cargo:rustc-cfg=procmacro2_semver_exempt");
}
if semver_exempt || cfg!(feature = "span-locations") {
println!("cargo:rustc-cfg=span_locations");
}
if rustc < 57 {
println!("cargo:rustc-cfg=no_is_available");
}
if rustc < 66 {
println!("cargo:rustc-cfg=no_source_text");
}
if !cfg!(feature = "proc-macro") {
println!("cargo:rerun-if-changed=build.rs");
return;
}
println!("cargo:rerun-if-changed=build/probe.rs");
let proc_macro_span;
let consider_rustc_bootstrap;
if compile_probe(false) {
proc_macro_span = true;
consider_rustc_bootstrap = false;
} else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") {
if compile_probe(true) {
proc_macro_span = true;
consider_rustc_bootstrap = true;
} else if rustc_bootstrap == "1" {
proc_macro_span = false;
consider_rustc_bootstrap = false;
} else {
proc_macro_span = false;
consider_rustc_bootstrap = true;
}
} else {
proc_macro_span = false;
consider_rustc_bootstrap = true;
}
if proc_macro_span || !semver_exempt {
println!("cargo:rustc-cfg=wrap_proc_macro");
}
if proc_macro_span {
println!("cargo:rustc-cfg=proc_macro_span");
}
if semver_exempt && proc_macro_span {
println!("cargo:rustc-cfg=super_unstable");
}
if consider_rustc_bootstrap {
println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP");
}
}
fn compile_probe(rustc_bootstrap: bool) -> bool {
if env::var_os("RUSTC_STAGE").is_some() {
return false;
}
let rustc = cargo_env_var("RUSTC");
let out_dir = cargo_env_var("OUT_DIR");
let probefile = Path::new("build").join("probe.rs");
let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") {
let mut cmd = Command::new(wrapper);
cmd.arg(rustc);
cmd
} else {
Command::new(rustc)
};
if !rustc_bootstrap {
cmd.env_remove("RUSTC_BOOTSTRAP");
}
cmd.stderr(Stdio::null())
.arg("--edition=2021")
.arg("--crate-name=proc_macro2")
.arg("--crate-type=lib")
.arg("--emit=metadata")
.arg("--out-dir")
.arg(out_dir)
.arg(probefile);
if let Some(target) = env::var_os("TARGET") {
cmd.arg("--target").arg(target);
}
if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") {
if !rustflags.is_empty() {
for arg in rustflags.split('\x1f') {
cmd.arg(arg);
}
}
}
match cmd.status() {
Ok(status) => status.success(),
Err(_) => false,
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = cargo_env_var("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()
}
fn cargo_env_var(key: &str) -> OsString {
env::var_os(key).unwrap_or_else(|| {
eprintln!(
"Environment variable ${} is not set during execution of build script",
key,
);
process::exit(1);
})
}