| 1 | use std::env; |
| 2 | use std::process::Command; |
| 3 | use std::str::{self, FromStr}; |
| 4 | |
| 5 | // The rustc-cfg strings below are *not* public API. Please let us know by |
| 6 | // opening a GitHub issue if your build environment requires some way to enable |
| 7 | // these cfgs other than by executing our build script. |
| 8 | fn main() { |
| 9 | println!("cargo:rerun-if-changed=build.rs" ); |
| 10 | |
| 11 | let minor = match rustc_minor_version() { |
| 12 | Some(minor) => minor, |
| 13 | None => return, |
| 14 | }; |
| 15 | |
| 16 | let target = env::var("TARGET" ).unwrap(); |
| 17 | let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten" ; |
| 18 | |
| 19 | // TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add |
| 20 | // stabilized in Rust 1.34: |
| 21 | // https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto |
| 22 | // https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations |
| 23 | if minor < 34 { |
| 24 | println!("cargo:rustc-cfg=no_core_try_from" ); |
| 25 | println!("cargo:rustc-cfg=no_num_nonzero_signed" ); |
| 26 | println!("cargo:rustc-cfg=no_systemtime_checked_add" ); |
| 27 | println!("cargo:rustc-cfg=no_relaxed_trait_bounds" ); |
| 28 | } |
| 29 | |
| 30 | // f32::copysign and f64::copysign stabilized in Rust 1.35. |
| 31 | // https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html#copy-the-sign-of-a-floating-point-number-onto-another |
| 32 | if minor < 35 { |
| 33 | println!("cargo:rustc-cfg=no_float_copysign" ); |
| 34 | } |
| 35 | |
| 36 | // Current minimum supported version of serde_derive crate is Rust 1.56. |
| 37 | if minor < 56 { |
| 38 | println!("cargo:rustc-cfg=no_serde_derive" ); |
| 39 | } |
| 40 | |
| 41 | // Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60. |
| 42 | if minor < 60 { |
| 43 | println!("cargo:rustc-cfg=no_target_has_atomic" ); |
| 44 | // Allowlist of archs that support std::sync::atomic module. This is |
| 45 | // based on rustc's compiler/rustc_target/src/spec/*.rs. |
| 46 | let has_atomic64 = target.starts_with("x86_64" ) |
| 47 | || target.starts_with("i686" ) |
| 48 | || target.starts_with("aarch64" ) |
| 49 | || target.starts_with("powerpc64" ) |
| 50 | || target.starts_with("sparc64" ) |
| 51 | || target.starts_with("mips64el" ) |
| 52 | || target.starts_with("riscv64" ); |
| 53 | let has_atomic32 = has_atomic64 || emscripten; |
| 54 | if minor < 34 || !has_atomic64 { |
| 55 | println!("cargo:rustc-cfg=no_std_atomic64" ); |
| 56 | } |
| 57 | if minor < 34 || !has_atomic32 { |
| 58 | println!("cargo:rustc-cfg=no_std_atomic" ); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | // Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64. |
| 63 | // https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc |
| 64 | if minor < 64 { |
| 65 | println!("cargo:rustc-cfg=no_core_cstr" ); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | fn rustc_minor_version() -> Option<u32> { |
| 70 | let rustc = match env::var_os("RUSTC" ) { |
| 71 | Some(rustc) => rustc, |
| 72 | None => return None, |
| 73 | }; |
| 74 | |
| 75 | let output = match Command::new(rustc).arg("--version" ).output() { |
| 76 | Ok(output) => output, |
| 77 | Err(_) => return None, |
| 78 | }; |
| 79 | |
| 80 | let version = match str::from_utf8(&output.stdout) { |
| 81 | Ok(version) => version, |
| 82 | Err(_) => return None, |
| 83 | }; |
| 84 | |
| 85 | let mut pieces = version.split('.' ); |
| 86 | if pieces.next() != Some("rustc 1" ) { |
| 87 | return None; |
| 88 | } |
| 89 | |
| 90 | let next = match pieces.next() { |
| 91 | Some(next) => next, |
| 92 | None => return None, |
| 93 | }; |
| 94 | |
| 95 | u32::from_str(next).ok() |
| 96 | } |
| 97 | |