17ac06127Sopenharmony_ci// rustc-cfg emitted by the build script:
27ac06127Sopenharmony_ci//
37ac06127Sopenharmony_ci// "wrap_proc_macro"
47ac06127Sopenharmony_ci//     Wrap types from libproc_macro rather than polyfilling the whole API.
57ac06127Sopenharmony_ci//     Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
67ac06127Sopenharmony_ci//     because we can't emulate the unstable API without emulating everything
77ac06127Sopenharmony_ci//     else. Also enabled unconditionally on nightly, in which case the
87ac06127Sopenharmony_ci//     procmacro2_semver_exempt surface area is implemented by using the
97ac06127Sopenharmony_ci//     nightly-only proc_macro API.
107ac06127Sopenharmony_ci//
117ac06127Sopenharmony_ci// "hygiene"
127ac06127Sopenharmony_ci//    Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at
137ac06127Sopenharmony_ci//    and Span::located_at. Enabled on Rust 1.45+.
147ac06127Sopenharmony_ci//
157ac06127Sopenharmony_ci// "proc_macro_span"
167ac06127Sopenharmony_ci//     Enable non-dummy behavior of Span::start and Span::end methods which
177ac06127Sopenharmony_ci//     requires an unstable compiler feature. Enabled when building with
187ac06127Sopenharmony_ci//     nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable
197ac06127Sopenharmony_ci//     features.
207ac06127Sopenharmony_ci//
217ac06127Sopenharmony_ci// "super_unstable"
227ac06127Sopenharmony_ci//     Implement the semver exempt API in terms of the nightly-only proc_macro
237ac06127Sopenharmony_ci//     API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
247ac06127Sopenharmony_ci//
257ac06127Sopenharmony_ci// "span_locations"
267ac06127Sopenharmony_ci//     Provide methods Span::start and Span::end which give the line/column
277ac06127Sopenharmony_ci//     location of a token. Enabled by procmacro2_semver_exempt or the
287ac06127Sopenharmony_ci//     "span-locations" Cargo cfg. This is behind a cfg because tracking
297ac06127Sopenharmony_ci//     location inside spans is a performance hit.
307ac06127Sopenharmony_ci//
317ac06127Sopenharmony_ci// "is_available"
327ac06127Sopenharmony_ci//     Use proc_macro::is_available() to detect if the proc macro API is
337ac06127Sopenharmony_ci//     available or needs to be polyfilled instead of trying to use the proc
347ac06127Sopenharmony_ci//     macro API and catching a panic if it isn't available. Enabled on Rust
357ac06127Sopenharmony_ci//     1.57+.
367ac06127Sopenharmony_ci
377ac06127Sopenharmony_ciuse std::env;
387ac06127Sopenharmony_ciuse std::ffi::OsString;
397ac06127Sopenharmony_ciuse std::path::Path;
407ac06127Sopenharmony_ciuse std::process::{self, Command, Stdio};
417ac06127Sopenharmony_ciuse std::str;
427ac06127Sopenharmony_ciuse std::u32;
437ac06127Sopenharmony_ci
447ac06127Sopenharmony_cifn main() {
457ac06127Sopenharmony_ci    let rustc = rustc_minor_version().unwrap_or(u32::MAX);
467ac06127Sopenharmony_ci
477ac06127Sopenharmony_ci    let docs_rs = env::var_os("DOCS_RS").is_some();
487ac06127Sopenharmony_ci    let semver_exempt = cfg!(procmacro2_semver_exempt) || docs_rs;
497ac06127Sopenharmony_ci    if semver_exempt {
507ac06127Sopenharmony_ci        // https://github.com/dtolnay/proc-macro2/issues/147
517ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=procmacro2_semver_exempt");
527ac06127Sopenharmony_ci    }
537ac06127Sopenharmony_ci
547ac06127Sopenharmony_ci    if semver_exempt || cfg!(feature = "span-locations") {
557ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=span_locations");
567ac06127Sopenharmony_ci    }
577ac06127Sopenharmony_ci
587ac06127Sopenharmony_ci    if rustc < 57 {
597ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=no_is_available");
607ac06127Sopenharmony_ci    }
617ac06127Sopenharmony_ci
627ac06127Sopenharmony_ci    if rustc < 66 {
637ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=no_source_text");
647ac06127Sopenharmony_ci    }
657ac06127Sopenharmony_ci
667ac06127Sopenharmony_ci    if !cfg!(feature = "proc-macro") {
677ac06127Sopenharmony_ci        println!("cargo:rerun-if-changed=build.rs");
687ac06127Sopenharmony_ci        return;
697ac06127Sopenharmony_ci    }
707ac06127Sopenharmony_ci
717ac06127Sopenharmony_ci    println!("cargo:rerun-if-changed=build/probe.rs");
727ac06127Sopenharmony_ci
737ac06127Sopenharmony_ci    let proc_macro_span;
747ac06127Sopenharmony_ci    let consider_rustc_bootstrap;
757ac06127Sopenharmony_ci    if compile_probe(false) {
767ac06127Sopenharmony_ci        // This is a nightly or dev compiler, so it supports unstable features
777ac06127Sopenharmony_ci        // regardless of RUSTC_BOOTSTRAP. No need to rerun build script if
787ac06127Sopenharmony_ci        // RUSTC_BOOTSTRAP is changed.
797ac06127Sopenharmony_ci        proc_macro_span = true;
807ac06127Sopenharmony_ci        consider_rustc_bootstrap = false;
817ac06127Sopenharmony_ci    } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") {
827ac06127Sopenharmony_ci        if compile_probe(true) {
837ac06127Sopenharmony_ci            // This is a stable or beta compiler for which the user has set
847ac06127Sopenharmony_ci            // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build script
857ac06127Sopenharmony_ci            // if they change it.
867ac06127Sopenharmony_ci            proc_macro_span = true;
877ac06127Sopenharmony_ci            consider_rustc_bootstrap = true;
887ac06127Sopenharmony_ci        } else if rustc_bootstrap == "1" {
897ac06127Sopenharmony_ci            // This compiler does not support the proc macro Span API in the
907ac06127Sopenharmony_ci            // form that proc-macro2 expects. No need to pay attention to
917ac06127Sopenharmony_ci            // RUSTC_BOOTSTRAP.
927ac06127Sopenharmony_ci            proc_macro_span = false;
937ac06127Sopenharmony_ci            consider_rustc_bootstrap = false;
947ac06127Sopenharmony_ci        } else {
957ac06127Sopenharmony_ci            // This is a stable or beta compiler for which RUSTC_BOOTSTRAP is
967ac06127Sopenharmony_ci            // set to restrict the use of unstable features by this crate.
977ac06127Sopenharmony_ci            proc_macro_span = false;
987ac06127Sopenharmony_ci            consider_rustc_bootstrap = true;
997ac06127Sopenharmony_ci        }
1007ac06127Sopenharmony_ci    } else {
1017ac06127Sopenharmony_ci        // Without RUSTC_BOOTSTRAP, this compiler does not support the proc
1027ac06127Sopenharmony_ci        // macro Span API in the form that proc-macro2 expects, but try again if
1037ac06127Sopenharmony_ci        // the user turns on unstable features.
1047ac06127Sopenharmony_ci        proc_macro_span = false;
1057ac06127Sopenharmony_ci        consider_rustc_bootstrap = true;
1067ac06127Sopenharmony_ci    }
1077ac06127Sopenharmony_ci
1087ac06127Sopenharmony_ci    if proc_macro_span || !semver_exempt {
1097ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=wrap_proc_macro");
1107ac06127Sopenharmony_ci    }
1117ac06127Sopenharmony_ci
1127ac06127Sopenharmony_ci    if proc_macro_span {
1137ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=proc_macro_span");
1147ac06127Sopenharmony_ci    }
1157ac06127Sopenharmony_ci
1167ac06127Sopenharmony_ci    if semver_exempt && proc_macro_span {
1177ac06127Sopenharmony_ci        println!("cargo:rustc-cfg=super_unstable");
1187ac06127Sopenharmony_ci    }
1197ac06127Sopenharmony_ci
1207ac06127Sopenharmony_ci    if consider_rustc_bootstrap {
1217ac06127Sopenharmony_ci        println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP");
1227ac06127Sopenharmony_ci    }
1237ac06127Sopenharmony_ci}
1247ac06127Sopenharmony_ci
1257ac06127Sopenharmony_cifn compile_probe(rustc_bootstrap: bool) -> bool {
1267ac06127Sopenharmony_ci    if env::var_os("RUSTC_STAGE").is_some() {
1277ac06127Sopenharmony_ci        // We are running inside rustc bootstrap. This is a highly non-standard
1287ac06127Sopenharmony_ci        // environment with issues such as:
1297ac06127Sopenharmony_ci        //
1307ac06127Sopenharmony_ci        //     https://github.com/rust-lang/cargo/issues/11138
1317ac06127Sopenharmony_ci        //     https://github.com/rust-lang/rust/issues/114839
1327ac06127Sopenharmony_ci        //
1337ac06127Sopenharmony_ci        // Let's just not use nightly features here.
1347ac06127Sopenharmony_ci        return false;
1357ac06127Sopenharmony_ci    }
1367ac06127Sopenharmony_ci
1377ac06127Sopenharmony_ci    let rustc = cargo_env_var("RUSTC");
1387ac06127Sopenharmony_ci    let out_dir = cargo_env_var("OUT_DIR");
1397ac06127Sopenharmony_ci    let probefile = Path::new("build").join("probe.rs");
1407ac06127Sopenharmony_ci
1417ac06127Sopenharmony_ci    // Make sure to pick up Cargo rustc configuration.
1427ac06127Sopenharmony_ci    let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") {
1437ac06127Sopenharmony_ci        let mut cmd = Command::new(wrapper);
1447ac06127Sopenharmony_ci        // The wrapper's first argument is supposed to be the path to rustc.
1457ac06127Sopenharmony_ci        cmd.arg(rustc);
1467ac06127Sopenharmony_ci        cmd
1477ac06127Sopenharmony_ci    } else {
1487ac06127Sopenharmony_ci        Command::new(rustc)
1497ac06127Sopenharmony_ci    };
1507ac06127Sopenharmony_ci
1517ac06127Sopenharmony_ci    if !rustc_bootstrap {
1527ac06127Sopenharmony_ci        cmd.env_remove("RUSTC_BOOTSTRAP");
1537ac06127Sopenharmony_ci    }
1547ac06127Sopenharmony_ci
1557ac06127Sopenharmony_ci    cmd.stderr(Stdio::null())
1567ac06127Sopenharmony_ci        .arg("--edition=2021")
1577ac06127Sopenharmony_ci        .arg("--crate-name=proc_macro2")
1587ac06127Sopenharmony_ci        .arg("--crate-type=lib")
1597ac06127Sopenharmony_ci        .arg("--emit=dep-info,metadata")
1607ac06127Sopenharmony_ci        .arg("--out-dir")
1617ac06127Sopenharmony_ci        .arg(out_dir)
1627ac06127Sopenharmony_ci        .arg(probefile);
1637ac06127Sopenharmony_ci
1647ac06127Sopenharmony_ci    if let Some(target) = env::var_os("TARGET") {
1657ac06127Sopenharmony_ci        cmd.arg("--target").arg(target);
1667ac06127Sopenharmony_ci    }
1677ac06127Sopenharmony_ci
1687ac06127Sopenharmony_ci    // If Cargo wants to set RUSTFLAGS, use that.
1697ac06127Sopenharmony_ci    if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") {
1707ac06127Sopenharmony_ci        if !rustflags.is_empty() {
1717ac06127Sopenharmony_ci            for arg in rustflags.split('\x1f') {
1727ac06127Sopenharmony_ci                cmd.arg(arg);
1737ac06127Sopenharmony_ci            }
1747ac06127Sopenharmony_ci        }
1757ac06127Sopenharmony_ci    }
1767ac06127Sopenharmony_ci
1777ac06127Sopenharmony_ci    match cmd.status() {
1787ac06127Sopenharmony_ci        Ok(status) => status.success(),
1797ac06127Sopenharmony_ci        Err(_) => false,
1807ac06127Sopenharmony_ci    }
1817ac06127Sopenharmony_ci}
1827ac06127Sopenharmony_ci
1837ac06127Sopenharmony_cifn rustc_minor_version() -> Option<u32> {
1847ac06127Sopenharmony_ci    let rustc = cargo_env_var("RUSTC");
1857ac06127Sopenharmony_ci    let output = Command::new(rustc).arg("--version").output().ok()?;
1867ac06127Sopenharmony_ci    let version = str::from_utf8(&output.stdout).ok()?;
1877ac06127Sopenharmony_ci    let mut pieces = version.split('.');
1887ac06127Sopenharmony_ci    if pieces.next() != Some("rustc 1") {
1897ac06127Sopenharmony_ci        return None;
1907ac06127Sopenharmony_ci    }
1917ac06127Sopenharmony_ci    pieces.next()?.parse().ok()
1927ac06127Sopenharmony_ci}
1937ac06127Sopenharmony_ci
1947ac06127Sopenharmony_cifn cargo_env_var(key: &str) -> OsString {
1957ac06127Sopenharmony_ci    env::var_os(key).unwrap_or_else(|| {
1967ac06127Sopenharmony_ci        eprintln!(
1977ac06127Sopenharmony_ci            "Environment variable ${} is not set during execution of build script",
1987ac06127Sopenharmony_ci            key,
1997ac06127Sopenharmony_ci        );
2007ac06127Sopenharmony_ci        process::exit(1);
2017ac06127Sopenharmony_ci    })
2027ac06127Sopenharmony_ci}
203