From f9c57fa26cfd4d8afb32daaabdf6cf68dfab7c2f Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 21 Feb 2025 09:36:02 +1100 Subject: [PATCH 01/11] Add `no_std` support to `bevy` --- Cargo.toml | 31 ++++ crates/bevy_internal/Cargo.toml | 143 +++++++++++++++--- crates/bevy_internal/src/default_plugins.rs | 2 + crates/bevy_internal/src/lib.rs | 3 + crates/bevy_internal/src/prelude.rs | 9 +- docs/cargo_features.md | 9 ++ src/lib.rs | 1 + tools/ci/src/commands/compile_check_no_std.rs | 130 +--------------- 8 files changed, 176 insertions(+), 152 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f5efb88019769..9ab8564cc45b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,6 +114,8 @@ unused_qualifications = "warn" [features] default = [ + "std", + "async_executor", "android-game-activity", "android_shared_stdcxx", "animation", @@ -124,6 +126,8 @@ default = [ "bevy_gilrs", "bevy_gizmos", "bevy_gltf", + "bevy_input_focus", + "bevy_log", "bevy_mesh_picking_backend", "bevy_pbr", "bevy_picking", @@ -150,6 +154,9 @@ default = [ "x11", ] +# Recommended defaults for no_std applications +default_no_std = ["edge_executor", "libm", "critical-section", "bevy_state"] + # Provides an implementation for picking meshes bevy_mesh_picking_backend = [ "bevy_picking", @@ -257,6 +264,12 @@ bevy_dev_tools = ["bevy_internal/bevy_dev_tools"] # Enable the Bevy Remote Protocol bevy_remote = ["bevy_internal/bevy_remote"] +# Enable integration with `tracing` and `log` +bevy_log = ["bevy_internal/bevy_log"] + +# Enable input focus subsystem +bevy_input_focus = ["bevy_internal/bevy_input_focus"] + # Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation) spirv_shader_passthrough = ["bevy_internal/spirv_shader_passthrough"] @@ -479,6 +492,24 @@ custom_cursor = ["bevy_internal/custom_cursor"] # Experimental support for nodes that are ignored for UI layouting ghost_nodes = ["bevy_internal/ghost_nodes"] +# Uses `async-executor` as a task execution backend. +async_executor = ["std", "bevy_internal/async_executor"] + +# Uses `edge-executor` as a task execution backend. +edge_executor = ["bevy_internal/edge_executor"] + +# Allows access to the `std` crate. +std = ["bevy_internal/std"] + +# `critical-section` provides the building blocks for synchronization primitives on all platforms, including `no_std`. +critical-section = ["bevy_internal/critical-section"] + +# `portable-atomic` provides additional platform support for atomic types and operations, even on targets without native support. +portable-atomic = ["bevy_internal/portable-atomic"] + +# Uses the `libm` maths library instead of the one provided in `std` and `core`. +libm = ["bevy_internal/libm"] + [dependencies] bevy_internal = { path = "crates/bevy_internal", version = "0.16.0-dev", default-features = false } tracing = { version = "0.1", default-features = false, optional = true } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 0ac089a94c6f9..4c652069f5dc9 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -90,6 +90,7 @@ shader_format_glsl = [ shader_format_spirv = ["bevy_render/shader_format_spirv"] serialize = [ + "bevy_a11y?/serialize", "bevy_color?/serialize", "bevy_ecs/serialize", "bevy_image?/serialize", @@ -104,12 +105,13 @@ serialize = [ "bevy_platform_support/serialize", ] multi_threaded = [ + "std", "bevy_asset?/multi_threaded", "bevy_ecs/multi_threaded", "bevy_render?/multi_threaded", "bevy_tasks/multi_threaded", ] -async-io = ["bevy_tasks/async-io"] +async-io = ["std", "bevy_tasks/async-io"] # Display server protocol support (X11 is enabled by default) wayland = ["bevy_winit/wayland"] @@ -272,31 +274,122 @@ custom_cursor = ["bevy_winit/custom_cursor"] # Experimental support for nodes that are ignored for UI layouting ghost_nodes = ["bevy_ui/ghost_nodes"] +# Allows access to the `std` crate. Enabling this feature will prevent compilation +# on `no_std` targets, but provides access to certain additional features on +# supported platforms. +std = [ + "bevy_a11y?/std", + "bevy_app/std", + "bevy_diagnostic/std", + "bevy_ecs/std", + "bevy_input/std", + "bevy_input_focus?/std", + "bevy_math/std", + "bevy_platform_support/std", + "bevy_reflect/std", + "bevy_state?/std", + "bevy_time/std", + "bevy_transform/std", + "bevy_utils/std", + "bevy_tasks/std", + "bevy_window?/std", +] + +# `critical-section` provides the building blocks for synchronization primitives +# on all platforms, including `no_std`. +critical-section = [ + "bevy_a11y?/critical-section", + "bevy_app/critical-section", + "bevy_diagnostic/critical-section", + "bevy_ecs/critical-section", + "bevy_input/critical-section", + "bevy_input_focus?/critical-section", + "bevy_platform_support/critical-section", + "bevy_reflect/critical-section", + "bevy_state?/critical-section", + "bevy_time/critical-section", + "bevy_utils/critical-section", + "bevy_tasks/critical-section", +] + +# `portable-atomic` provides additional platform support for atomic types and +# operations, even on targets without native support. +portable-atomic = [ + "bevy_a11y?/portable-atomic", + "bevy_app/portable-atomic", + "bevy_diagnostic/portable-atomic", + "bevy_ecs/portable-atomic", + "bevy_input/portable-atomic", + "bevy_input_focus?/portable-atomic", + "bevy_platform_support/portable-atomic", + "bevy_reflect/portable-atomic", + "bevy_state?/portable-atomic", + "bevy_time/portable-atomic", + "bevy_utils/portable-atomic", + "bevy_tasks/portable-atomic", +] + +# Uses the `libm` maths library instead of the one provided in `std` and `core`. +libm = [ + "bevy_a11y?/libm", + "bevy_input/libm", + "bevy_input_focus?/libm", + "bevy_math/libm", + "bevy_transform/libm", + "bevy_window?/libm", +] + +# Executor Backend (choose one) +# Uses `async-executor` as a task execution backend. +# This backend is incompatible with `no_std` targets. +async_executor = ["std", "bevy_tasks/async_executor", "bevy_ecs/async_executor"] +# Uses `edge-executor` as a task execution backend. +# Use this instead of `async-executor` if working on a `no_std` target. +edge_executor = ["bevy_tasks/edge_executor", "bevy_ecs/edge_executor"] + [dependencies] -# bevy -bevy_a11y = { path = "../bevy_a11y", version = "0.16.0-dev", optional = true } -bevy_app = { path = "../bevy_app", version = "0.16.0-dev" } -bevy_derive = { path = "../bevy_derive", version = "0.16.0-dev" } -bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.16.0-dev" } -bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } -bevy_state = { path = "../bevy_state", optional = true, version = "0.16.0-dev" } -bevy_input = { path = "../bevy_input", version = "0.16.0-dev" } -bevy_input_focus = { path = "../bevy_input_focus", version = "0.16.0-dev" } -bevy_log = { path = "../bevy_log", version = "0.16.0-dev" } -bevy_math = { path = "../bevy_math", version = "0.16.0-dev", features = [ +# bevy (no_std) +bevy_app = { path = "../bevy_app", version = "0.16.0-dev", default-features = false, features = [ + "bevy_tasks", + "bevy_reflect", +] } +bevy_derive = { path = "../bevy_derive", version = "0.16.0-dev", default-features = false } +bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.16.0-dev", default-features = false } +bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev", default-features = false, features = [ + "bevy_reflect", +] } +bevy_input = { path = "../bevy_input", version = "0.16.0-dev", default-features = false, features = [ + "bevy_reflect", +] } +bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false, features = [ "bevy_reflect", ] } -bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev" } -bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ +bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [ + "alloc", +] } +bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev", default-features = false } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", default-features = false, features = [ "bevy", ] } -bevy_time = { path = "../bevy_time", version = "0.16.0-dev" } -bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } -bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" } -bevy_window = { path = "../bevy_window", version = "0.16.0-dev", optional = true } -bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" } +bevy_time = { path = "../bevy_time", version = "0.16.0-dev", default-features = false, features = [ + "bevy_reflect", +] } +bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev", default-features = false, features = [ + "bevy-support", + "bevy_reflect", +] } +bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features = false, features = [ + "alloc", +] } +bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false } + +# bevy (std required) +bevy_log = { path = "../bevy_log", version = "0.16.0-dev", optional = true } + # bevy (optional) +bevy_a11y = { path = "../bevy_a11y", optional = true, version = "0.16.0-dev", features = [ + "bevy_reflect", +] } bevy_animation = { path = "../bevy_animation", optional = true, version = "0.16.0-dev" } bevy_asset = { path = "../bevy_asset", optional = true, version = "0.16.0-dev" } bevy_audio = { path = "../bevy_audio", optional = true, version = "0.16.0-dev" } @@ -307,14 +400,24 @@ bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.16.0-dev" } bevy_gizmos = { path = "../bevy_gizmos", optional = true, version = "0.16.0-dev", default-features = false } bevy_gltf = { path = "../bevy_gltf", optional = true, version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", optional = true, version = "0.16.0-dev" } +bevy_input_focus = { path = "../bevy_input_focus", optional = true, version = "0.16.0-dev", default-features = false, features = [ + "bevy_reflect", +] } bevy_pbr = { path = "../bevy_pbr", optional = true, version = "0.16.0-dev" } bevy_picking = { path = "../bevy_picking", optional = true, version = "0.16.0-dev" } bevy_remote = { path = "../bevy_remote", optional = true, version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", optional = true, version = "0.16.0-dev" } bevy_scene = { path = "../bevy_scene", optional = true, version = "0.16.0-dev" } bevy_sprite = { path = "../bevy_sprite", optional = true, version = "0.16.0-dev" } +bevy_state = { path = "../bevy_state", optional = true, version = "0.16.0-dev", default-features = false, features = [ + "bevy_app", + "bevy_reflect", +] } bevy_text = { path = "../bevy_text", optional = true, version = "0.16.0-dev" } bevy_ui = { path = "../bevy_ui", optional = true, version = "0.16.0-dev" } +bevy_window = { path = "../bevy_window", optional = true, version = "0.16.0-dev", default-features = false, features = [ + "bevy_reflect", +] } bevy_winit = { path = "../bevy_winit", optional = true, version = "0.16.0-dev" } [lints] diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index d9aee3017a2ee..16aad774d3131 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -4,6 +4,7 @@ plugin_group! { /// This plugin group will add all the default plugins for a *Bevy* application: pub struct DefaultPlugins { bevy_app:::PanicHandlerPlugin, + #[cfg(feature = "bevy_log")] bevy_log:::LogPlugin, bevy_app:::TaskPoolPlugin, bevy_diagnostic:::FrameCountPlugin, @@ -17,6 +18,7 @@ plugin_group! { bevy_window:::WindowPlugin, #[cfg(feature = "bevy_window")] bevy_a11y:::AccessibilityPlugin, + #[cfg(feature = "std")] #[custom(cfg(any(unix, windows)))] bevy_app:::TerminalCtrlCHandlerPlugin, #[cfg(feature = "bevy_asset")] diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index 578527d68ec52..ae0176f0d11dd 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -4,6 +4,7 @@ html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" )] +#![no_std] //! This module is separated into its own crate to enable simple dynamic linking for Bevy, and should not be used directly @@ -39,7 +40,9 @@ pub use bevy_gltf as gltf; #[cfg(feature = "bevy_image")] pub use bevy_image as image; pub use bevy_input as input; +#[cfg(feature = "bevy_input_focus")] pub use bevy_input_focus as input_focus; +#[cfg(feature = "bevy_log")] pub use bevy_log as log; pub use bevy_math as math; #[cfg(feature = "bevy_pbr")] diff --git a/crates/bevy_internal/src/prelude.rs b/crates/bevy_internal/src/prelude.rs index 1c19c7ccc14a0..3bf13d34c98f9 100644 --- a/crates/bevy_internal/src/prelude.rs +++ b/crates/bevy_internal/src/prelude.rs @@ -1,10 +1,13 @@ #[doc(hidden)] pub use crate::{ - app::prelude::*, ecs::prelude::*, input::prelude::*, log::prelude::*, math::prelude::*, - reflect::prelude::*, time::prelude::*, transform::prelude::*, utils::prelude::*, - DefaultPlugins, MinimalPlugins, + app::prelude::*, ecs::prelude::*, input::prelude::*, math::prelude::*, reflect::prelude::*, + time::prelude::*, transform::prelude::*, utils::prelude::*, DefaultPlugins, MinimalPlugins, }; +#[doc(hidden)] +#[cfg(feature = "bevy_log")] +pub use crate::log::prelude::*; + #[doc(hidden)] #[cfg(feature = "bevy_window")] pub use crate::window::prelude::*; diff --git a/docs/cargo_features.md b/docs/cargo_features.md index 00f27a618490a..38150322afeb1 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -14,6 +14,7 @@ The default feature set enables most of the expected features of a game engine, |android-game-activity|Android GameActivity support. Default, choose between this and `android-native-activity`.| |android_shared_stdcxx|Enable using a shared stdlib for cxx on Android| |animation|Enable animation support, and glTF animation loading| +|async_executor|Uses `async-executor` as a task execution backend.| |bevy_animation|Provides animation functionality| |bevy_asset|Provides asset functionality| |bevy_audio|Provides audio functionality| @@ -22,6 +23,8 @@ The default feature set enables most of the expected features of a game engine, |bevy_gilrs|Adds gamepad support| |bevy_gizmos|Adds support for rendering gizmos| |bevy_gltf|[glTF](https://www.khronos.org/gltf/) support| +|bevy_input_focus|Enable input focus subsystem| +|bevy_log|Enable integration with `tracing` and `log`| |bevy_mesh_picking_backend|Provides an implementation for picking meshes| |bevy_pbr|Adds PBR rendering| |bevy_picking|Provides picking functionality| @@ -42,6 +45,7 @@ The default feature set enables most of the expected features of a game engine, |multi_threaded|Enables multithreaded parallelism in the engine. Disabling it forces all engine tasks to run on a single thread.| |png|PNG image format support| |smaa_luts|Include SMAA Look Up Tables KTX2 Files| +|std|Allows access to the `std` crate.| |sysinfo_plugin|Enables system information diagnostic plugin| |tonemapping_luts|Include tonemapping Look Up Tables KTX2 files. If everything is pink, you need to enable this feature or change the `Tonemapping` method for your `Camera2d` or `Camera3d`.| |vorbis|OGG/VORBIS audio format support| @@ -65,10 +69,13 @@ The default feature set enables most of the expected features of a game engine, |bevy_remote|Enable the Bevy Remote Protocol| |bevy_ui_debug|Provides a debug overlay for bevy UI| |bmp|BMP image format support| +|critical-section|`critical-section` provides the building blocks for synchronization primitives on all platforms, including `no_std`.| |dds|DDS compressed texture support| |debug_glam_assert|Enable assertions in debug builds to check the validity of parameters passed to glam| +|default_no_std|Recommended defaults for no_std applications| |detailed_trace|Enable detailed trace event logging. These trace events are expensive even when off, thus they require compile time opt-in| |dynamic_linking|Force dynamic linking, which improves iterative compile times| +|edge_executor|Uses `edge-executor` as a task execution backend.| |embedded_watcher|Enables watching in memory asset providers for Bevy Asset hot-reloading| |experimental_pbr_pcss|Enable support for PCSS, at the risk of blowing past the global, per-shader sampler limit on older/lower-end GPUs| |exr|EXR image format support| @@ -80,6 +87,7 @@ The default feature set enables most of the expected features of a game engine, |glam_assert|Enable assertions to check the validity of parameters passed to glam| |ico|ICO image format support| |jpeg|JPEG image format support| +|libm|Uses the `libm` maths library instead of the one provided in `std` and `core`.| |meshlet|Enables the meshlet renderer for dense high-poly scenes (experimental)| |meshlet_processor|Enables processing meshes into meshlet meshes for bevy_pbr| |minimp3|MP3 audio format support (through minimp3)| @@ -89,6 +97,7 @@ The default feature set enables most of the expected features of a game engine, |pbr_specular_textures|Enable support for specular textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_transmission_textures|Enable support for transmission-related textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pnm|PNM image format support, includes pam, pbm, pgm and ppm| +|portable-atomic|`portable-atomic` provides additional platform support for atomic types and operations, even on targets without native support. | |qoi|QOI image format support| |reflect_functions|Enable function reflection| |serialize|Enable serialization support through serde| diff --git a/src/lib.rs b/src/lib.rs index 29f7cc5cc7a74..1eb60b9e2b20f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,7 @@ html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" )] +#![no_std] pub use bevy_internal::*; diff --git a/tools/ci/src/commands/compile_check_no_std.rs b/tools/ci/src/commands/compile_check_no_std.rs index 2b45bcc4c4a35..3967e1a0bd2a5 100644 --- a/tools/ci/src/commands/compile_check_no_std.rs +++ b/tools/ci/src/commands/compile_check_no_std.rs @@ -41,139 +41,11 @@ impl Prepare for CompileCheckNoStdCommand { commands.push(PreparedCommand::new::( cmd!( sh, - "cargo check -p bevy_ptr --no-default-features --target {target}" + "cargo check -p bevy --no-default-features --features default_no_std --target {target}" ), "Please fix compiler errors in output above for bevy_ptr no_std compatibility.", )); - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_utils --no-default-features --target {target}" - ), - "Please fix compiler errors in output above for bevy_utils no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_mikktspace --no-default-features --features libm --target {target}" - ), - "Please fix compiler errors in output above for bevy_mikktspace no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_reflect --no-default-features --target {target}" - ), - "Please fix compiler errors in output above for bevy_reflect no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_math --no-default-features --features libm --target {target}" - ), - "Please fix compiler errors in output above for bevy_math no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_color --no-default-features --features libm --target {target}" - ), - "Please fix compiler errors in output above for bevy_color no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_tasks --no-default-features --features edge_executor,critical-section --target {target}" - ), - "Please fix compiler errors in output above for bevy_tasks no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_ecs --no-default-features --features edge_executor,critical-section,bevy_debug_stepping,bevy_reflect --target {target}" - ), - "Please fix compiler errors in output above for bevy_ecs no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_app --no-default-features --features bevy_reflect --target {target}" - ), - "Please fix compiler errors in output above for bevy_app no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_input --no-default-features --features libm,serialize,bevy_reflect --target {target}" - ), - "Please fix compiler errors in output above for bevy_input no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_state --no-default-features --features bevy_reflect,bevy_app --target {target}" - ), - "Please fix compiler errors in output above for bevy_state no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_window --no-default-features --features libm,bevy_reflect,serialize --target {target}" - ), - "Please fix compiler errors in output above for bevy_window no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_transform --no-default-features --features bevy-support,serialize,libm --target {target}" - ), - "Please fix compiler errors in output above for bevy_transform no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_time --no-default-features --features bevy_reflect,serialize --target {target}" - ), - "Please fix compiler errors in output above for bevy_time no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_input_focus --no-default-features --features libm,serialize,bevy_reflect --target {target}" - ), - "Please fix compiler errors in output above for bevy_input_focus no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_a11y --no-default-features --features libm,serialize,bevy_reflect --target {target}" - ), - "Please fix compiler errors in output above for bevy_a11y no_std compatibility.", - )); - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy_diagnostic --no-default-features --features serialize --target {target}" - ), - "Please fix compiler errors in output above for bevy_diagnostic no_std compatibility.", - )); - commands } } From 8ea178785276494dbcbf11fc045c57ed5a0b7b85 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 21 Feb 2025 15:11:08 +1100 Subject: [PATCH 02/11] Fix `thumbv6m-none-eabi` Compatibility and add to CI _Possibly_ controversial, but support _should_ be relatively easy to maintain --- .github/workflows/ci.yml | 26 +++++++++- crates/bevy_animation/Cargo.toml | 1 - crates/bevy_audio/Cargo.toml | 4 +- crates/bevy_color/Cargo.toml | 4 +- crates/bevy_ecs/src/entity/unique_slice.rs | 7 +-- crates/bevy_ecs/src/entity/unique_vec.rs | 3 +- crates/bevy_gltf/Cargo.toml | 4 +- crates/bevy_image/Cargo.toml | 4 +- crates/bevy_internal/Cargo.toml | 2 +- crates/bevy_mesh/Cargo.toml | 4 +- crates/bevy_pbr/Cargo.toml | 4 +- crates/bevy_reflect/Cargo.toml | 3 -- crates/bevy_render/Cargo.toml | 4 +- crates/bevy_scene/Cargo.toml | 4 +- crates/bevy_sprite/Cargo.toml | 4 +- crates/bevy_text/Cargo.toml | 4 +- crates/bevy_time/Cargo.toml | 4 +- crates/bevy_ui/Cargo.toml | 4 +- tools/ci/src/ci.rs | 3 -- tools/ci/src/commands/compile_check_no_std.rs | 51 ------------------- tools/ci/src/commands/mod.rs | 2 - 21 files changed, 44 insertions(+), 102 deletions(-) delete mode 100644 tools/ci/src/commands/compile_check_no_std.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0704a2395528..4a2cf83ea9b61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,31 @@ jobs: - name: Install Linux dependencies uses: ./.github/actions/install-linux-deps - name: Check Compile - run: cargo run -p ci -- compile-check-no-std + run: cargo check -p bevy --no-default-features --features default_no_std --target x86_64-unknown-none + check-compiles-no-std-portable-atomic: + runs-on: ubuntu-latest + timeout-minutes: 30 + needs: ci + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + crates/bevy_ecs_compile_fail_tests/target/ + crates/bevy_reflect_compile_fail_tests/target/ + key: ${{ runner.os }}-cargo-check-compiles-no-std-portable-atomic-${{ hashFiles('**/Cargo.toml') }} + - uses: dtolnay/rust-toolchain@stable + with: + targets: thumbv6m-none-eabi + - name: Install Linux dependencies + uses: ./.github/actions/install-linux-deps + - name: Check Compile + run: cargo check -p bevy --no-default-features --features default_no_std,portable-atomic --target thumbv6m-none-eabi build-wasm: runs-on: ubuntu-latest diff --git a/crates/bevy_animation/Cargo.toml b/crates/bevy_animation/Cargo.toml index 5b906fed7c496..ec039b801cdd3 100644 --- a/crates/bevy_animation/Cargo.toml +++ b/crates/bevy_animation/Cargo.toml @@ -17,7 +17,6 @@ bevy_derive = { path = "../bevy_derive", version = "0.16.0-dev" } bevy_log = { path = "../bevy_log", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", "petgraph", ] } bevy_render = { path = "../bevy_render", version = "0.16.0-dev" } diff --git a/crates/bevy_audio/Cargo.toml b/crates/bevy_audio/Cargo.toml index 4d7967977e78f..028e2b2021a67 100644 --- a/crates/bevy_audio/Cargo.toml +++ b/crates/bevy_audio/Cargo.toml @@ -14,9 +14,7 @@ bevy_app = { path = "../bevy_app", version = "0.16.0-dev" } bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } bevy_derive = { path = "../bevy_derive", version = "0.16.0-dev" } diff --git a/crates/bevy_color/Cargo.toml b/crates/bevy_color/Cargo.toml index 7115963e7f025..0babfac809438 100644 --- a/crates/bevy_color/Cargo.toml +++ b/crates/bevy_color/Cargo.toml @@ -13,9 +13,7 @@ rust-version = "1.83.0" bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false, features = [ "curve", ] } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -], optional = true } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", optional = true } bytemuck = { version = "1", features = ["derive"] } serde = { version = "1.0", features = [ "derive", diff --git a/crates/bevy_ecs/src/entity/unique_slice.rs b/crates/bevy_ecs/src/entity/unique_slice.rs index f3a6f66de7e87..ba7ab66c87e7e 100644 --- a/crates/bevy_ecs/src/entity/unique_slice.rs +++ b/crates/bevy_ecs/src/entity/unique_slice.rs @@ -16,10 +16,11 @@ use alloc::{ boxed::Box, collections::VecDeque, rc::Rc, - sync::Arc, vec::Vec, }; +use bevy_platform_support::sync::Arc; + use super::{ unique_vec, EntitySet, EntitySetIterator, FromEntitySetIterator, TrustedEntityBorrow, UniqueEntityIter, UniqueEntityVec, @@ -85,9 +86,9 @@ impl UniqueEntitySlice { } /// Casts `self` to the inner slice. - pub fn into_arc_inner(self: Arc) -> Arc<[T]> { + pub fn into_arc_inner(this: Arc) -> Arc<[T]> { // SAFETY: UniqueEntitySlice is a transparent wrapper around [T]. - unsafe { Arc::from_raw(Arc::into_raw(self) as *mut [T]) } + unsafe { Arc::from_raw(Arc::into_raw(this) as *mut [T]) } } // Constructs a `UniqueEntitySlice` from a [`Rc<[T]>`] unsafely. diff --git a/crates/bevy_ecs/src/entity/unique_vec.rs b/crates/bevy_ecs/src/entity/unique_vec.rs index 9ea1f9c7a6b39..cb26b8569bd9f 100644 --- a/crates/bevy_ecs/src/entity/unique_vec.rs +++ b/crates/bevy_ecs/src/entity/unique_vec.rs @@ -12,10 +12,11 @@ use alloc::{ boxed::Box, collections::{BTreeSet, BinaryHeap, TryReserveError, VecDeque}, rc::Rc, - sync::Arc, vec::{self, Vec}, }; +use bevy_platform_support::sync::Arc; + use super::{ unique_slice, EntitySet, FromEntitySetIterator, TrustedEntityBorrow, UniqueEntityIter, UniqueEntitySlice, diff --git a/crates/bevy_gltf/Cargo.toml b/crates/bevy_gltf/Cargo.toml index da0d97ad9670a..b0c7afa7eb42c 100644 --- a/crates/bevy_gltf/Cargo.toml +++ b/crates/bevy_gltf/Cargo.toml @@ -28,9 +28,7 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } bevy_pbr = { path = "../bevy_pbr", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", version = "0.16.0-dev" } bevy_scene = { path = "../bevy_scene", version = "0.16.0-dev", features = [ "bevy_render", diff --git a/crates/bevy_image/Cargo.toml b/crates/bevy_image/Cargo.toml index ceab1de1ce33e..f1fc06d8bb470 100644 --- a/crates/bevy_image/Cargo.toml +++ b/crates/bevy_image/Cargo.toml @@ -49,9 +49,7 @@ bevy_color = { path = "../bevy_color", version = "0.16.0-dev", features = [ "wgpu-types", ] } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -], optional = true } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", optional = true } bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" } bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [ "std", diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 4c652069f5dc9..7ad89da884e52 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -369,7 +369,7 @@ bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-d ] } bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev", default-features = false } bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", default-features = false, features = [ - "bevy", + "smallvec", ] } bevy_time = { path = "../bevy_time", version = "0.16.0-dev", default-features = false, features = [ "bevy_reflect", diff --git a/crates/bevy_mesh/Cargo.toml b/crates/bevy_mesh/Cargo.toml index ffcc2f72e2969..9ac2383366e1a 100644 --- a/crates/bevy_mesh/Cargo.toml +++ b/crates/bevy_mesh/Cargo.toml @@ -13,9 +13,7 @@ keywords = ["bevy"] bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } bevy_mikktspace = { path = "../bevy_mikktspace", version = "0.16.0-dev" } diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index 0b97ceedb9245..8e7f4ebac8927 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -40,9 +40,7 @@ bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.16.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", version = "0.16.0-dev" } bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", optional = true } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index c15784d22d3a0..37d112db346f0 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -20,9 +20,6 @@ documentation = ["bevy_reflect_derive/documentation"] ## Enables function reflection functions = ["bevy_reflect_derive/functions"] -# When enabled, provides Bevy-related reflection implementations -bevy = ["smallvec", "smol_str"] - # Debugging Features ## Enables features useful for debugging reflection diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 4167185632fa3..91ccd6c7336b9 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -48,9 +48,7 @@ bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.16.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_encase_derive = { path = "../bevy_encase_derive", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_render_macros = { path = "macros", version = "0.16.0-dev" } bevy_time = { path = "../bevy_time", version = "0.16.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } diff --git a/crates/bevy_scene/Cargo.toml b/crates/bevy_scene/Cargo.toml index ac263fe734e83..2955e0d5e3f14 100644 --- a/crates/bevy_scene/Cargo.toml +++ b/crates/bevy_scene/Cargo.toml @@ -23,9 +23,7 @@ bevy_app = { path = "../bevy_app", version = "0.16.0-dev" } bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev" } bevy_derive = { path = "../bevy_derive", version = "0.16.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", version = "0.16.0-dev", optional = true } diff --git a/crates/bevy_sprite/Cargo.toml b/crates/bevy_sprite/Cargo.toml index dc9c10154fe88..b707af4fee0a0 100644 --- a/crates/bevy_sprite/Cargo.toml +++ b/crates/bevy_sprite/Cargo.toml @@ -23,9 +23,7 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } bevy_picking = { path = "../bevy_picking", version = "0.16.0-dev", optional = true } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", version = "0.16.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" } diff --git a/crates/bevy_text/Cargo.toml b/crates/bevy_text/Cargo.toml index a5e8dea07db51..accead902641d 100644 --- a/crates/bevy_text/Cargo.toml +++ b/crates/bevy_text/Cargo.toml @@ -21,9 +21,7 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", version = "0.16.0-dev" } bevy_log = { path = "../bevy_log", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", version = "0.16.0-dev" } bevy_sprite = { path = "../bevy_sprite", version = "0.16.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" } diff --git a/crates/bevy_time/Cargo.toml b/crates/bevy_time/Cargo.toml index f209e01740db3..16c9d01143ef7 100644 --- a/crates/bevy_time/Cargo.toml +++ b/crates/bevy_time/Cargo.toml @@ -63,9 +63,7 @@ portable-atomic = [ # bevy bevy_app = { path = "../bevy_app", version = "0.16.0-dev", default-features = false } bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev", default-features = false } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", default-features = false, features = [ - "bevy", -], optional = true } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", default-features = false, optional = true } bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false } # other diff --git a/crates/bevy_ui/Cargo.toml b/crates/bevy_ui/Cargo.toml index c287ede55b5a3..6d6717c2aa43e 100644 --- a/crates/bevy_ui/Cargo.toml +++ b/crates/bevy_ui/Cargo.toml @@ -20,9 +20,7 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" } bevy_image = { path = "../bevy_image", version = "0.16.0-dev" } bevy_input = { path = "../bevy_input", version = "0.16.0-dev" } bevy_math = { path = "../bevy_math", version = "0.16.0-dev" } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ - "bevy", -] } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" } bevy_render = { path = "../bevy_render", version = "0.16.0-dev" } bevy_sprite = { path = "../bevy_sprite", version = "0.16.0-dev" } bevy_text = { path = "../bevy_text", version = "0.16.0-dev" } diff --git a/tools/ci/src/ci.rs b/tools/ci/src/ci.rs index 07470967f2b53..349e74a5a0183 100644 --- a/tools/ci/src/ci.rs +++ b/tools/ci/src/ci.rs @@ -84,7 +84,6 @@ impl CI { cmds.append(&mut commands::DocCheckCommand::default().prepare(sh, flags)); cmds.append(&mut commands::DocTestCommand::default().prepare(sh, flags)); cmds.append(&mut commands::CompileCheckCommand::default().prepare(sh, flags)); - cmds.append(&mut commands::CompileCheckNoStdCommand::default().prepare(sh, flags)); cmds.append(&mut commands::CompileFailCommand::default().prepare(sh, flags)); cmds.append(&mut commands::BenchCheckCommand::default().prepare(sh, flags)); cmds.append(&mut commands::ExampleCheckCommand::default().prepare(sh, flags)); @@ -113,7 +112,6 @@ enum Commands { DocCheck(commands::DocCheckCommand), DocTest(commands::DocTestCommand), CompileCheck(commands::CompileCheckCommand), - CompileCheckNoStd(commands::CompileCheckNoStdCommand), CompileFail(commands::CompileFailCommand), BenchCheck(commands::BenchCheckCommand), ExampleCheck(commands::ExampleCheckCommand), @@ -136,7 +134,6 @@ impl Prepare for Commands { Commands::DocCheck(subcommand) => subcommand.prepare(sh, flags), Commands::DocTest(subcommand) => subcommand.prepare(sh, flags), Commands::CompileCheck(subcommand) => subcommand.prepare(sh, flags), - Commands::CompileCheckNoStd(subcommand) => subcommand.prepare(sh, flags), Commands::CompileFail(subcommand) => subcommand.prepare(sh, flags), Commands::BenchCheck(subcommand) => subcommand.prepare(sh, flags), Commands::ExampleCheck(subcommand) => subcommand.prepare(sh, flags), diff --git a/tools/ci/src/commands/compile_check_no_std.rs b/tools/ci/src/commands/compile_check_no_std.rs deleted file mode 100644 index 3967e1a0bd2a5..0000000000000 --- a/tools/ci/src/commands/compile_check_no_std.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::{Flag, Prepare, PreparedCommand}; -use argh::FromArgs; -use xshell::cmd; - -/// Checks that the project compiles for a `no_std` target. -/// Note that this tool will attempt to install the target via rustup. -/// This can be skipped by passing the "--skip-install" flag. -#[derive(FromArgs)] -#[argh(subcommand, name = "compile-check-no-std")] -pub struct CompileCheckNoStdCommand { - /// the target to check against. - /// Defaults to "x86_64-unknown-none" - #[argh(option, default = "Self::default().target")] - target: String, - /// skip attempting the installation of the target. - #[argh(switch)] - skip_install: bool, -} - -impl Default for CompileCheckNoStdCommand { - fn default() -> Self { - Self { - target: String::from("x86_64-unknown-none"), - skip_install: false, - } - } -} - -impl Prepare for CompileCheckNoStdCommand { - fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { - let target = self.target.as_str(); - let mut commands = Vec::new(); - - if !self.skip_install { - commands.push(PreparedCommand::new::( - cmd!(sh, "rustup target add {target}"), - "Unable to add the required target via rustup, is it spelled correctly?", - )); - } - - commands.push(PreparedCommand::new::( - cmd!( - sh, - "cargo check -p bevy --no-default-features --features default_no_std --target {target}" - ), - "Please fix compiler errors in output above for bevy_ptr no_std compatibility.", - )); - - commands - } -} diff --git a/tools/ci/src/commands/mod.rs b/tools/ci/src/commands/mod.rs index abbd862cbd8f6..9247ab201627b 100644 --- a/tools/ci/src/commands/mod.rs +++ b/tools/ci/src/commands/mod.rs @@ -2,7 +2,6 @@ pub use bench_check::*; pub use clippy::*; pub use compile::*; pub use compile_check::*; -pub use compile_check_no_std::*; pub use compile_fail::*; pub use doc::*; pub use doc_check::*; @@ -20,7 +19,6 @@ mod bench_check; mod clippy; mod compile; mod compile_check; -mod compile_check_no_std; mod compile_fail; mod doc; mod doc_check; From 7b49b9cb9572ff1121979ca11c9a4dd251d1f7bb Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Tue, 25 Feb 2025 08:23:17 +1100 Subject: [PATCH 03/11] Simplify features now that `portable-atomic` is removed --- Cargo.toml | 3 --- crates/bevy_internal/Cargo.toml | 17 ----------------- crates/bevy_platform_support/README.md | 7 +------ crates/bevy_tasks/README.md | 2 +- docs/cargo_features.md | 1 - 5 files changed, 2 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1d982b48af654..e90609461e341 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -509,9 +509,6 @@ std = ["bevy_internal/std"] # `critical-section` provides the building blocks for synchronization primitives on all platforms, including `no_std`. critical-section = ["bevy_internal/critical-section"] -# `portable-atomic` provides additional platform support for atomic types and operations, even on targets without native support. -portable-atomic = ["bevy_internal/portable-atomic"] - # Uses the `libm` maths library instead of the one provided in `std` and `core`. libm = ["bevy_internal/libm"] diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 1a4e371ba89e2..25eb25716addf 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -315,23 +315,6 @@ critical-section = [ "bevy_tasks/critical-section", ] -# `portable-atomic` provides additional platform support for atomic types and -# operations, even on targets without native support. -portable-atomic = [ - "bevy_a11y?/portable-atomic", - "bevy_app/portable-atomic", - "bevy_diagnostic/portable-atomic", - "bevy_ecs/portable-atomic", - "bevy_input/portable-atomic", - "bevy_input_focus?/portable-atomic", - "bevy_platform_support/portable-atomic", - "bevy_reflect/portable-atomic", - "bevy_state?/portable-atomic", - "bevy_time/portable-atomic", - "bevy_utils/portable-atomic", - "bevy_tasks/portable-atomic", -] - # Uses the `libm` maths library instead of the one provided in `std` and `core`. libm = [ "bevy_a11y?/libm", diff --git a/crates/bevy_platform_support/README.md b/crates/bevy_platform_support/README.md index 7daf5afa5097e..69969ad614dea 100644 --- a/crates/bevy_platform_support/README.md +++ b/crates/bevy_platform_support/README.md @@ -45,12 +45,7 @@ This is explicitly incompatible with `no_std` targets. Enables usage of the [`alloc`](https://doc.rust-lang.org/stable/alloc/) crate. Note that this feature is automatically enabled when enabling `std`. This is compatible with most `no_std` targets, but not all. -### `portable-atomic` - -Switches to using [`portable-atomic`](https://docs.rs/portable-atomic/latest/portable_atomic/) as a backend for atomic types, such as `Arc`, `AtomicU8`, etc. -You may need to enable this feature on platforms without full support for atomic types or certain operations, such as [atomic CAS](https://en.wikipedia.org/wiki/Compare-and-swap). - ### `critical-section` Switches to using [`critical-section`](https://docs.rs/critical-section/latest/critical_section/) as a backend for synchronization. -You may need to enable this feature on platforms with little to no support for atomic operations, and is often paired with the `portable-atomic` feature. +You may need to enable this feature on platforms with little to no support for atomic operations. diff --git a/crates/bevy_tasks/README.md b/crates/bevy_tasks/README.md index 2af6a606f65fa..b03d2fcf979da 100644 --- a/crates/bevy_tasks/README.md +++ b/crates/bevy_tasks/README.md @@ -36,7 +36,7 @@ The determining factor for what kind of work should go in each pool is latency r ## `no_std` Support -To enable `no_std` support in this crate, you will need to disable default features, and enable the `edge_executor` and `critical-section` features. For platforms without full support for Rust atomics, you may also need to enable the `portable-atomic` feature. +To enable `no_std` support in this crate, you will need to disable default features, and enable the `edge_executor` and `critical-section` features. [bevy]: https://bevyengine.org [rayon]: https://github.com/rayon-rs/rayon diff --git a/docs/cargo_features.md b/docs/cargo_features.md index ffe5967d066ad..d559b06012bc6 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -97,7 +97,6 @@ The default feature set enables most of the expected features of a game engine, |pbr_specular_textures|Enable support for specular textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_transmission_textures|Enable support for transmission-related textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pnm|PNM image format support, includes pam, pbm, pgm and ppm| -|portable-atomic|`portable-atomic` provides additional platform support for atomic types and operations, even on targets without native support. | |qoi|QOI image format support| |reflect_documentation|Enable documentation reflection| |reflect_functions|Enable function reflection| From 5991069a7ab537ea4cd39208604f212554a96bdc Mon Sep 17 00:00:00 2001 From: Zachary Harrold Date: Tue, 25 Feb 2025 08:31:53 +1100 Subject: [PATCH 04/11] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20a3f6f0716f4..1e34830f08a40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,7 @@ jobs: - name: Install Linux dependencies uses: ./.github/actions/install-linux-deps - name: Check Compile - run: cargo check -p bevy --no-default-features --features default_no_std,portable-atomic --target thumbv6m-none-eabi + run: cargo check -p bevy --no-default-features --features default_no_std --target thumbv6m-none-eabi build-wasm: runs-on: ubuntu-latest From e3ac49d096119cd9f87ed1d513dc4e6b1330bba9 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Tue, 25 Feb 2025 15:07:41 +1100 Subject: [PATCH 05/11] Fix `bevy_color` feature gates --- Cargo.toml | 2 +- crates/bevy_color/Cargo.toml | 4 ++-- crates/bevy_internal/Cargo.toml | 9 ++++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e90609461e341..d14f524d85f74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,7 +157,7 @@ default = [ ] # Recommended defaults for no_std applications -default_no_std = ["edge_executor", "libm", "critical-section", "bevy_state"] +default_no_std = ["edge_executor", "libm", "critical-section", "bevy_color", "bevy_state"] # Provides an implementation for picking meshes bevy_mesh_picking_backend = [ diff --git a/crates/bevy_color/Cargo.toml b/crates/bevy_color/Cargo.toml index 28525429fc5a8..ad6508b8a0bbf 100644 --- a/crates/bevy_color/Cargo.toml +++ b/crates/bevy_color/Cargo.toml @@ -13,7 +13,7 @@ rust-version = "1.85.0" bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false, features = [ "curve", ] } -bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", optional = true } +bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", optional = true, default-features = false } bytemuck = { version = "1", features = ["derive"] } serde = { version = "1.0", features = [ "derive", @@ -28,7 +28,7 @@ default = ["std", "bevy_reflect", "encase"] std = ["alloc", "bevy_math/std", "serde?/std"] alloc = ["bevy_math/alloc", "serde?/alloc"] serialize = ["serde", "bevy_math/serialize"] -bevy_reflect = ["dep:bevy_reflect", "std"] +bevy_reflect = ["dep:bevy_reflect"] wgpu-types = ["dep:wgpu-types", "std"] encase = ["dep:encase", "std"] libm = ["bevy_math/libm"] diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 25eb25716addf..8bc8da2990156 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -197,6 +197,8 @@ bevy_render = [ "bevy_scene?/bevy_render", "bevy_gizmos?/bevy_render", "bevy_image", + "bevy_color/wgpu-types", + "bevy_color/encase", ] # Enable assertions to check the validity of parameters passed to glam @@ -283,6 +285,7 @@ ghost_nodes = ["bevy_ui/ghost_nodes"] std = [ "bevy_a11y?/std", "bevy_app/std", + "bevy_color?/std", "bevy_diagnostic/std", "bevy_ecs/std", "bevy_input/std", @@ -318,6 +321,7 @@ critical-section = [ # Uses the `libm` maths library instead of the one provided in `std` and `core`. libm = [ "bevy_a11y?/libm", + "bevy_color?/libm", "bevy_input/libm", "bevy_input_focus?/libm", "bevy_math/libm", @@ -379,7 +383,10 @@ bevy_a11y = { path = "../bevy_a11y", optional = true, version = "0.16.0-dev", fe bevy_animation = { path = "../bevy_animation", optional = true, version = "0.16.0-dev" } bevy_asset = { path = "../bevy_asset", optional = true, version = "0.16.0-dev" } bevy_audio = { path = "../bevy_audio", optional = true, version = "0.16.0-dev" } -bevy_color = { path = "../bevy_color", optional = true, version = "0.16.0-dev" } +bevy_color = { path = "../bevy_color", optional = true, version = "0.16.0-dev", default-features = false, features = [ + "alloc", + "bevy_reflect", +] } bevy_core_pipeline = { path = "../bevy_core_pipeline", optional = true, version = "0.16.0-dev" } bevy_dev_tools = { path = "../bevy_dev_tools", optional = true, version = "0.16.0-dev" } bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.16.0-dev" } From c6c7a60cee5a7bccb351fb3fc21632abae9da1b8 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Tue, 25 Feb 2025 15:38:14 +1100 Subject: [PATCH 06/11] Formatting --- Cargo.toml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d14f524d85f74..37d59d72bc9bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,7 +157,13 @@ default = [ ] # Recommended defaults for no_std applications -default_no_std = ["edge_executor", "libm", "critical-section", "bevy_color", "bevy_state"] +default_no_std = [ + "edge_executor", + "libm", + "critical-section", + "bevy_color", + "bevy_state", +] # Provides an implementation for picking meshes bevy_mesh_picking_backend = [ From 0755b51586a1bcfd6f5cc0b10f79cea8dabbcf83 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Tue, 25 Feb 2025 15:51:22 +1100 Subject: [PATCH 07/11] Fix arbitrary self types issue --- crates/bevy_ecs/src/entity/unique_array.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/entity/unique_array.rs b/crates/bevy_ecs/src/entity/unique_array.rs index 2e55b2ce6e0ee..ffc2e91edd1cc 100644 --- a/crates/bevy_ecs/src/entity/unique_array.rs +++ b/crates/bevy_ecs/src/entity/unique_array.rs @@ -74,9 +74,9 @@ impl UniqueEntityArray { } /// Casts `self` to the inner array. - pub fn into_arc_inner(self: Arc) -> Arc<[T; N]> { + pub fn into_arc_inner(this: Arc) -> Arc<[T; N]> { // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. - unsafe { Arc::from_raw(Arc::into_raw(self).cast()) } + unsafe { Arc::from_raw(Arc::into_raw(this).cast()) } } // Constructs a `Rc` from a [`Rc<[T; N]>`] unsafely. From f5af460a0a089ddb79eb7ed824ab7c77d77f48c8 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 7 Mar 2025 10:14:34 +1100 Subject: [PATCH 08/11] Inline `edge-executor` Original implementation uses outdated `futures-lite` version relying on unmaintained `instant`. --- crates/bevy_tasks/Cargo.toml | 18 +- crates/bevy_tasks/src/edge_executor.rs | 653 +++++++++++++++++++++++++ crates/bevy_tasks/src/executor.rs | 4 +- crates/bevy_tasks/src/lib.rs | 22 +- 4 files changed, 688 insertions(+), 9 deletions(-) create mode 100644 crates/bevy_tasks/src/edge_executor.rs diff --git a/crates/bevy_tasks/Cargo.toml b/crates/bevy_tasks/Cargo.toml index 3f9c9f2a3a995..c3e8bb3a8ee08 100644 --- a/crates/bevy_tasks/Cargo.toml +++ b/crates/bevy_tasks/Cargo.toml @@ -13,15 +13,15 @@ default = ["std", "async_executor"] std = [ "futures-lite/std", "async-task/std", - "edge-executor?/std", "bevy_platform_support/std", + "once_cell/std", ] multi_threaded = ["std", "dep:async-channel", "dep:concurrent-queue"] async_executor = ["std", "dep:async-executor"] -edge_executor = ["dep:edge-executor"] +edge_executor = ["dep:atomic-waker", "dep:once_cell", "dep:crossbeam-queue"] critical-section = [ "bevy_platform_support/critical-section", - "edge-executor?/critical-section", + "once_cell?/critical-section", ] [dependencies] @@ -37,12 +37,15 @@ derive_more = { version = "1", default-features = false, features = [ "deref", "deref_mut", ] } - async-executor = { version = "1.11", optional = true } -edge-executor = { version = "0.4.1", default-features = false, optional = true } async-channel = { version = "2.3.0", optional = true } async-io = { version = "2.0.0", optional = true } concurrent-queue = { version = "2.0.0", optional = true } +atomic-waker = { version = "1", default-features = false, optional = true } +once_cell = { version = "1.18", default-features = false, optional = true } +crossbeam-queue = { version = "0.3", default-features = false, features = [ + "alloc", +], optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4" @@ -53,7 +56,10 @@ futures-channel = "0.3" async-task = { version = "4.4.0", default-features = false, features = [ "portable-atomic", ] } -edge-executor = { version = "0.4.1", default-features = false, optional = true, features = [ +heapless = { version = "0.8", default-features = false, features = [ + "portable-atomic", +] } +atomic-waker = { version = "1", default-features = false, features = [ "portable-atomic", ] } diff --git a/crates/bevy_tasks/src/edge_executor.rs b/crates/bevy_tasks/src/edge_executor.rs new file mode 100644 index 0000000000000..521e117eb2e96 --- /dev/null +++ b/crates/bevy_tasks/src/edge_executor.rs @@ -0,0 +1,653 @@ +//! Alternative to `async_executor` based on [`edge_executor`] by Ivan Markov. +//! +//! It has been vendored along with its tests to update several outdated dependencies. +//! +//! [`async_executor`]: https://github.com/smol-rs/async-executor +//! [`edge_executor`]: https://github.com/ivmarkov/edge-executor + +#![expect(unsafe_code, reason = "original implementation relies on unsafe")] +#![expect( + dead_code, + reason = "keeping methods from original implementation for transparency" +)] + +// TODO: Create a more tailored replacement, possibly integrating [Fotre](https://github.com/NthTensor/Forte) + +use alloc::rc::Rc; +use core::{ + future::{poll_fn, Future}, + marker::PhantomData, + task::{Context, Poll}, +}; + +use async_task::{Runnable, Task}; +use atomic_waker::AtomicWaker; +use bevy_platform_support::sync::Arc; +use futures_lite::FutureExt; +use once_cell::sync::OnceCell; + +/// An async executor. +/// +/// # Examples +/// +/// A multi-threaded executor: +/// +/// ```ignore +/// use async_channel::unbounded; +/// use easy_parallel::Parallel; +/// +/// use edge_executor::{Executor, block_on}; +/// +/// let ex: Executor = Default::default(); +/// let (signal, shutdown) = unbounded::<()>(); +/// +/// Parallel::new() +/// // Run four executor threads. +/// .each(0..4, |_| block_on(ex.run(shutdown.recv()))) +/// // Run the main future on the current thread. +/// .finish(|| block_on(async { +/// println!("Hello world!"); +/// drop(signal); +/// })); +/// ``` +pub struct Executor<'a, const C: usize = 64> { + state: OnceCell>>, + _invariant: PhantomData>, +} + +impl<'a, const C: usize> Executor<'a, C> { + /// Creates a new executor. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::Executor; + /// + /// let ex: Executor = Default::default(); + /// ``` + pub const fn new() -> Self { + Self { + state: OnceCell::new(), + _invariant: PhantomData, + } + } + + /// Spawns a task onto the executor. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::Executor; + /// + /// let ex: Executor = Default::default(); + /// + /// let task = ex.spawn(async { + /// println!("Hello world"); + /// }); + /// ``` + /// + /// Note that if the executor's queue size is equal to the number of currently + /// spawned and running tasks, spawning this additional task might cause the executor to panic + /// later, when the task is scheduled for polling. + pub fn spawn(&self, fut: F) -> Task + where + F: Future + Send + 'a, + F::Output: Send + 'a, + { + // SAFETY: Original implementation missing safety documentation + unsafe { self.spawn_unchecked(fut) } + } + + /// Attempts to run a task if at least one is scheduled. + /// + /// Running a scheduled task means simply polling its future once. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::Executor; + /// + /// let ex: Executor = Default::default(); + /// assert!(!ex.try_tick()); // no tasks to run + /// + /// let task = ex.spawn(async { + /// println!("Hello world"); + /// }); + /// assert!(ex.try_tick()); // a task was found + /// ``` + pub fn try_tick(&self) -> bool { + if let Some(runnable) = self.try_runnable() { + runnable.run(); + + true + } else { + false + } + } + + /// Runs a single task asynchronously. + /// + /// Running a task means simply polling its future once. + /// + /// If no tasks are scheduled when this method is called, it will wait until one is scheduled. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::{Executor, block_on}; + /// + /// let ex: Executor = Default::default(); + /// + /// let task = ex.spawn(async { + /// println!("Hello world"); + /// }); + /// block_on(ex.tick()); // runs the task + /// ``` + pub async fn tick(&self) { + self.runnable().await.run(); + } + + /// Runs the executor asynchronously until the given future completes. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::{Executor, block_on}; + /// + /// let ex: Executor = Default::default(); + /// + /// let task = ex.spawn(async { 1 + 2 }); + /// let res = block_on(ex.run(async { task.await * 2 })); + /// + /// assert_eq!(res, 6); + /// ``` + pub async fn run(&self, fut: F) -> F::Output + where + F: Future + Send + 'a, + { + // SAFETY: Original implementation missing safety documentation + unsafe { self.run_unchecked(fut).await } + } + + /// Waits for the next runnable task to run. + async fn runnable(&self) -> Runnable { + poll_fn(|ctx| self.poll_runnable(ctx)).await + } + + /// Polls the first task scheduled for execution by the executor. + fn poll_runnable(&self, ctx: &Context<'_>) -> Poll { + self.state().waker.register(ctx.waker()); + + if let Some(runnable) = self.try_runnable() { + Poll::Ready(runnable) + } else { + Poll::Pending + } + } + + /// Pops the first task scheduled for execution by the executor. + /// + /// Returns + /// - `None` - if no task was scheduled for execution + /// - `Some(Runnnable)` - the first task scheduled for execution. Calling `Runnable::run` will + /// execute the task. In other words, it will poll its future. + fn try_runnable(&self) -> Option { + let runnable; + + #[cfg(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + ))] + { + runnable = self.state().queue.pop(); + } + + #[cfg(not(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + )))] + { + runnable = self.state().queue.dequeue(); + } + + runnable + } + + /// # Safety + /// + /// Original implementation missing safety documentation + unsafe fn spawn_unchecked(&self, fut: F) -> Task + where + F: Future, + { + let schedule = { + let state = self.state().clone(); + + move |runnable| { + #[cfg(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + ))] + { + state.queue.push(runnable).unwrap(); + } + + #[cfg(not(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + )))] + { + state.queue.enqueue(runnable).unwrap(); + } + + if let Some(waker) = state.waker.take() { + waker.wake(); + } + } + }; + + // SAFETY: Original implementation missing safety documentation + let (runnable, task) = unsafe { async_task::spawn_unchecked(fut, schedule) }; + + runnable.schedule(); + + task + } + + /// # Safety + /// + /// Original implementation missing safety documentation + async unsafe fn run_unchecked(&self, fut: F) -> F::Output + where + F: Future, + { + let run_forever = async { + loop { + self.tick().await; + } + }; + + run_forever.or(fut).await + } + + /// Returns a reference to the inner state. + fn state(&self) -> &Arc> { + self.state.get_or_init(|| Arc::new(State::new())) + } +} + +impl<'a, const C: usize> Default for Executor<'a, C> { + fn default() -> Self { + Self::new() + } +} + +// SAFETY: Original implementation missing safety documentation +unsafe impl<'a, const C: usize> Send for Executor<'a, C> {} +// SAFETY: Original implementation missing safety documentation +unsafe impl<'a, const C: usize> Sync for Executor<'a, C> {} + +/// A thread-local executor. +/// +/// The executor can only be run on the thread that created it. +/// +/// # Examples +/// +/// ```ignore +/// use edge_executor::{LocalExecutor, block_on}; +/// +/// let local_ex: LocalExecutor = Default::default(); +/// +/// block_on(local_ex.run(async { +/// println!("Hello world!"); +/// })); +/// ``` +pub struct LocalExecutor<'a, const C: usize = 64> { + executor: Executor<'a, C>, + _not_send: PhantomData>>, +} + +impl<'a, const C: usize> LocalExecutor<'a, C> { + /// Creates a single-threaded executor. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::LocalExecutor; + /// + /// let local_ex: LocalExecutor = Default::default(); + /// ``` + pub const fn new() -> Self { + Self { + executor: Executor::::new(), + _not_send: PhantomData, + } + } + + /// Spawns a task onto the executor. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::LocalExecutor; + /// + /// let local_ex: LocalExecutor = Default::default(); + /// + /// let task = local_ex.spawn(async { + /// println!("Hello world"); + /// }); + /// ``` + /// + /// Note that if the executor's queue size is equal to the number of currently + /// spawned and running tasks, spawning this additional task might cause the executor to panic + /// later, when the task is scheduled for polling. + pub fn spawn(&self, fut: F) -> Task + where + F: Future + 'a, + F::Output: 'a, + { + // SAFETY: Original implementation missing safety documentation + unsafe { self.executor.spawn_unchecked(fut) } + } + + /// Attempts to run a task if at least one is scheduled. + /// + /// Running a scheduled task means simply polling its future once. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::LocalExecutor; + /// + /// let local_ex: LocalExecutor = Default::default(); + /// assert!(!local_ex.try_tick()); // no tasks to run + /// + /// let task = local_ex.spawn(async { + /// println!("Hello world"); + /// }); + /// assert!(local_ex.try_tick()); // a task was found + /// ``` + pub fn try_tick(&self) -> bool { + self.executor.try_tick() + } + + /// Runs a single task asynchronously. + /// + /// Running a task means simply polling its future once. + /// + /// If no tasks are scheduled when this method is called, it will wait until one is scheduled. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::{LocalExecutor, block_on}; + /// + /// let local_ex: LocalExecutor = Default::default(); + /// + /// let task = local_ex.spawn(async { + /// println!("Hello world"); + /// }); + /// block_on(local_ex.tick()); // runs the task + /// ``` + pub async fn tick(&self) { + self.executor.tick().await; + } + + /// Runs the executor asynchronously until the given future completes. + /// + /// # Examples + /// + /// ```ignore + /// use edge_executor::{LocalExecutor, block_on}; + /// + /// let local_ex: LocalExecutor = Default::default(); + /// + /// let task = local_ex.spawn(async { 1 + 2 }); + /// let res = block_on(local_ex.run(async { task.await * 2 })); + /// + /// assert_eq!(res, 6); + /// ``` + pub async fn run(&self, fut: F) -> F::Output + where + F: Future, + { + // SAFETY: Original implementation missing safety documentation + unsafe { self.executor.run_unchecked(fut) }.await + } +} + +impl<'a, const C: usize> Default for LocalExecutor<'a, C> { + fn default() -> Self { + Self::new() + } +} + +struct State { + #[cfg(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + ))] + queue: crossbeam_queue::ArrayQueue, + #[cfg(not(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + )))] + queue: heapless::mpmc::MpMcQueue, + waker: AtomicWaker, +} + +impl State { + fn new() -> Self { + Self { + #[cfg(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + ))] + queue: crossbeam_queue::ArrayQueue::new(C), + #[cfg(not(all( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" + )))] + queue: heapless::mpmc::MpMcQueue::new(), + waker: AtomicWaker::new(), + } + } +} + +#[cfg(test)] +mod different_executor_tests { + use core::cell::Cell; + + use futures_lite::future::{block_on, pending, poll_once}; + use futures_lite::pin; + + use super::LocalExecutor; + + #[test] + fn shared_queue_slot() { + block_on(async { + let was_polled = Cell::new(false); + let future = async { + was_polled.set(true); + pending::<()>().await; + }; + + let ex1: LocalExecutor = Default::default(); + let ex2: LocalExecutor = Default::default(); + + // Start the futures for running forever. + let (run1, run2) = (ex1.run(pending::<()>()), ex2.run(pending::<()>())); + pin!(run1); + pin!(run2); + assert!(poll_once(run1.as_mut()).await.is_none()); + assert!(poll_once(run2.as_mut()).await.is_none()); + + // Spawn the future on executor one and then poll executor two. + ex1.spawn(future).detach(); + assert!(poll_once(run2).await.is_none()); + assert!(!was_polled.get()); + + // Poll the first one. + assert!(poll_once(run1).await.is_none()); + assert!(was_polled.get()); + }); + } +} + +#[cfg(test)] +mod drop_tests { + use alloc::string::String; + use core::mem; + use core::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Mutex; + use core::task::{Poll, Waker}; + + use futures_lite::future; + use once_cell::sync::Lazy; + + use super::{Executor, Task}; + + #[test] + fn leaked_executor_leaks_everything() { + static DROP: AtomicUsize = AtomicUsize::new(0); + static WAKER: Lazy>> = Lazy::new(Default::default); + + let ex: Executor = Default::default(); + + let task = ex.spawn(async { + let _guard = CallOnDrop(|| { + DROP.fetch_add(1, Ordering::SeqCst); + }); + + future::poll_fn(|cx| { + *WAKER.lock().unwrap() = Some(cx.waker().clone()); + Poll::Pending::<()> + }) + .await; + }); + + future::block_on(ex.tick()); + assert!(WAKER.lock().unwrap().is_some()); + assert_eq!(DROP.load(Ordering::SeqCst), 0); + + mem::forget(ex); + assert_eq!(DROP.load(Ordering::SeqCst), 0); + + assert!(future::block_on(future::poll_once(task)).is_none()); + assert_eq!(DROP.load(Ordering::SeqCst), 0); + } + + #[test] + fn await_task_after_dropping_executor() { + let s: String = "hello".into(); + + let ex: Executor = Default::default(); + let task: Task<&str> = ex.spawn(async { &*s }); + assert!(ex.try_tick()); + + drop(ex); + assert_eq!(future::block_on(task), "hello"); + drop(s); + } + + #[test] + fn drop_executor_and_then_drop_finished_task() { + static DROP: AtomicUsize = AtomicUsize::new(0); + + let ex: Executor = Default::default(); + let task = ex.spawn(async { + CallOnDrop(|| { + DROP.fetch_add(1, Ordering::SeqCst); + }) + }); + assert!(ex.try_tick()); + + assert_eq!(DROP.load(Ordering::SeqCst), 0); + drop(ex); + assert_eq!(DROP.load(Ordering::SeqCst), 0); + drop(task); + assert_eq!(DROP.load(Ordering::SeqCst), 1); + } + + #[test] + fn drop_finished_task_and_then_drop_executor() { + static DROP: AtomicUsize = AtomicUsize::new(0); + + let ex: Executor = Default::default(); + let task = ex.spawn(async { + CallOnDrop(|| { + DROP.fetch_add(1, Ordering::SeqCst); + }) + }); + assert!(ex.try_tick()); + + assert_eq!(DROP.load(Ordering::SeqCst), 0); + drop(task); + assert_eq!(DROP.load(Ordering::SeqCst), 1); + drop(ex); + assert_eq!(DROP.load(Ordering::SeqCst), 1); + } + + struct CallOnDrop(F); + + impl Drop for CallOnDrop { + fn drop(&mut self) { + (self.0)(); + } + } +} + +#[cfg(test)] +mod local_queue { + use alloc::boxed::Box; + + use futures_lite::{future, pin}; + + use super::Executor; + + #[test] + fn two_queues() { + future::block_on(async { + // Create an executor with two runners. + let ex: Executor = Default::default(); + let (run1, run2) = ( + ex.run(future::pending::<()>()), + ex.run(future::pending::<()>()), + ); + let mut run1 = Box::pin(run1); + pin!(run2); + + // Poll them both. + assert!(future::poll_once(run1.as_mut()).await.is_none()); + assert!(future::poll_once(run2.as_mut()).await.is_none()); + + // Drop the first one, which should leave the local queue in the `None` state. + drop(run1); + assert!(future::poll_once(run2.as_mut()).await.is_none()); + }); + } +} diff --git a/crates/bevy_tasks/src/executor.rs b/crates/bevy_tasks/src/executor.rs index 3c18ccd897fa1..fc222b5e0006c 100644 --- a/crates/bevy_tasks/src/executor.rs +++ b/crates/bevy_tasks/src/executor.rs @@ -24,10 +24,10 @@ type ExecutorInner<'a> = async_executor::Executor<'a>; type LocalExecutorInner<'a> = async_executor::LocalExecutor<'a>; #[cfg(all(not(feature = "async_executor"), feature = "edge_executor"))] -type ExecutorInner<'a> = edge_executor::Executor<'a, 64>; +type ExecutorInner<'a> = crate::edge_executor::Executor<'a, 64>; #[cfg(all(not(feature = "async_executor"), feature = "edge_executor"))] -type LocalExecutorInner<'a> = edge_executor::LocalExecutor<'a, 64>; +type LocalExecutorInner<'a> = crate::edge_executor::LocalExecutor<'a, 64>; /// Wrapper around a multi-threading-aware async executor. /// Spawning will generally require tasks to be `Send` and `Sync` to allow multiple diff --git a/crates/bevy_tasks/src/lib.rs b/crates/bevy_tasks/src/lib.rs index 6055960060ac8..e83fba33a8f0c 100644 --- a/crates/bevy_tasks/src/lib.rs +++ b/crates/bevy_tasks/src/lib.rs @@ -14,6 +14,14 @@ extern crate alloc; #[cfg(not(any(feature = "async_executor", feature = "edge_executor")))] compile_error!("Either of the `async_executor` or the `edge_executor` features must be enabled."); +#[cfg(all( + feature = "edge_executor", + not(any(feature = "std", feature = "critical-section")) +))] +compile_error!( + "`edge_executor` requires either `std` or `critical-section` features to be enabled." +); + #[cfg(not(target_arch = "wasm32"))] mod conditional_send { /// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm), @@ -43,7 +51,19 @@ pub type BoxedFuture<'a, T> = core::pin::Pin Date: Fri, 7 Mar 2025 10:15:45 +1100 Subject: [PATCH 09/11] cargo fmt --- crates/bevy_tasks/src/edge_executor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_tasks/src/edge_executor.rs b/crates/bevy_tasks/src/edge_executor.rs index 521e117eb2e96..c0821890828cb 100644 --- a/crates/bevy_tasks/src/edge_executor.rs +++ b/crates/bevy_tasks/src/edge_executor.rs @@ -220,7 +220,7 @@ impl<'a, const C: usize> Executor<'a, C> { } /// # Safety - /// + /// /// Original implementation missing safety documentation unsafe fn spawn_unchecked(&self, fut: F) -> Task where @@ -267,7 +267,7 @@ impl<'a, const C: usize> Executor<'a, C> { } /// # Safety - /// + /// /// Original implementation missing safety documentation async unsafe fn run_unchecked(&self, fut: F) -> F::Output where @@ -523,8 +523,8 @@ mod drop_tests { use alloc::string::String; use core::mem; use core::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Mutex; use core::task::{Poll, Waker}; + use std::sync::Mutex; use futures_lite::future; use once_cell::sync::Lazy; From 13fabea09c29b5099adc878f120c9fa327c38305 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 7 Mar 2025 14:13:06 +1100 Subject: [PATCH 10/11] Refactor features to allow `--no-default-features` to compile --- Cargo.toml | 11 +---- crates/bevy_app/Cargo.toml | 11 ++--- crates/bevy_app/src/app.rs | 2 +- crates/bevy_app/src/lib.rs | 8 +--- crates/bevy_app/src/schedule_runner.rs | 2 +- crates/bevy_diagnostic/Cargo.toml | 8 ++-- crates/bevy_ecs/Cargo.toml | 10 ++--- crates/bevy_internal/Cargo.toml | 11 ++--- crates/bevy_internal/src/default_plugins.rs | 2 + crates/bevy_internal/src/lib.rs | 3 ++ crates/bevy_internal/src/prelude.rs | 8 +++- crates/bevy_tasks/Cargo.toml | 14 +++---- crates/bevy_tasks/src/executor.rs | 4 +- crates/bevy_tasks/src/lib.rs | 23 +--------- .../src/single_threaded_task_pool.rs | 42 +------------------ crates/bevy_transform/Cargo.toml | 17 ++------ 16 files changed, 44 insertions(+), 132 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0e245c6edb1d2..dab13437df5bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -161,13 +161,7 @@ default = [ ] # Recommended defaults for no_std applications -default_no_std = [ - "edge_executor", - "libm", - "critical-section", - "bevy_color", - "bevy_state", -] +default_no_std = ["libm", "critical-section", "bevy_color", "bevy_state"] # Provides an implementation for picking meshes bevy_mesh_picking_backend = [ @@ -510,9 +504,6 @@ ghost_nodes = ["bevy_internal/ghost_nodes"] # Uses `async-executor` as a task execution backend. async_executor = ["std", "bevy_internal/async_executor"] -# Uses `edge-executor` as a task execution backend. -edge_executor = ["bevy_internal/edge_executor"] - # Allows access to the `std` crate. std = ["bevy_internal/std"] diff --git a/crates/bevy_app/Cargo.toml b/crates/bevy_app/Cargo.toml index c19a3329d3434..48164b2281e05 100644 --- a/crates/bevy_app/Cargo.toml +++ b/crates/bevy_app/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" keywords = ["bevy"] [features] -default = ["std", "bevy_reflect", "bevy_tasks", "bevy_ecs/default"] +default = ["std", "bevy_reflect", "bevy_ecs/default"] # Functionality @@ -23,9 +23,6 @@ reflect_functions = [ "bevy_ecs/reflect_functions", ] -## Adds support for running async background tasks -bevy_tasks = ["dep:bevy_tasks"] - # Debugging Features ## Enables `tracing` integration, allowing spans and other metrics to be reported @@ -47,14 +44,14 @@ std = [ "dep:ctrlc", "downcast-rs/std", "bevy_utils/std", - "bevy_tasks?/std", + "bevy_tasks/std", "bevy_platform_support/std", ] ## `critical-section` provides the building blocks for synchronization primitives ## on all platforms, including `no_std`. critical-section = [ - "bevy_tasks?/critical-section", + "bevy_tasks/critical-section", "bevy_ecs/critical-section", "bevy_platform_support/critical-section", "bevy_reflect?/critical-section", @@ -68,7 +65,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", default-featu bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features = false, features = [ "alloc", ] } -bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true } +bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false } bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false } # other diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 9799693aff19f..15d2f901c31c8 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1353,7 +1353,7 @@ type RunnerFn = Box AppExit>; fn run_once(mut app: App) -> AppExit { while app.plugins_state() == PluginsState::Adding { - #[cfg(all(not(target_arch = "wasm32"), feature = "bevy_tasks"))] + #[cfg(not(target_arch = "wasm32"))] bevy_tasks::tick_global_task_pools_on_main_thread(); } app.finish(); diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index 489b5415e30a3..5e4b87ff5543b 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -30,7 +30,6 @@ mod plugin; mod plugin_group; mod schedule_runner; mod sub_app; -#[cfg(feature = "bevy_tasks")] mod task_pool_plugin; #[cfg(all(any(unix, windows), feature = "std"))] mod terminal_ctrl_c_handler; @@ -42,7 +41,6 @@ pub use plugin::*; pub use plugin_group::*; pub use schedule_runner::*; pub use sub_app::*; -#[cfg(feature = "bevy_tasks")] pub use task_pool_plugin::*; #[cfg(all(any(unix, windows), feature = "std"))] pub use terminal_ctrl_c_handler::*; @@ -60,10 +58,6 @@ pub mod prelude { RunFixedMainLoopSystem, SpawnScene, Startup, Update, }, sub_app::SubApp, - Plugin, PluginGroup, + NonSendMarker, Plugin, PluginGroup, TaskPoolOptions, TaskPoolPlugin, }; - - #[cfg(feature = "bevy_tasks")] - #[doc(hidden)] - pub use crate::{NonSendMarker, TaskPoolOptions, TaskPoolPlugin}; } diff --git a/crates/bevy_app/src/schedule_runner.rs b/crates/bevy_app/src/schedule_runner.rs index 2a0e1f966a49e..952ccad072384 100644 --- a/crates/bevy_app/src/schedule_runner.rs +++ b/crates/bevy_app/src/schedule_runner.rs @@ -77,7 +77,7 @@ impl Plugin for ScheduleRunnerPlugin { let plugins_state = app.plugins_state(); if plugins_state != PluginsState::Cleaned { while app.plugins_state() == PluginsState::Adding { - #[cfg(all(not(target_arch = "wasm32"), feature = "bevy_tasks"))] + #[cfg(not(target_arch = "wasm32"))] bevy_tasks::tick_global_task_pools_on_main_thread(); } app.finish(); diff --git a/crates/bevy_diagnostic/Cargo.toml b/crates/bevy_diagnostic/Cargo.toml index be8f7cddcccde..0fc784db750ce 100644 --- a/crates/bevy_diagnostic/Cargo.toml +++ b/crates/bevy_diagnostic/Cargo.toml @@ -26,7 +26,7 @@ serialize = [ dynamic_linking = [] ## Adds integration with `sysinfo`. -sysinfo_plugin = ["sysinfo", "dep:bevy_tasks"] +sysinfo_plugin = ["sysinfo"] # Platform Compatibility @@ -40,7 +40,7 @@ std = [ "bevy_platform_support/std", "bevy_time/std", "bevy_utils/std", - "bevy_tasks?/std", + "bevy_tasks/std", ] ## `critical-section` provides the building blocks for synchronization primitives @@ -51,7 +51,7 @@ critical-section = [ "bevy_platform_support/critical-section", "bevy_time/critical-section", "bevy_utils/critical-section", - "bevy_tasks?/critical-section", + "bevy_tasks/critical-section", ] [dependencies] @@ -62,7 +62,7 @@ bevy_time = { path = "../bevy_time", version = "0.16.0-dev", default-features = bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features = false, features = [ "alloc", ] } -bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true } +bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false } bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [ "alloc", ] } diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index e42b2b62a0650..422279340803c 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -57,11 +57,7 @@ track_location = [] ## Uses `async-executor` as a task execution backend. ## This backend is incompatible with `no_std` targets. -async_executor = ["dep:bevy_tasks", "std", "bevy_tasks/async_executor"] - -## Uses `edge-executor` as a task execution backend. -## Use this instead of `async-executor` if working on a `no_std` target. -edge_executor = ["dep:bevy_tasks", "bevy_tasks/edge_executor"] +async_executor = ["std", "bevy_tasks/async_executor"] # Platform Compatibility @@ -87,7 +83,7 @@ std = [ ## `critical-section` provides the building blocks for synchronization primitives ## on all platforms, including `no_std`. critical-section = [ - "bevy_tasks?/critical-section", + "bevy_tasks/critical-section", "bevy_platform_support/critical-section", "bevy_reflect?/critical-section", ] @@ -97,7 +93,7 @@ bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [ "smallvec", ], default-features = false, optional = true } -bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true } +bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false } bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features = false, features = [ "alloc", ] } diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 8bc8da2990156..f1b73102837d8 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -329,18 +329,13 @@ libm = [ "bevy_window?/libm", ] -# Executor Backend (choose one) # Uses `async-executor` as a task execution backend. # This backend is incompatible with `no_std` targets. async_executor = ["std", "bevy_tasks/async_executor", "bevy_ecs/async_executor"] -# Uses `edge-executor` as a task execution backend. -# Use this instead of `async-executor` if working on a `no_std` target. -edge_executor = ["bevy_tasks/edge_executor", "bevy_ecs/edge_executor"] [dependencies] # bevy (no_std) bevy_app = { path = "../bevy_app", version = "0.16.0-dev", default-features = false, features = [ - "bevy_tasks", "bevy_reflect", ] } bevy_derive = { path = "../bevy_derive", version = "0.16.0-dev", default-features = false } @@ -350,10 +345,10 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev", default-features = fa ] } bevy_input = { path = "../bevy_input", version = "0.16.0-dev", default-features = false, features = [ "bevy_reflect", -] } +], optional = true } bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false, features = [ "bevy_reflect", -] } +], optional = true } bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [ "alloc", ] } @@ -367,7 +362,7 @@ bevy_time = { path = "../bevy_time", version = "0.16.0-dev", default-features = bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev", default-features = false, features = [ "bevy-support", "bevy_reflect", -] } +], optional = true } bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features = false, features = [ "alloc", ] } diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index 16aad774d3131..259a8c89226cd 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -9,8 +9,10 @@ plugin_group! { bevy_app:::TaskPoolPlugin, bevy_diagnostic:::FrameCountPlugin, bevy_time:::TimePlugin, + #[custom(cfg(any(feature = "libm", feature = "std")))] bevy_transform:::TransformPlugin, bevy_diagnostic:::DiagnosticsPlugin, + #[custom(cfg(any(feature = "libm", feature = "std")))] bevy_input:::InputPlugin, #[custom(cfg(not(feature = "bevy_window")))] bevy_app:::ScheduleRunnerPlugin, diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index ae0176f0d11dd..37bcef26b2ad7 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -39,11 +39,13 @@ pub use bevy_gizmos as gizmos; pub use bevy_gltf as gltf; #[cfg(feature = "bevy_image")] pub use bevy_image as image; +#[cfg(any(feature = "libm", feature = "std"))] pub use bevy_input as input; #[cfg(feature = "bevy_input_focus")] pub use bevy_input_focus as input_focus; #[cfg(feature = "bevy_log")] pub use bevy_log as log; +#[cfg(any(feature = "libm", feature = "std"))] pub use bevy_math as math; #[cfg(feature = "bevy_pbr")] pub use bevy_pbr as pbr; @@ -66,6 +68,7 @@ pub use bevy_tasks as tasks; #[cfg(feature = "bevy_text")] pub use bevy_text as text; pub use bevy_time as time; +#[cfg(any(feature = "libm", feature = "std"))] pub use bevy_transform as transform; #[cfg(feature = "bevy_ui")] pub use bevy_ui as ui; diff --git a/crates/bevy_internal/src/prelude.rs b/crates/bevy_internal/src/prelude.rs index 3bf13d34c98f9..9f7dd8f33e267 100644 --- a/crates/bevy_internal/src/prelude.rs +++ b/crates/bevy_internal/src/prelude.rs @@ -1,9 +1,13 @@ #[doc(hidden)] pub use crate::{ - app::prelude::*, ecs::prelude::*, input::prelude::*, math::prelude::*, reflect::prelude::*, - time::prelude::*, transform::prelude::*, utils::prelude::*, DefaultPlugins, MinimalPlugins, + app::prelude::*, ecs::prelude::*, reflect::prelude::*, time::prelude::*, utils::prelude::*, + DefaultPlugins, MinimalPlugins, }; +#[doc(hidden)] +#[cfg(any(feature = "libm", feature = "std"))] +pub use crate::{input::prelude::*, math::prelude::*, transform::prelude::*}; + #[doc(hidden)] #[cfg(feature = "bevy_log")] pub use crate::log::prelude::*; diff --git a/crates/bevy_tasks/Cargo.toml b/crates/bevy_tasks/Cargo.toml index c3e8bb3a8ee08..b035e1abf88d1 100644 --- a/crates/bevy_tasks/Cargo.toml +++ b/crates/bevy_tasks/Cargo.toml @@ -18,11 +18,7 @@ std = [ ] multi_threaded = ["std", "dep:async-channel", "dep:concurrent-queue"] async_executor = ["std", "dep:async-executor"] -edge_executor = ["dep:atomic-waker", "dep:once_cell", "dep:crossbeam-queue"] -critical-section = [ - "bevy_platform_support/critical-section", - "once_cell?/critical-section", -] +critical-section = ["bevy_platform_support/critical-section"] [dependencies] bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [ @@ -41,11 +37,13 @@ async-executor = { version = "1.11", optional = true } async-channel = { version = "2.3.0", optional = true } async-io = { version = "2.0.0", optional = true } concurrent-queue = { version = "2.0.0", optional = true } -atomic-waker = { version = "1", default-features = false, optional = true } -once_cell = { version = "1.18", default-features = false, optional = true } +atomic-waker = { version = "1", default-features = false } +once_cell = { version = "1.18", default-features = false, features = [ + "critical-section", +] } crossbeam-queue = { version = "0.3", default-features = false, features = [ "alloc", -], optional = true } +] } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4" diff --git a/crates/bevy_tasks/src/executor.rs b/crates/bevy_tasks/src/executor.rs index fc222b5e0006c..d6b7234e74c01 100644 --- a/crates/bevy_tasks/src/executor.rs +++ b/crates/bevy_tasks/src/executor.rs @@ -23,10 +23,10 @@ type ExecutorInner<'a> = async_executor::Executor<'a>; #[cfg(feature = "async_executor")] type LocalExecutorInner<'a> = async_executor::LocalExecutor<'a>; -#[cfg(all(not(feature = "async_executor"), feature = "edge_executor"))] +#[cfg(not(feature = "async_executor"))] type ExecutorInner<'a> = crate::edge_executor::Executor<'a, 64>; -#[cfg(all(not(feature = "async_executor"), feature = "edge_executor"))] +#[cfg(not(feature = "async_executor"))] type LocalExecutorInner<'a> = crate::edge_executor::LocalExecutor<'a, 64>; /// Wrapper around a multi-threading-aware async executor. diff --git a/crates/bevy_tasks/src/lib.rs b/crates/bevy_tasks/src/lib.rs index e83fba33a8f0c..094d8d5fd2183 100644 --- a/crates/bevy_tasks/src/lib.rs +++ b/crates/bevy_tasks/src/lib.rs @@ -11,17 +11,6 @@ extern crate std; extern crate alloc; -#[cfg(not(any(feature = "async_executor", feature = "edge_executor")))] -compile_error!("Either of the `async_executor` or the `edge_executor` features must be enabled."); - -#[cfg(all( - feature = "edge_executor", - not(any(feature = "std", feature = "critical-section")) -))] -compile_error!( - "`edge_executor` requires either `std` or `critical-section` features to be enabled." -); - #[cfg(not(target_arch = "wasm32"))] mod conditional_send { /// Use [`ConditionalSend`] to mark an optional Send trait bound. Useful as on certain platforms (eg. Wasm), @@ -51,19 +40,9 @@ pub type BoxedFuture<'a, T> = core::pin::Pin(PhantomData); - - impl<'a> LocalExecutor<'a> { - /// Dummy implementation - pub const fn new() -> Self { - Self(PhantomData) - } - - /// Dummy implementation - pub fn try_tick(&self) -> bool { - unimplemented!() - } - - /// Dummy implementation - pub fn spawn(&self, _: impl Future + 'a) -> Task { - unimplemented!() - } - } -} - -#[cfg(not(any(feature = "async_executor", feature = "edge_executor")))] -use dummy_executor::LocalExecutor; - #[cfg(feature = "std")] thread_local! { static LOCAL_EXECUTOR: LocalExecutor<'static> = const { LocalExecutor::new() }; diff --git a/crates/bevy_transform/Cargo.toml b/crates/bevy_transform/Cargo.toml index bab7607b9f4c7..aa20a922aa212 100644 --- a/crates/bevy_transform/Cargo.toml +++ b/crates/bevy_transform/Cargo.toml @@ -15,7 +15,7 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev", default-features = fa bevy_log = { path = "../bevy_log", version = "0.16.0-dev", default-features = false, optional = true } bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false } bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", default-features = false, optional = true } -bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true } +bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false } bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features = false, optional = true } serde = { version = "1", default-features = false, features = [ "derive", @@ -59,16 +59,7 @@ bevy_reflect = [ ## Uses `async-executor` as a task execution backend. ## This backend is incompatible with `no_std` targets. -async_executor = [ - "std", - "dep:bevy_tasks", - "dep:bevy_utils", - "bevy_tasks/async_executor", -] - -## Uses `edge-executor` as a task execution backend. -## Use this instead of `async-executor` if working on a `no_std` target. -edge_executor = ["dep:bevy_tasks", "bevy_tasks/edge_executor"] +async_executor = ["std", "dep:bevy_utils", "bevy_tasks/async_executor"] # Platform Compatibility @@ -82,7 +73,7 @@ std = [ "bevy_ecs?/std", "bevy_math/std", "bevy_reflect?/std", - "bevy_tasks?/std", + "bevy_tasks/std", "bevy_utils?/std", "serde?/std", ] @@ -92,7 +83,7 @@ std = [ critical-section = [ "bevy_app?/critical-section", "bevy_ecs?/critical-section", - "bevy_tasks?/critical-section", + "bevy_tasks/critical-section", "bevy_reflect?/critical-section", ] From 3d09e4b8a838d6493aa9842bbc567fcc03cfa2eb Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 7 Mar 2025 14:20:22 +1100 Subject: [PATCH 11/11] Update cargo_features.md --- docs/cargo_features.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/cargo_features.md b/docs/cargo_features.md index d559b06012bc6..a58c4f14f94db 100644 --- a/docs/cargo_features.md +++ b/docs/cargo_features.md @@ -75,7 +75,6 @@ The default feature set enables most of the expected features of a game engine, |default_no_std|Recommended defaults for no_std applications| |detailed_trace|Enable detailed trace event logging. These trace events are expensive even when off, thus they require compile time opt-in| |dynamic_linking|Force dynamic linking, which improves iterative compile times| -|edge_executor|Uses `edge-executor` as a task execution backend.| |embedded_watcher|Enables watching in memory asset providers for Bevy Asset hot-reloading| |experimental_pbr_pcss|Enable support for PCSS, at the risk of blowing past the global, per-shader sampler limit on older/lower-end GPUs| |exr|EXR image format support|