From d7ad23a7927c47cd4030427722d1eb9902d15af1 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 25 Dec 2020 13:46:18 +0900 Subject: [PATCH 1/3] Use autocfg instead of unstable feature(cfg_target_has_atomic) --- .github/workflows/ci.yml | 57 +++++------------------ Cargo.toml | 1 + futures-channel/Cargo.toml | 12 +++-- futures-channel/build.rs | 23 +++++++++ futures-channel/src/lib.rs | 7 +-- futures-core/Cargo.toml | 8 ++-- futures-core/build.rs | 23 +++++++++ futures-core/src/lib.rs | 5 -- futures-core/src/task/__internal/mod.rs | 4 +- futures-task/Cargo.toml | 8 ++-- futures-task/build.rs | 23 +++++++++ futures-task/src/lib.rs | 7 +-- futures-util/Cargo.toml | 8 +++- futures-util/build.rs | 23 +++++++++ futures-util/src/lib.rs | 6 +-- futures-util/src/stream/mod.rs | 6 +-- futures-util/src/stream/stream/mod.rs | 8 ++-- futures-util/src/stream/try_stream/mod.rs | 6 +-- futures/Cargo.toml | 8 +++- futures/build.rs | 23 +++++++++ futures/src/lib.rs | 4 -- futures/tests/no-std/Cargo.toml | 22 +++++++++ futures/tests/no-std/build.rs | 14 ++++++ futures/tests/no-std/src/lib.rs | 31 ++++++++++++ 24 files changed, 240 insertions(+), 97 deletions(-) create mode 100644 futures-channel/build.rs create mode 100644 futures-core/build.rs create mode 100644 futures-task/build.rs create mode 100644 futures-util/build.rs create mode 100644 futures/build.rs create mode 100644 futures/tests/no-std/Cargo.toml create mode 100644 futures/tests/no-std/build.rs create mode 100644 futures/tests/no-std/src/lib.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c4de8a949..0d810c54a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,59 +127,24 @@ jobs: - run: cargo update -Z minimal-versions - run: cargo build --workspace --all-features - thumbv6m: - name: cargo build --target thumbv6m-none-eabi - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install Rust - run: rustup update nightly && rustup default nightly - - run: rustup target add thumbv6m-none-eabi - - run: cargo install cargo-hack - # remove dev-dependencies to avoid https://github.com/rust-lang/cargo/issues/4866 - - run: cargo hack --remove-dev-deps --workspace - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv6m-none-eabi \ - --no-default-features \ - --features unstable,cfg-target-has-atomic - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv6m-none-eabi \ - --no-default-features \ - --features alloc,unstable,cfg-target-has-atomic - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv6m-none-eabi \ - --no-default-features \ - --features async-await,unstable,cfg-target-has-atomic - - thumbv7m: - name: cargo build --target thumbv7m-none-eabi + no-std: + name: cargo build --target ${{ matrix.target }} + strategy: + matrix: + target: + - thumbv6m-none-eabi + - thumbv7m-none-eabi runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install Rust run: rustup update nightly && rustup default nightly - - run: rustup target add thumbv7m-none-eabi + - run: rustup target add ${{ matrix.target }} - run: cargo install cargo-hack - # remove dev-dependencies to avoid https://github.com/rust-lang/cargo/issues/4866 - - run: cargo hack --remove-dev-deps --workspace - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv7m-none-eabi \ - --no-default-features \ - --features unstable,cfg-target-has-atomic - - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv7m-none-eabi \ - --no-default-features \ - --features alloc - run: | - cargo build --manifest-path futures/Cargo.toml \ - --target thumbv7m-none-eabi \ - --no-default-features \ - --features async-await + cargo hack build --manifest-path futures/tests/no-std/Cargo.toml \ + --each-feature --optional-deps \ + --target ${{ matrix.target }} bench: name: cargo bench diff --git a/Cargo.toml b/Cargo.toml index f972a73d2c..d27a9f2885 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ members = [ "futures/tests/macro-tests", "futures/tests/macro-reexport", + "futures/tests/no-std", "examples/functional", "examples/imperative", diff --git a/futures-channel/Cargo.toml b/futures-channel/Cargo.toml index dbdc0b765b..f38dcf540a 100644 --- a/futures-channel/Cargo.toml +++ b/futures-channel/Cargo.toml @@ -17,11 +17,13 @@ std = ["alloc", "futures-core/std"] alloc = ["futures-core/alloc"] sink = ["futures-sink"] -# Unstable features -# These features are outside of the normal semver guarantees and require the -# `unstable` feature as an explicit opt-in to unstable API. -unstable = ["futures-core/unstable"] -cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic"] +# These features are no longer used. +# TODO: remove in the next major version. +unstable = [] +cfg-target-has-atomic = [] + +[build-dependencies] +autocfg = "1" [dependencies] futures-core = { path = "../futures-core", version = "0.3.8", default-features = false } diff --git a/futures-channel/build.rs b/futures-channel/build.rs new file mode 100644 index 0000000000..43ddfeafd6 --- /dev/null +++ b/futures-channel/build.rs @@ -0,0 +1,23 @@ +use autocfg::AutoCfg; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let cfg = match AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + println!( + "cargo:warning={}: unable to determine rustc version: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=has_atomic_cas"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/futures-channel/src/lib.rs b/futures-channel/src/lib.rs index 22d90d8a63..15b804f5eb 100644 --- a/futures-channel/src/lib.rs +++ b/futures-channel/src/lib.rs @@ -11,8 +11,6 @@ //! All items are only available when the `std` or `alloc` feature of this //! library is activated, and it is activated by default. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] - #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -21,12 +19,9 @@ #![warn(clippy::all)] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] $item )*}; } diff --git a/futures-core/Cargo.toml b/futures-core/Cargo.toml index 530c557f57..6454e1e330 100644 --- a/futures-core/Cargo.toml +++ b/futures-core/Cargo.toml @@ -16,12 +16,14 @@ default = ["std"] std = ["alloc"] alloc = [] -# Unstable features -# These features are outside of the normal semver guarantees and require the -# `unstable` feature as an explicit opt-in to unstable API. +# These features are no longer used. +# TODO: remove in the next major version. unstable = [] cfg-target-has-atomic = [] +[build-dependencies] +autocfg = "1" + [dependencies] [dev-dependencies] diff --git a/futures-core/build.rs b/futures-core/build.rs new file mode 100644 index 0000000000..43ddfeafd6 --- /dev/null +++ b/futures-core/build.rs @@ -0,0 +1,23 @@ +use autocfg::AutoCfg; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let cfg = match AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + println!( + "cargo:warning={}: unable to determine rustc version: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=has_atomic_cas"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/futures-core/src/lib.rs b/futures-core/src/lib.rs index ec14adba22..d79ef386b3 100644 --- a/futures-core/src/lib.rs +++ b/futures-core/src/lib.rs @@ -1,7 +1,5 @@ //! Core traits and types for asynchronous operations in Rust. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] - #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -10,9 +8,6 @@ #![warn(clippy::all)] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(feature = "alloc")] extern crate alloc; diff --git a/futures-core/src/task/__internal/mod.rs b/futures-core/src/task/__internal/mod.rs index 77e3678075..0ef898c11e 100644 --- a/futures-core/src/task/__internal/mod.rs +++ b/futures-core/src/task/__internal/mod.rs @@ -1,4 +1,4 @@ -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(has_atomic_cas)] mod atomic_waker; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(has_atomic_cas)] pub use self::atomic_waker::AtomicWaker; diff --git a/futures-task/Cargo.toml b/futures-task/Cargo.toml index 4a8da101e9..cb9333d478 100644 --- a/futures-task/Cargo.toml +++ b/futures-task/Cargo.toml @@ -16,12 +16,14 @@ default = ["std"] std = ["alloc", "once_cell"] alloc = [] -# Unstable features -# These features are outside of the normal semver guarantees and require the -# `unstable` feature as an explicit opt-in to unstable API. +# These features are no longer used. +# TODO: remove in the next major version. unstable = [] cfg-target-has-atomic = [] +[build-dependencies] +autocfg = "1" + [dependencies] once_cell = { version = "1.3.1", default-features = false, features = ["std"], optional = true } diff --git a/futures-task/build.rs b/futures-task/build.rs new file mode 100644 index 0000000000..43ddfeafd6 --- /dev/null +++ b/futures-task/build.rs @@ -0,0 +1,23 @@ +use autocfg::AutoCfg; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let cfg = match AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + println!( + "cargo:warning={}: unable to determine rustc version: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=has_atomic_cas"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/futures-task/src/lib.rs b/futures-task/src/lib.rs index 92b4ad0d25..8b65cada3d 100644 --- a/futures-task/src/lib.rs +++ b/futures-task/src/lib.rs @@ -1,7 +1,5 @@ //! Tools for working with tasks. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] - #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -10,15 +8,12 @@ #![warn(clippy::all)] #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(feature = "alloc")] extern crate alloc; macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] $item )*}; } diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml index b4c7532d4f..3b30cd7405 100644 --- a/futures-util/Cargo.toml +++ b/futures-util/Cargo.toml @@ -27,11 +27,17 @@ channel = ["std", "futures-channel"] # These features are outside of the normal semver guarantees and require the # `unstable` feature as an explicit opt-in to unstable API. unstable = ["futures-core/unstable", "futures-task/unstable"] -cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic", "futures-task/cfg-target-has-atomic"] bilock = [] read-initializer = ["io", "futures-io/read-initializer", "futures-io/unstable"] write-all-vectored = ["io"] +# These features are no longer used. +# TODO: remove in the next major version. +cfg-target-has-atomic = [] + +[build-dependencies] +autocfg = "1" + [dependencies] futures-core = { path = "../futures-core", version = "0.3.8", default-features = false } futures-task = { path = "../futures-task", version = "0.3.8", default-features = false } diff --git a/futures-util/build.rs b/futures-util/build.rs new file mode 100644 index 0000000000..43ddfeafd6 --- /dev/null +++ b/futures-util/build.rs @@ -0,0 +1,23 @@ +use autocfg::AutoCfg; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let cfg = match AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + println!( + "cargo:warning={}: unable to determine rustc version: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=has_atomic_cas"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/futures-util/src/lib.rs b/futures-util/src/lib.rs index 44823cc7da..710906f3e3 100644 --- a/futures-util/src/lib.rs +++ b/futures-util/src/lib.rs @@ -1,7 +1,6 @@ //! Combinators and utilities for working with `Future`s, `Stream`s, `Sink`s, //! and the `AsyncRead` and `AsyncWrite` traits. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(feature = "read-initializer", feature(read_initializer))] #![cfg_attr(feature = "write-all-vectored", feature(io_slice_advance))] #![cfg_attr(not(feature = "std"), no_std)] @@ -17,9 +16,6 @@ #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] #![cfg_attr(docsrs, feature(doc_cfg))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(all(feature = "bilock", not(feature = "unstable")))] compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features"); @@ -58,7 +54,7 @@ pub mod __private { macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] $item )*}; } diff --git a/futures-util/src/stream/mod.rs b/futures-util/src/stream/mod.rs index a5624badac..45611ea81a 100644 --- a/futures-util/src/stream/mod.rs +++ b/futures-util/src/stream/mod.rs @@ -36,11 +36,11 @@ pub use self::stream::ReadyChunks; #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] pub use self::stream::Forward; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] pub use self::stream::{BufferUnordered, Buffered, ForEachConcurrent}; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(has_atomic_cas)] #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] #[cfg(feature = "alloc")] @@ -58,7 +58,7 @@ pub use self::try_stream::{ #[cfg(feature = "std")] pub use self::try_stream::IntoAsyncRead; -#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] +#[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] pub use self::try_stream::{TryBufferUnordered, TryBuffered, TryForEachConcurrent}; diff --git a/futures-util/src/stream/stream/mod.rs b/futures-util/src/stream/stream/mod.rs index b1b4384279..b6ce054400 100644 --- a/futures-util/src/stream/stream/mod.rs +++ b/futures-util/src/stream/stream/mod.rs @@ -917,7 +917,7 @@ pub trait StreamExt: Stream { /// fut.await; /// # }) /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn for_each_concurrent( self, @@ -1140,7 +1140,7 @@ pub trait StreamExt: Stream { /// /// This method is only available when the `std` or `alloc` feature of this /// library is activated, and it is activated by default. - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn buffered(self, n: usize) -> Buffered where @@ -1185,7 +1185,7 @@ pub trait StreamExt: Stream { /// assert_eq!(buffered.next().await, None); /// # Ok::<(), i32>(()) }).unwrap(); /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn buffer_unordered(self, n: usize) -> BufferUnordered where @@ -1349,7 +1349,7 @@ pub trait StreamExt: Stream { /// library is activated, and it is activated by default. #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn split(self) -> (SplitSink, SplitStream) where diff --git a/futures-util/src/stream/try_stream/mod.rs b/futures-util/src/stream/try_stream/mod.rs index 6a48a4c4b4..7870bdfe92 100644 --- a/futures-util/src/stream/try_stream/mod.rs +++ b/futures-util/src/stream/try_stream/mod.rs @@ -515,7 +515,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(Err(oneshot::Canceled), fut.await); /// # }) /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn try_for_each_concurrent( self, @@ -836,7 +836,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); /// # Ok::<(), Box>(()) }).unwrap(); /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered where @@ -912,7 +912,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); /// # Ok::<(), Box>(()) }).unwrap(); /// ``` - #[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))] + #[cfg(has_atomic_cas)] #[cfg(feature = "alloc")] fn try_buffered(self, n: usize) -> TryBuffered where diff --git a/futures/Cargo.toml b/futures/Cargo.toml index d12c425ae8..31b4df1f83 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -15,6 +15,9 @@ composability, and iterator-like interfaces. """ categories = ["asynchronous"] +[build-dependencies] +autocfg = "1" + [dependencies] futures-core = { path = "../futures-core", version = "0.3.8", default-features = false } futures-task = { path = "../futures-task", version = "0.3.8", default-features = false } @@ -46,11 +49,14 @@ thread-pool = ["executor", "futures-executor/thread-pool"] # These features are outside of the normal semver guarantees and require the # `unstable` feature as an explicit opt-in to unstable API. unstable = ["futures-core/unstable", "futures-task/unstable", "futures-channel/unstable", "futures-io/unstable", "futures-util/unstable"] -cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic", "futures-task/cfg-target-has-atomic", "futures-channel/cfg-target-has-atomic", "futures-util/cfg-target-has-atomic"] bilock = ["futures-util/bilock"] read-initializer = ["futures-io/read-initializer", "futures-util/read-initializer"] write-all-vectored = ["futures-util/write-all-vectored"] +# These features are no longer used. +# TODO: remove in the next major version. +cfg-target-has-atomic = [] + [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/futures/build.rs b/futures/build.rs new file mode 100644 index 0000000000..43ddfeafd6 --- /dev/null +++ b/futures/build.rs @@ -0,0 +1,23 @@ +use autocfg::AutoCfg; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let cfg = match AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + println!( + "cargo:warning={}: unable to determine rustc version: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=has_atomic_cas"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/futures/src/lib.rs b/futures/src/lib.rs index de29ace218..c507e3d5dc 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -78,7 +78,6 @@ //! The majority of examples and code snippets in this crate assume that they are //! inside an async block as written above. -#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] #![cfg_attr(feature = "read-initializer", feature(read_initializer))] #![cfg_attr(not(feature = "std"), no_std)] @@ -91,9 +90,6 @@ #![cfg_attr(docsrs, feature(doc_cfg))] -#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))] -compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features"); - #[cfg(all(feature = "bilock", not(feature = "unstable")))] compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features"); diff --git a/futures/tests/no-std/Cargo.toml b/futures/tests/no-std/Cargo.toml new file mode 100644 index 0000000000..9526732e34 --- /dev/null +++ b/futures/tests/no-std/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "no-std" +version = "0.1.0" +authors = ["Taiki Endo "] +edition = "2018" +publish = false + +[features] +futures-core-alloc = ["futures-core/alloc"] +futures-task-alloc = ["futures-task/alloc"] +futures-channel-alloc = ["futures-channel/alloc"] +futures-util-alloc = ["futures-util/alloc"] +futures-util-async-await = ["futures-util/async-await"] +futures-alloc = ["futures/alloc"] +futures-async-await = ["futures/async-await"] + +[dependencies] +futures-core = { path = "../../../futures-core", optional = true, default-features = false } +futures-task = { path = "../../../futures-task", optional = true, default-features = false } +futures-channel = { path = "../../../futures-channel", optional = true, default-features = false } +futures-util = { path = "../../../futures-util", optional = true, default-features = false } +futures = { path = "../..", optional = true, default-features = false } diff --git a/futures/tests/no-std/build.rs b/futures/tests/no-std/build.rs new file mode 100644 index 0000000000..a96a68274b --- /dev/null +++ b/futures/tests/no-std/build.rs @@ -0,0 +1,14 @@ +use std::{env, process::Command}; + +fn main() { + if is_nightly() { + println!("cargo:rustc-cfg=nightly"); + } +} + +fn is_nightly() -> bool { + env::var_os("RUSTC") + .and_then(|rustc| Command::new(rustc).arg("--version").output().ok()) + .and_then(|output| String::from_utf8(output.stdout).ok()) + .map_or(false, |version| version.contains("nightly") || version.contains("dev")) +} diff --git a/futures/tests/no-std/src/lib.rs b/futures/tests/no-std/src/lib.rs new file mode 100644 index 0000000000..308218d6b7 --- /dev/null +++ b/futures/tests/no-std/src/lib.rs @@ -0,0 +1,31 @@ +#![cfg(nightly)] +#![no_std] +#![feature(cfg_target_has_atomic)] + +#[cfg(feature = "futures-core-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_core::task::__internal::AtomicWaker as _; + +#[cfg(feature = "futures-task-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_task::ArcWake as _; + +#[cfg(feature = "futures-channel-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_channel::oneshot as _; + +#[cfg(any(feature = "futures", feature = "futures-alloc"))] +#[cfg(target_has_atomic = "ptr")] +pub use futures::task::AtomicWaker as _; + +#[cfg(feature = "futures-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures::stream::FuturesOrdered as _; + +#[cfg(any(feature = "futures-util", feature = "futures-util-alloc"))] +#[cfg(target_has_atomic = "ptr")] +pub use futures_util::task::AtomicWaker as _; + +#[cfg(feature = "futures-util-alloc")] +#[cfg(target_has_atomic = "ptr")] +pub use futures_util::stream::FuturesOrdered as _; From 2c2dde2e3abfd51b20980edcaa58738f9bb065a7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 1 Jan 2021 01:39:29 +0900 Subject: [PATCH 2/3] Change has_atomic_cas to no_atomic_cas to implement a workaround for the first problem --- futures-channel/build.rs | 8 ++++++-- futures-channel/src/lib.rs | 2 +- futures-core/build.rs | 8 ++++++-- futures-core/src/task/__internal/mod.rs | 4 ++-- futures-task/build.rs | 8 ++++++-- futures-task/src/lib.rs | 2 +- futures-util/build.rs | 8 ++++++-- futures-util/src/lib.rs | 2 +- futures-util/src/stream/mod.rs | 6 +++--- futures-util/src/stream/stream/mod.rs | 8 ++++---- futures-util/src/stream/try_stream/mod.rs | 6 +++--- futures/build.rs | 8 ++++++-- 12 files changed, 45 insertions(+), 25 deletions(-) diff --git a/futures-channel/build.rs b/futures-channel/build.rs index 43ddfeafd6..25661aee45 100644 --- a/futures-channel/build.rs +++ b/futures-channel/build.rs @@ -16,8 +16,12 @@ fn main() { } }; - if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { - println!("cargo:rustc-cfg=has_atomic_cas"); + // Note that this is `no_atomic_cas`, not `has_atomic_cas`. This allows + // treating `cfg(target_has_atomic = "ptr")` as true when the build script + // doesn't run. This is needed for compatibility with non-cargo build + // systems that don't run build scripts. + if !cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=no_atomic_cas"); } println!("cargo:rerun-if-changed=build.rs"); } diff --git a/futures-channel/src/lib.rs b/futures-channel/src/lib.rs index 15b804f5eb..4d26a65012 100644 --- a/futures-channel/src/lib.rs +++ b/futures-channel/src/lib.rs @@ -21,7 +21,7 @@ macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] $item )*}; } diff --git a/futures-core/build.rs b/futures-core/build.rs index 43ddfeafd6..25661aee45 100644 --- a/futures-core/build.rs +++ b/futures-core/build.rs @@ -16,8 +16,12 @@ fn main() { } }; - if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { - println!("cargo:rustc-cfg=has_atomic_cas"); + // Note that this is `no_atomic_cas`, not `has_atomic_cas`. This allows + // treating `cfg(target_has_atomic = "ptr")` as true when the build script + // doesn't run. This is needed for compatibility with non-cargo build + // systems that don't run build scripts. + if !cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=no_atomic_cas"); } println!("cargo:rerun-if-changed=build.rs"); } diff --git a/futures-core/src/task/__internal/mod.rs b/futures-core/src/task/__internal/mod.rs index 0ef898c11e..fafe3d5350 100644 --- a/futures-core/src/task/__internal/mod.rs +++ b/futures-core/src/task/__internal/mod.rs @@ -1,4 +1,4 @@ -#[cfg(has_atomic_cas)] +#[cfg(not(no_atomic_cas))] mod atomic_waker; -#[cfg(has_atomic_cas)] +#[cfg(not(no_atomic_cas))] pub use self::atomic_waker::AtomicWaker; diff --git a/futures-task/build.rs b/futures-task/build.rs index 43ddfeafd6..25661aee45 100644 --- a/futures-task/build.rs +++ b/futures-task/build.rs @@ -16,8 +16,12 @@ fn main() { } }; - if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { - println!("cargo:rustc-cfg=has_atomic_cas"); + // Note that this is `no_atomic_cas`, not `has_atomic_cas`. This allows + // treating `cfg(target_has_atomic = "ptr")` as true when the build script + // doesn't run. This is needed for compatibility with non-cargo build + // systems that don't run build scripts. + if !cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=no_atomic_cas"); } println!("cargo:rerun-if-changed=build.rs"); } diff --git a/futures-task/src/lib.rs b/futures-task/src/lib.rs index 8b65cada3d..db0da7ae8a 100644 --- a/futures-task/src/lib.rs +++ b/futures-task/src/lib.rs @@ -13,7 +13,7 @@ extern crate alloc; macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] $item )*}; } diff --git a/futures-util/build.rs b/futures-util/build.rs index 43ddfeafd6..25661aee45 100644 --- a/futures-util/build.rs +++ b/futures-util/build.rs @@ -16,8 +16,12 @@ fn main() { } }; - if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { - println!("cargo:rustc-cfg=has_atomic_cas"); + // Note that this is `no_atomic_cas`, not `has_atomic_cas`. This allows + // treating `cfg(target_has_atomic = "ptr")` as true when the build script + // doesn't run. This is needed for compatibility with non-cargo build + // systems that don't run build scripts. + if !cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=no_atomic_cas"); } println!("cargo:rerun-if-changed=build.rs"); } diff --git a/futures-util/src/lib.rs b/futures-util/src/lib.rs index 710906f3e3..4ed5dd356a 100644 --- a/futures-util/src/lib.rs +++ b/futures-util/src/lib.rs @@ -54,7 +54,7 @@ pub mod __private { macro_rules! cfg_target_has_atomic { ($($item:item)*) => {$( - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] $item )*}; } diff --git a/futures-util/src/stream/mod.rs b/futures-util/src/stream/mod.rs index 45611ea81a..a7e40b55ba 100644 --- a/futures-util/src/stream/mod.rs +++ b/futures-util/src/stream/mod.rs @@ -36,11 +36,11 @@ pub use self::stream::ReadyChunks; #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] pub use self::stream::Forward; -#[cfg(has_atomic_cas)] +#[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] pub use self::stream::{BufferUnordered, Buffered, ForEachConcurrent}; -#[cfg(has_atomic_cas)] +#[cfg(not(no_atomic_cas))] #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] #[cfg(feature = "alloc")] @@ -58,7 +58,7 @@ pub use self::try_stream::{ #[cfg(feature = "std")] pub use self::try_stream::IntoAsyncRead; -#[cfg(has_atomic_cas)] +#[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] pub use self::try_stream::{TryBufferUnordered, TryBuffered, TryForEachConcurrent}; diff --git a/futures-util/src/stream/stream/mod.rs b/futures-util/src/stream/stream/mod.rs index b6ce054400..24a916eae0 100644 --- a/futures-util/src/stream/stream/mod.rs +++ b/futures-util/src/stream/stream/mod.rs @@ -917,7 +917,7 @@ pub trait StreamExt: Stream { /// fut.await; /// # }) /// ``` - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn for_each_concurrent( self, @@ -1140,7 +1140,7 @@ pub trait StreamExt: Stream { /// /// This method is only available when the `std` or `alloc` feature of this /// library is activated, and it is activated by default. - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn buffered(self, n: usize) -> Buffered where @@ -1185,7 +1185,7 @@ pub trait StreamExt: Stream { /// assert_eq!(buffered.next().await, None); /// # Ok::<(), i32>(()) }).unwrap(); /// ``` - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn buffer_unordered(self, n: usize) -> BufferUnordered where @@ -1349,7 +1349,7 @@ pub trait StreamExt: Stream { /// library is activated, and it is activated by default. #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn split(self) -> (SplitSink, SplitStream) where diff --git a/futures-util/src/stream/try_stream/mod.rs b/futures-util/src/stream/try_stream/mod.rs index 7870bdfe92..c7969f554c 100644 --- a/futures-util/src/stream/try_stream/mod.rs +++ b/futures-util/src/stream/try_stream/mod.rs @@ -515,7 +515,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(Err(oneshot::Canceled), fut.await); /// # }) /// ``` - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn try_for_each_concurrent( self, @@ -836,7 +836,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); /// # Ok::<(), Box>(()) }).unwrap(); /// ``` - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered where @@ -912,7 +912,7 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); /// # Ok::<(), Box>(()) }).unwrap(); /// ``` - #[cfg(has_atomic_cas)] + #[cfg(not(no_atomic_cas))] #[cfg(feature = "alloc")] fn try_buffered(self, n: usize) -> TryBuffered where diff --git a/futures/build.rs b/futures/build.rs index 43ddfeafd6..25661aee45 100644 --- a/futures/build.rs +++ b/futures/build.rs @@ -16,8 +16,12 @@ fn main() { } }; - if cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { - println!("cargo:rustc-cfg=has_atomic_cas"); + // Note that this is `no_atomic_cas`, not `has_atomic_cas`. This allows + // treating `cfg(target_has_atomic = "ptr")` as true when the build script + // doesn't run. This is needed for compatibility with non-cargo build + // systems that don't run build scripts. + if !cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { + println!("cargo:rustc-cfg=no_atomic_cas"); } println!("cargo:rerun-if-changed=build.rs"); } From bd52ef1fafc23e8e0404487ec728989c5641d1c2 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 1 Jan 2021 15:43:11 +0900 Subject: [PATCH 3/3] Remove build script from futures crate After #2299, this is no longer needed. --- futures/Cargo.toml | 3 --- futures/build.rs | 27 --------------------------- 2 files changed, 30 deletions(-) delete mode 100644 futures/build.rs diff --git a/futures/Cargo.toml b/futures/Cargo.toml index 31b4df1f83..4711d05025 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -15,9 +15,6 @@ composability, and iterator-like interfaces. """ categories = ["asynchronous"] -[build-dependencies] -autocfg = "1" - [dependencies] futures-core = { path = "../futures-core", version = "0.3.8", default-features = false } futures-task = { path = "../futures-task", version = "0.3.8", default-features = false } diff --git a/futures/build.rs b/futures/build.rs deleted file mode 100644 index 25661aee45..0000000000 --- a/futures/build.rs +++ /dev/null @@ -1,27 +0,0 @@ -use autocfg::AutoCfg; - -// The rustc-cfg strings below are *not* public API. Please let us know by -// opening a GitHub issue if your build environment requires some way to enable -// these cfgs other than by executing our build script. -fn main() { - let cfg = match AutoCfg::new() { - Ok(cfg) => cfg, - Err(e) => { - println!( - "cargo:warning={}: unable to determine rustc version: {}", - env!("CARGO_PKG_NAME"), - e - ); - return; - } - }; - - // Note that this is `no_atomic_cas`, not `has_atomic_cas`. This allows - // treating `cfg(target_has_atomic = "ptr")` as true when the build script - // doesn't run. This is needed for compatibility with non-cargo build - // systems that don't run build scripts. - if !cfg.probe_expression("core::sync::atomic::AtomicPtr::<()>::compare_exchange") { - println!("cargo:rustc-cfg=no_atomic_cas"); - } - println!("cargo:rerun-if-changed=build.rs"); -}