diff --git a/tokio/build.rs b/tokio/build.rs index 93b05092bf9..503c0242fc8 100644 --- a/tokio/build.rs +++ b/tokio/build.rs @@ -24,10 +24,25 @@ const CONST_MUTEX_NEW_PROBE: &str = r#" } "#; +const TARGET_HAS_ATOMIC_PROBE: &str = r#" +{ + #[cfg(target_has_atomic = "ptr")] + let _ = (); +} +"#; + +const TARGET_ATOMIC_U64_PROBE: &str = r#" +{ + use std::sync::atomic::AtomicU64 as _; +} +"#; + fn main() { let mut enable_const_thread_local = false; let mut enable_addr_of = false; + let mut enable_target_has_atomic = false; let mut enable_const_mutex_new = false; + let mut target_needs_atomic_u64_fallback = false; match AutoCfg::new() { Ok(ac) => { @@ -66,6 +81,27 @@ fn main() { } } + // The `target_has_atomic` cfg was stabilized in 1.60. + if ac.probe_rustc_version(1, 61) { + enable_target_has_atomic = true; + } else if ac.probe_rustc_version(1, 60) { + // This compiler claims to be 1.60, but there are some nightly + // compilers that claim to be 1.60 without supporting the + // feature. Explicitly probe to check if code using them + // compiles. + // + // The oldest nightly that supports the feature is 2022-02-11. + if ac.probe_expression(TARGET_HAS_ATOMIC_PROBE) { + enable_target_has_atomic = true; + } + } + + // If we can't tell using `target_has_atomic`, tell if the target + // has `AtomicU64` by trying to use it. + if !enable_target_has_atomic && !ac.probe_expression(TARGET_ATOMIC_U64_PROBE) { + target_needs_atomic_u64_fallback = true; + } + // The `Mutex::new` method was made const in 1.63. if ac.probe_rustc_version(1, 64) { enable_const_mutex_new = true; @@ -109,6 +145,14 @@ fn main() { autocfg::emit("tokio_no_addr_of") } + if !enable_target_has_atomic { + // To disable this feature on compilers that support it, you can + // explicitly pass this flag with the following environment variable: + // + // RUSTFLAGS="--cfg tokio_no_target_has_atomic" + autocfg::emit("tokio_no_target_has_atomic") + } + if !enable_const_mutex_new { // To disable this feature on compilers that support it, you can // explicitly pass this flag with the following environment variable: @@ -117,6 +161,14 @@ fn main() { autocfg::emit("tokio_no_const_mutex_new") } + if target_needs_atomic_u64_fallback { + // To disable this feature on compilers that support it, you can + // explicitly pass this flag with the following environment variable: + // + // RUSTFLAGS="--cfg tokio_no_atomic_u64" + autocfg::emit("tokio_no_atomic_u64") + } + let target = ::std::env::var("TARGET").unwrap_or_default(); // We emit cfgs instead of using `target_family = "wasm"` that requires Rust 1.54. diff --git a/tokio/src/macros/cfg.rs b/tokio/src/macros/cfg.rs index 2eea344b516..1c66d24147a 100644 --- a/tokio/src/macros/cfg.rs +++ b/tokio/src/macros/cfg.rs @@ -461,14 +461,14 @@ macro_rules! cfg_not_coop { macro_rules! cfg_has_atomic_u64 { ($($item:item)*) => { $( - #[cfg(not(any( - target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc", - target_arch = "riscv32", - tokio_wasm, - tokio_no_atomic_u64, - )))] + #[cfg_attr( + not(tokio_no_target_has_atomic), + cfg(all(target_has_atomic = "64", not(tokio_no_atomic_u64)) + ))] + #[cfg_attr( + tokio_no_target_has_atomic, + cfg(not(tokio_no_atomic_u64)) + )] $item )* } @@ -477,14 +477,14 @@ macro_rules! cfg_has_atomic_u64 { macro_rules! cfg_not_has_atomic_u64 { ($($item:item)*) => { $( - #[cfg(any( - target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc", - target_arch = "riscv32", - tokio_wasm, - tokio_no_atomic_u64, + #[cfg_attr( + not(tokio_no_target_has_atomic), + cfg(any(not(target_has_atomic = "64"), tokio_no_atomic_u64) ))] + #[cfg_attr( + tokio_no_target_has_atomic, + cfg(tokio_no_atomic_u64) + )] $item )* }