Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking Issue: MVP no_std Bevy #15460

Open
bushrat011899 opened this issue Sep 26, 2024 · 19 comments
Open

Tracking Issue: MVP no_std Bevy #15460

bushrat011899 opened this issue Sep 26, 2024 · 19 comments
Assignees
Labels
A-Cross-Cutting Impacts the entire engine C-Dependencies A change to the crates that Bevy depends on C-Feature A new feature, making something new possible C-Tracking-Issue An issue that collects information about a broad development initiative D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes O-Embedded Weird hardware and no_std platforms X-Contentious There are nontrivial implications that should be thought through

Comments

@bushrat011899
Copy link
Contributor

bushrat011899 commented Sep 26, 2024

This is a tracking issue for progress on a no_std compatible subset of Bevy. The tasks are ordered roughly in sequence (bevy_app can't be no_std until bevy_ecs is for example).

Overview

Below is a visualisation of the crates planned to be ported to no_std. Edges indicate the primary blocker for a crate being ported. The 🚧 symbol indicates that this crate is in-progress, while ✅ indicates it is now available in no_std.

graph TD;
    bevy_a11y
    bevy_app[bevy_app ✅]
    bevy_asset
    bevy_color[bevy_color ✅]
    bevy_core[bevy_core* ✅]
    bevy_ecs[bevy_ecs ✅]
    bevy_hierarchy[bevy_hierarchy ✅]
    bevy_input[bevy_input ✅]
    bevy_input_focus
    bevy_math[bevy_math ✅]
    bevy_mikktspace[bevy_mikktspace ✅]
    bevy_ptr[bevy_ptr ✅]
    bevy_reflect[bevy_reflect✅]
    bevy_state[bevy_state ✅]
    bevy_tasks[bevy_tasks ✅]
    bevy_time
    bevy_transform[bevy_transform ✅]
    bevy_utils[bevy_utils ✅]
    bevy_window[bevy_window ✅]

    bevy_ptr-->bevy_ecs;

    bevy_utils-->bevy_ecs;

    bevy_tasks-->bevy_ecs;

    bevy_ecs-->bevy_app;

    bevy_app-->bevy_core;
    bevy_app-->bevy_a11y;
    bevy_app-->bevy_asset;
    bevy_app-->bevy_time;
    bevy_app-->bevy_log;

    bevy_time-->bevy_diagnostics;

    bevy_core-->bevy_input;
    bevy_core-->bevy_diagnostics;
    bevy_core-->bevy_hierarchy;
    
    bevy_asset-->bevy_image;

    bevy_color-->bevy_image;

    bevy_mikktspace-->bevy_mesh;

    bevy_hierarchy-->bevy_remote;
    bevy_hierarchy-->bevy_state;
    bevy_hierarchy-->bevy_transform;
    bevy_hierarchy-->bevy_input_focus;

    bevy_transform-->bevy_mesh;
    bevy_transform-->bevy_scene;
    
    bevy_math-->bevy_input;
    bevy_math-->bevy_color;

    bevy_input-->bevy_window;

    bevy_input_focus-->bevy_a11y;

    bevy_window-->bevy_input_focus;

    bevy_reflect-->bevy_ecs;

    bevy_image-->bevy_mesh;
Loading

Core Tasks

These tasks must be completed for a no_std Bevy to become usable at all.

Prerequisites ✅

bevy_ptr

Done prior to initiative.

bevy_utils

Provide an appropriate Instant type which can be controlled by the user in no_std contexts, or avoid its use. Move web-time into wasm32-only dependencies (doesn't need to exist outside web anyway!). Make thread_local optional.

Done!

bevy_tasks

Done!

bevy_macro_utils

Update derive_label to use Box from alloc (requires wrapping the quoted impl in a const _: () = { ... } so that extern crate alloc wont conflict with the outer namespace).

Done!

bevy_ecs

Done!

bevy_app

Merged!

bevy_core1

Merged!

bevy_internal / bevy

  • Thread std / alloc features from sub-crates through to the final bevy crate.

Blocked on bevy_core.

CI 🚧

Bonus Features

These tasks aren't strictly required, but should be completed to close the gap between no_std and std Bevy. The more functionality we can provide in no_std, the more the community can develop for it.

bevy_a11y

This crate is was blocked on AccessKit's lack of no_std support. @DataTriny pointed out AccessKit 0.17 now supports no_std! This should now be quite straightforward to add no_std support to once the other internal blockers are resolved (bevy_app, etc.)

bevy_asset

Reliance on filesystem operations will make this interesting, but a lot of the asset functionality exists outside of files and folders (processing, etc.). It's reasonable to consider that a no_std platform could have a custom AssetSource (and accompanying AssetReader/Writer/etc.).

bevy_color

Done!

bevy_derive

Should work as-is, but need to test.

bevy_diagnostic

Blocked on bevy_core.

bevy_hierarchy

Merged!

bevy_image

Blocked on bevy_asset. Would also require some substantial feature-gating to isolate out the no_std compatible subset.

bevy_input

Awaiting merge.

bevy_input_focus

Blocked on bevy_hierarchy and bevy_window.

bevy_log

Blocked on bevy_ecs.

bevy_math

Done!

bevy_mesh

Blocked on bevy_image, bevy_transform, and hexasphere. hexasphere would need upstream changes, but on a first-glance looks like to could be no_std.

bevy_mikktspace

Done!

bevy_reflect

Done!

bevy_remote

Blocked on bevy_hierarchy and a design. Currently built around networking, but could support serial commands instead, and would make debugging on embedded much easier too.

bevy_scene

Blocked on bevy_hierarchy and bevy_asset.

bevy_state

Done!

bevy_time

Blocked on bevy_ecs, but also needs some design work, since Instant is a part of std and not core. Providing an unsafe method for manually updating Time's based on a Duration would be sufficient.

bevy_transform

Merged!

bevy_window

Merged!

Not Planned

These crates can't be ported to no_std because they are highly platform specific. If you see something on this list that could be ported, please let me know!

bevy_animation

Blocked by bevy_render.

Currently only using the DiGraph type with no edge data and only a single node type AnimationGraphNode (and a serializable alternate SerializedAnimationGraphNode).

bevy_audio

Currently undergoing a major re-write so this is subject to change. I suspect even with the re-write no_std support would be blocked on a fundamental dependency such as cpal. Like rendering, audio is very platform dependent so there likely isn't a viable API Bevy could provide that would be simultaneously feature-rich enough for use on common platforms (PC, etc.) while being low-level enough for no_std ones too.

bevy_core_pipeline

Blocked by bevy_render.

bevy_dev_tools

Blocked by bevy_render.

bevy_dylib

Unfamiliar with the dynamic linking this crate provides. I don't see any reason why it couldn't be supported in no_std, but I would definitely require an SME to assist with getting it working.

bevy_encase_derive

Exclusively used with encase, which is a part of the rendering side of Bevy.

bevy_gilrs

Built around gilrs which does not currently have any no_std support. There might be a way to upstream no_std support by relying on something like SDL, but I'm not familiar enough with the project to make a fair assessment on the viability here.

bevy_gizmos

Blocked by bevy_render.

bevy_gltf

Blocked by bevy_render. It may make sense to find a way to break this dependency, since gLTF can be used independently of wgpu (e.g., with a user-created OpenGL renderer backend), but this would need an SME for sure.

bevy_pbr

Blocked by bevy_render and wgpu. Without support for WGSL shaders there's no real point in having this crate supported in no_std.

bevy_render

Massive crate very deeply integrated with wgpu, which is not just std reliant, but also platform dependent too. I don't think it will ever make sense to have a no_std bevy_render. Maybe could have value in splitting out some abstractions, but I don't know.

bevy_sprite

Blocked on bevy_render.

bevy_text

Blocked on bevy_render.

bevy_ui

Blocked on bevy_render.

bevy_winit

Blocked on winit. Likely couldn't be made no_std upstream either since it's entirely platform dependent.

General Notes

thiserror

Note: this is now outdated, as thiserror version 2 includes no_std support and is now publicly available.

thiserror is currently not available in a no_std form due to its use of the ::std::error::Error path for Error (which it continues to use for MSRV backwards compatibility). There is a PR to add no_std support to thiserror which preserves that MSRV requirement, but it's unclear if/when that will be merged and released.

One alternative is to link against the PR instead of the published version of thiserror:

thiserror = {
  git = "https://github.com/quartiq/thiserror",
  rev = "515bd36da54dbc346250026ddc349c88851e4bb1",
  default-features = false,
}

Another alternative is to switch to using derive_more. This would require adding explicit calls to derive(From, Display) as well, which adds to the noise. Additionally, it isn't already in the dependency tree, so its inclusion may be contentious.

Due to delays in thiserror's no_std support, we have decided to use derive_more.

portable-atomic

Certain platforms, such as the Raspberry Pi Pico, could run Bevy once no_std support is added, but can't due to Bevy's use of certain atomic features. To work around this issue, Bevy should employ portable-atomic and its sibling portable-atomic-util. These crates provide suitable replacements for the various AtomicX types and Arc.

This adds cfg(...) burden to the project, but would be limited in scope to bevy_ecs and bevy_tasks (the largest users of atomic types), at least initially. Additionally, there is issue with coercion since portable_atomic_util::Arc is a 3rd party smart-pointer, so you cannot, for example, create an Arc<dyn T> directly from an Arc<impl T>. There is a simple workaround, but at a small performance cost for unsized types. However, this will be resolved once #18598 stabilises.

Platform Support

Being no_std is necessary for certain platforms, but it is not always sufficient. Below is a table of platforms that I have tested:

Name Target Builds Notes
UEFI x86_64-unknown-uefi Runs Boots on emulated and real hardware, supported by the uefi crate.
GameBoy Advance thumbv4t-none-eabi Partially The platform does not support all atomic operations (e.g., CAS), which Bevy directly and transiently relies on. Moving from tracing to log, and using portable_atomics is sufficient to make this platform compile.
Nintendo Switch aarch64-nintendo-switch-freestanding Compiles I cannot test the binary produced by cargo nx on real hardware or an emulator to confirm it actually works.
PlayStation One mipsel-sony-psx Partially The platform does not support all atomic operations (e.g., CAS), which Bevy directly and transiently relies on. Moving from tracing to log, and using portable_atomics is sufficient to make this platform compile.
MSP430 msp430-none-elf No This platform is 16-bit, which breaks too many assumptions made by dependencies like zerocopy.
Playdate thumbv7em-none-eabihf Runs Runs but requires a patch to fixedbitset to disabled SIMD. Could potentially be fixed from within Bevy without the patch though.
Raspberry Pi Pico thumbv6m-none-eabi Runs Runs but requires adopting portable_atomics within Bevy, since the Pico doesn't support the atomic CAS instructions required.

I have a prototype of no_std compatible Bevy available on this branch. It's not being actively maintained, as it is a proof of concept for upstream no_std support (use at your own risk, etc.). However, if anyone has a particular platform they'd like to use Bevy on, please feel free to test using this branch and let me know what kind of compatibility you have. In general:

  • You must be able to compile a Rust project for this platform. (I hope this goes without saying!)
  • You must have alloc and core available.
  • Your platform must support Atomic CAS (hoping to relax this in the future!)
  • Only the bevy_app, bevy_ecs, bevy_utils, and bevy_tasks are compatible in this branch, and must be imported directly (e.g., you can't use bevy;, instead use bevy_app;). Additionally, you must disable default features for no_std compatibility.
  • Your platform must be 32-bit or higher due to safety concerns in bevy_ecs. For further information, see [Merged by Bors] - Fail to compile on 16-bit platforms #4736.

Having an std Feature

I've posted a more detailed write-up here. But as a succinct warning: no_std crates should unconditionally be #[no_std] to ensure consistent implicit prelude.

#![no_std]

#[cfg(feature = "std")]
extern crate std;

These findings are acted upon in #17086.

Footnotes

  1. bevy_core has been removed, effectively resolving its no_std compatibility.

@bushrat011899 bushrat011899 added C-Feature A new feature, making something new possible C-Dependencies A change to the crates that Bevy depends on C-Tracking-Issue An issue that collects information about a broad development initiative A-Cross-Cutting Impacts the entire engine X-Contentious There are nontrivial implications that should be thought through D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes labels Sep 26, 2024
@BD103
Copy link
Member

BD103 commented Sep 27, 2024

Looks like there is some effort to make thiserror support #![no_std] in dtolnay/thiserror#304. Looks like it's on hold until the author responds, though.

@bushrat011899
Copy link
Contributor Author

Yeah that's where I got the (temporary) fix from:

thiserror = {
  git = "https://github.com/quartiq/thiserror",
  rev = "515bd36da54dbc346250026ddc349c88851e4bb1",
  default-features = false,
}

I'm hoping the PR is merged sooner rather than later, but there's a similar issue with petgraph where there does exist a no_std compatible version, but it's waiting in the wings.

In both cases we have options for how to proceed. Either waiting for those crates to get updated, replacing them with something equivalent, or developing a replacement based on these prior efforts.

github-merge-queue bot pushed a commit that referenced this issue Sep 27, 2024
# Objective

- Contributes to #15460

## Solution

- Wrap `derive_label` `quote!` in an anonymous constant which contains
an `extern crate alloc` statement, allowing use of the `alloc` namespace
even when a user has not brought in the crate themselves.

## Testing

- CI passed locally.

## Notes

We can't generate code that uses `::std::boxed::Box` in `no_std`
environments, but we also can't rely on `::alloc::boxed::Box` either,
since the user might not have declared `extern crate alloc`. To resolve
this, the generated code is wrapped in an anonymous constant which
contains the `extern crate alloc` invocation.

This does mean the macro is no longer hygienic against cases where the
user provides an alternate `alloc` crate, however I believe this is an
acceptable compromise.

Additionally, this crate itself doesn't need to be `no_std`, it just
needs to _generate_ `no_std` compatible code.

---------

Co-authored-by: Alice Cecile <[email protected]>
rudderbucky pushed a commit to rudderbucky/bevy that referenced this issue Sep 27, 2024
)

# Objective

- Contributes to bevyengine#15460

## Solution

- Wrap `derive_label` `quote!` in an anonymous constant which contains
an `extern crate alloc` statement, allowing use of the `alloc` namespace
even when a user has not brought in the crate themselves.

## Testing

- CI passed locally.

## Notes

We can't generate code that uses `::std::boxed::Box` in `no_std`
environments, but we also can't rely on `::alloc::boxed::Box` either,
since the user might not have declared `extern crate alloc`. To resolve
this, the generated code is wrapped in an anonymous constant which
contains the `extern crate alloc` invocation.

This does mean the macro is no longer hygienic against cases where the
user provides an alternate `alloc` crate, however I believe this is an
acceptable compromise.

Additionally, this crate itself doesn't need to be `no_std`, it just
needs to _generate_ `no_std` compatible code.

---------

Co-authored-by: Alice Cecile <[email protected]>
github-merge-queue bot pushed a commit that referenced this issue Sep 30, 2024
# Objective

- Contributes to #15460
- Allows `bevy_mikktspace` to be used in `no_std` contexts.

## Solution

- Added `std` (default) and `libm` features which control the inclusion
of the standard library. To use `bevy_mikktspace` in `no_std`
environments, enable the `libm` feature.

## Testing

- CI
- `cargo clippy -p bevy_mikktspace --target "x86_64-unknown-none"
--no-default-features --features libm`
@bushrat011899 bushrat011899 self-assigned this Oct 4, 2024
robtfm pushed a commit to robtfm/bevy that referenced this issue Oct 4, 2024
)

# Objective

- Contributes to bevyengine#15460

## Solution

- Wrap `derive_label` `quote!` in an anonymous constant which contains
an `extern crate alloc` statement, allowing use of the `alloc` namespace
even when a user has not brought in the crate themselves.

## Testing

- CI passed locally.

## Notes

We can't generate code that uses `::std::boxed::Box` in `no_std`
environments, but we also can't rely on `::alloc::boxed::Box` either,
since the user might not have declared `extern crate alloc`. To resolve
this, the generated code is wrapped in an anonymous constant which
contains the `extern crate alloc` invocation.

This does mean the macro is no longer hygienic against cases where the
user provides an alternate `alloc` crate, however I believe this is an
acceptable compromise.

Additionally, this crate itself doesn't need to be `no_std`, it just
needs to _generate_ `no_std` compatible code.

---------

Co-authored-by: Alice Cecile <[email protected]>
robtfm pushed a commit to robtfm/bevy that referenced this issue Oct 4, 2024
# Objective

- Contributes to bevyengine#15460
- Allows `bevy_mikktspace` to be used in `no_std` contexts.

## Solution

- Added `std` (default) and `libm` features which control the inclusion
of the standard library. To use `bevy_mikktspace` in `no_std`
environments, enable the `libm` feature.

## Testing

- CI
- `cargo clippy -p bevy_mikktspace --target "x86_64-unknown-none"
--no-default-features --features libm`
github-merge-queue bot pushed a commit that referenced this issue Oct 4, 2024
# Objective

- Contributes to #15460

## Solution

- Made `web-time` a `wasm32`-only dependency.
- Moved time-related exports to its own module for clarity.
- Feature-gated allocator requirements for `hashbrown` behind `alloc`.
- Enabled compile-time RNG for `ahash` (runtime RNG will preferentially
used in `std` environments)
- Made `thread_local` optional by feature-gating the `Parallel` type.

## Testing

- Ran CI locally.
- `cargo build -p bevy_utils --target "x86_64-unknown-none"
--no-default-features`
@bushrat011899
Copy link
Contributor Author

After some discussion on the Discord, I'm going to open PRs to replace thiserror with derive_more for at least bevy_ecs and bevy_app in the near-term. A quick experiment on bevy_ecs made the change look pretty minor, and the crate does offer more functionality than thiserror does on its own.

github-merge-queue bot pushed a commit that referenced this issue Dec 17, 2024
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `async_executor` (default)
  - `edge_executor`
  - `critical-section`
  - `portable-atomic`
- Gated `tracing` in `bevy_utils` to allow compilation on certain
platforms
- Switched from `tracing` to `log` for simple message logging within
`bevy_ecs`. Note that `tracing` supports capturing from `log` so this
should be an uncontroversial change.
- Fixed imports and added feature gates as required 
- Made `bevy_tasks` optional within `bevy_ecs`. Turns out it's only
needed for parallel operations which are already gated behind
`multi_threaded` anyway.

## Testing

- Added to `compile-check-no-std` CI command
- `cargo check -p bevy_ecs --no-default-features --features
edge_executor,critical-section,portable-atomic --target
thumbv6m-none-eabi`
- `cargo check -p bevy_ecs --no-default-features --features
edge_executor,critical-section`
- `cargo check -p bevy_ecs --no-default-features`

## Draft Release Notes

Bevy's core ECS now supports `no_std` platforms.

In prior versions of Bevy, it was not possible to work with embedded or
niche platforms due to our reliance on the standard library, `std`. This
has blocked a number of novel use-cases for Bevy, such as an embedded
database for IoT devices, or for creating games on retro consoles.

With this release, `bevy_ecs` no longer requires `std`. To use Bevy on a
`no_std` platform, you must disable default features and enable the new
`edge_executor` and `critical-section` features. You may also need to
enable `portable-atomic` and `critical-section` if your platform does
not natively support all atomic types and operations used by Bevy.

```toml
[dependencies]
bevy_ecs = { version = "0.16", default-features = false, features = [
  # Required for platforms with incomplete atomics (e.g., Raspberry Pi Pico)
  "portable-atomic",
  "critical-section",

  # Optional
  "bevy_reflect",
  "serialize",
  "bevy_debug_stepping",
  "edge_executor"
] }
```

Currently, this has been tested on bare-metal x86 and the Raspberry Pi
Pico. If you have trouble using `bevy_ecs` on a particular platform,
please reach out either through a GitHub issue or in the `no_std`
working group on the Bevy Discord server.

Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!

## Notes

- Creating PR in draft to ensure CI is passing before requesting
reviews.
- This implementation has no support for multithreading in `no_std`,
especially due to `NonSend` being unsound if allowed in multithreading.
The reason is we cannot check the `ThreadId` in `no_std`, so we have no
mechanism to at-runtime determine if access is sound.

---------

Co-authored-by: Alice Cecile <[email protected]>
Co-authored-by: Vic <[email protected]>
github-merge-queue bot pushed a commit that referenced this issue Dec 18, 2024
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `bevy_tasks` (default)
  - `downcast ` (default)
  - `portable-atomic`
  - `critical-section`
- `downcast` and `bevy_tasks` are now optional dependencies for
`bevy_app`.

## Testing

- CI
- Personal UEFI and Raspberry Pi Pico demo applications compile and run
against this branch

## Draft Release Notes

Bevy's application framework now supports `no_std` platforms.

Following up on `bevy_ecs` gaining `no_std` support, `bevy_app` extends
the functionality available on these targets to include the powerful
`App` and `Plugin` abstractions. With this, library authors now have the
option of making their plugins `no_std` compatible, or even offering
plugins specifically to improve Bevy on certain embedded platforms!

To start making a `no_std` compatible plugin, simply disable default
features when including `bevy_app`:

```toml
[dependencies]
bevy_app = { version = "0.16", default-features = false }
```

We encourage library authors to do this anyway, as it can also help with
compile times and binary size on all platforms.

Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!

## Notes

- `downcast-rs` is optional as it isn't compatible with
`portable-atomic`. I will investigate making a PR upstream to add
support for this functionality, as it should be very straightforward.
- In line with the `bevy_ecs` no-std-ification, I've added documentation
to all features, and grouped them as well.
- ~~Creating this PR in draft while CI runs and so I can polish before
review.~~

---------

Co-authored-by: Alice Cecile <[email protected]>
github-merge-queue bot pushed a commit that referenced this issue Dec 29, 2024
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)

## Testing

- CI

## Notes

- There was a minor issue with `bevy_reflect`'s `smallvec` feature
noticed in this PR which I have also resolved here. I can split this out
if desired, but I've left it here for now as it's a very small change
and I don't consider this PR itself to be very controversial.
github-merge-queue bot pushed a commit that referenced this issue Dec 29, 2024
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `smol_str` (default)
  - `portable-atomic`
  - `critical-section`
  - `libm`
- Fixed an existing issue where `bevy_reflect` wasn't properly feature
gated.

## Testing

- CI

## Notes

- There were some minor issues with `bevy_math` and `bevy_ecs` noticed
in this PR which I have also resolved here. I can split these out if
desired, but I've left them here for now as they're very small changes
and I don't consider this PR itself to be very controversial.
- `libm`, `portable-atomic`, and `critical-section` are shortcuts to
enable the relevant features in dependencies, making the usage of this
crate on atomically challenged platforms possible and simpler.
- `smol_str` is gated as it doesn't support atomically challenged
platforms (e.g., Raspberry Pi Pico). I have an issue and a
[PR](rust-analyzer/smol_str#91) to discuss this
upstream.
github-merge-queue bot pushed a commit that referenced this issue Dec 29, 2024
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `portable-atomic`
  - `critical-section`

## Testing

- CI

## Notes

- `portable-atomic`, and `critical-section` are shortcuts to enable the
relevant features in dependencies, making the usage of this crate on
atomically challenged platforms possible and simpler.
- This PR is blocked until #17027 is merged (as it depends on fixes for
the `once!` macro). Once merged, the change-count for this PR should
reduce.
@TimJentzsch
Copy link
Contributor

I think the thiserror note can be updated now that it supports no_std.

github-merge-queue bot pushed a commit that referenced this issue Dec 30, 2024
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `alloc` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `alloc` feature added to allow using this crate in `no_alloc`
environments.
- `bevy_reflect` was previously always enabled when `bevy-support` was
enabled, which isn't how most other crates handle reflection. I've
brought this in line with how most crates gate `bevy_reflect`.
@bushrat011899
Copy link
Contributor Author

I think the thiserror note can be updated now that it supports no_std.

Agreed! I've added a little preface note indicating that the below information was written prior to version 2 of thiserror.

@TimJentzsch TimJentzsch added the O-Embedded Weird hardware and no_std platforms label Dec 31, 2024
github-merge-queue bot pushed a commit that referenced this issue Jan 1, 2025
# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `bevy_reflect` was previously always enabled, which isn't how most
other crates handle reflection. I've brought this in line with how most
crates gate `bevy_reflect`. This is where the majority of the changes
come from in this PR.

---------

Co-authored-by: Alice Cecile <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added two new features, `std` (default) and `alloc`, gating `std` and
`alloc` behind them respectively.
- Added missing `f32` functions to `std_ops` as required. These `f32`
methods have been added to the `clippy.toml` deny list to aid in
`no_std` development.

## Testing

- CI
- `cargo clippy -p bevy_math --no-default-features --features libm
--target "x86_64-unknown-none"`
- `cargo test -p bevy_math --no-default-features --features libm`
- `cargo test -p bevy_math --no-default-features --features "libm,
alloc"`
- `cargo test -p bevy_math --no-default-features --features "libm,
alloc, std"`
- `cargo test -p bevy_math --no-default-features --features "std"`

## Notes

The following items require the `alloc` feature to be enabled:

- `CubicBSpline`
- `CubicBezier`
- `CubicCardinalSpline`
- `CubicCurve`
- `CubicGenerator`
- `CubicHermite`
- `CubicNurbs`
- `CyclicCubicGenerator`
- `RationalCurve`
- `RationalGenerator`
- `BoxedPolygon`
- `BoxedPolyline2d`
- `BoxedPolyline3d`
- `SampleCurve`
- `SampleAutoCurve`
- `UnevenSampleCurve`
- `UnevenSampleAutoCurve`
- `EvenCore`
- `UnevenCore`
- `ChunkedUnevenCore`

This requirement could be relaxed in certain cases, but I had erred on
the side of gating rather than modifying. Since `no_std` is a new set of
platforms we are adding support to, and the `alloc` feature is enabled
by default, this is not a breaking change.

---------

Co-authored-by: Benjamin Brienen <[email protected]>
Co-authored-by: Matty <[email protected]>
Co-authored-by: Joona Aalto <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Removed `petgraph` as a dependency from the `bevy_ecs` crate.
- Replaced `TarjanScc` and `GraphMap` with specialised in-tree
alternatives.

## Testing

- Ran CI locally.
- Added new unit tests to check ordering invariants.
- Confirmed `petgraph` is no longer present in `cargo tree -p bevy_ecs`

## Migration Guide

The `Dag::graph` method no longer returns a `petgraph` `DiGraph` and
instead returns the new `DiGraph` type within `bevy_ecs`. Edge and node
iteration methods are provided so conversion to the `petgraph` type
should be trivial if required.

## Notes

- `indexmap` was already in the dependency graph for `bevy_ecs`, so its
inclusion here makes no difference to compilation time for Bevy.
- The implementation for `Graph` is heavily inspired from the `petgraph`
original, with specialisations added to simplify and improve the type.
- `petgraph` does have public plans for `no_std` support, however there
is no timeframe on if or when that functionality will be available.
Moving to an in-house solution in the interim allows Bevy to continue
developing its `no_std` offerings and further explore alternate graphing
options.

---------

Co-authored-by: Lixou <[email protected]>
Co-authored-by: vero <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added `std` feature (enabled by default)

## Testing

- CI
- `cargo check -p bevy_reflect --no-default-features --target
"x86_64-unknown-none"`
- UEFI demo application runs with this branch of `bevy_reflect`,
allowing `derive(Reflect)`

## Notes

- The [`spin`](https://crates.io/crates/spin) crate has been included to
provide `RwLock` and `Once` (as an alternative to `OnceLock`) when the
`std` feature is not enabled. Another alternative may be more desirable,
please provide feedback if you have a strong opinion here!
- Certain items (`Box`, `String`, `ToString`) provided by `alloc` have
been added to `__macro_exports` as a way to avoid `alloc` vs `std`
namespacing. I'm personally quite annoyed that we can't rely on `alloc`
as a crate name in `std` environments within macros. I'd love an
alternative to my approach here, but I suspect it's the least-bad
option.
- I would've liked to have an `alloc` feature (for allocation-free
`bevy_reflect`), unfortunately, `erased_serde` unconditionally requires
access to `Box`. Maybe one day we could design around this, but for now
it just means `bevy_reflect` requires `alloc`.

---------

Co-authored-by: Gino Valente <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following new features: 
  - `std` (default)
  - `alloc`
  - `encase` (default)
  - `libm`

## Testing

- Added to `compile-check-no-std` CI command

## Notes

- `ColorCurve` requires `alloc` due to how the underlying `EvenCore`
type works.
- `Srgba::to_hex` requires `alloc` to return a `String`.
- This was otherwise a _very_ simple change
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `async_executor` (default)
  - `edge_executor`
  - `critical-section`
  - `portable-atomic`
- Added [`edge-executor`](https://crates.io/crates/edge-executor) as a
`no_std` alternative to `async-executor`.
- Updated the `single_threaded_task_pool` to work in `no_std`
environments by gating its reliance on `thread_local`.

## Testing

- Added to `compile-check-no-std` CI command

## Notes

- In previous iterations of this PR, a custom `async-executor`
alternative was vendored in. This raised concerns around maintenance and
testing. In this iteration, an existing version of that same vendoring
is now used, but _only_ in `no_std` contexts. For existing `std`
contexts, the original `async-executor` is used.
- Due to the way statics work, certain `TaskPool` operations have added
restrictions around `Send`/`Sync` in `no_std`. This is because there
isn't a straightforward way to create a thread-local in `no_std`. If
these added constraints pose an issue we can revisit this at a later
date.
- If a user enables both the `async_executor` and `edge_executor`
features, we will default to using `async-executor`. Since enabling
`async_executor` requires `std`, we can safely assume we are in an `std`
context and use the original library.

---------

Co-authored-by: Mike <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `async_executor` (default)
  - `edge_executor`
  - `critical-section`
  - `portable-atomic`
- Gated `tracing` in `bevy_utils` to allow compilation on certain
platforms
- Switched from `tracing` to `log` for simple message logging within
`bevy_ecs`. Note that `tracing` supports capturing from `log` so this
should be an uncontroversial change.
- Fixed imports and added feature gates as required 
- Made `bevy_tasks` optional within `bevy_ecs`. Turns out it's only
needed for parallel operations which are already gated behind
`multi_threaded` anyway.

## Testing

- Added to `compile-check-no-std` CI command
- `cargo check -p bevy_ecs --no-default-features --features
edge_executor,critical-section,portable-atomic --target
thumbv6m-none-eabi`
- `cargo check -p bevy_ecs --no-default-features --features
edge_executor,critical-section`
- `cargo check -p bevy_ecs --no-default-features`

## Draft Release Notes

Bevy's core ECS now supports `no_std` platforms.

In prior versions of Bevy, it was not possible to work with embedded or
niche platforms due to our reliance on the standard library, `std`. This
has blocked a number of novel use-cases for Bevy, such as an embedded
database for IoT devices, or for creating games on retro consoles.

With this release, `bevy_ecs` no longer requires `std`. To use Bevy on a
`no_std` platform, you must disable default features and enable the new
`edge_executor` and `critical-section` features. You may also need to
enable `portable-atomic` and `critical-section` if your platform does
not natively support all atomic types and operations used by Bevy.

```toml
[dependencies]
bevy_ecs = { version = "0.16", default-features = false, features = [
  # Required for platforms with incomplete atomics (e.g., Raspberry Pi Pico)
  "portable-atomic",
  "critical-section",

  # Optional
  "bevy_reflect",
  "serialize",
  "bevy_debug_stepping",
  "edge_executor"
] }
```

Currently, this has been tested on bare-metal x86 and the Raspberry Pi
Pico. If you have trouble using `bevy_ecs` on a particular platform,
please reach out either through a GitHub issue or in the `no_std`
working group on the Bevy Discord server.

Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!

## Notes

- Creating PR in draft to ensure CI is passing before requesting
reviews.
- This implementation has no support for multithreading in `no_std`,
especially due to `NonSend` being unsound if allowed in multithreading.
The reason is we cannot check the `ThreadId` in `no_std`, so we have no
mechanism to at-runtime determine if access is sound.

---------

Co-authored-by: Alice Cecile <[email protected]>
Co-authored-by: Vic <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `bevy_tasks` (default)
  - `downcast ` (default)
  - `portable-atomic`
  - `critical-section`
- `downcast` and `bevy_tasks` are now optional dependencies for
`bevy_app`.

## Testing

- CI
- Personal UEFI and Raspberry Pi Pico demo applications compile and run
against this branch

## Draft Release Notes

Bevy's application framework now supports `no_std` platforms.

Following up on `bevy_ecs` gaining `no_std` support, `bevy_app` extends
the functionality available on these targets to include the powerful
`App` and `Plugin` abstractions. With this, library authors now have the
option of making their plugins `no_std` compatible, or even offering
plugins specifically to improve Bevy on certain embedded platforms!

To start making a `no_std` compatible plugin, simply disable default
features when including `bevy_app`:

```toml
[dependencies]
bevy_app = { version = "0.16", default-features = false }
```

We encourage library authors to do this anyway, as it can also help with
compile times and binary size on all platforms.

Keep an eye out for future `no_std` updates as we continue to improve
the parity between `std` and `no_std`. We look forward to seeing what
kinds of applications are now possible with Bevy!

## Notes

- `downcast-rs` is optional as it isn't compatible with
`portable-atomic`. I will investigate making a PR upstream to add
support for this functionality, as it should be very straightforward.
- In line with the `bevy_ecs` no-std-ification, I've added documentation
to all features, and grouped them as well.
- ~~Creating this PR in draft while CI runs and so I can polish before
review.~~

---------

Co-authored-by: Alice Cecile <[email protected]>
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)

## Testing

- CI

## Notes

- There was a minor issue with `bevy_reflect`'s `smallvec` feature
noticed in this PR which I have also resolved here. I can split this out
if desired, but I've left it here for now as it's a very small change
and I don't consider this PR itself to be very controversial.
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `smol_str` (default)
  - `portable-atomic`
  - `critical-section`
  - `libm`
- Fixed an existing issue where `bevy_reflect` wasn't properly feature
gated.

## Testing

- CI

## Notes

- There were some minor issues with `bevy_math` and `bevy_ecs` noticed
in this PR which I have also resolved here. I can split these out if
desired, but I've left them here for now as they're very small changes
and I don't consider this PR itself to be very controversial.
- `libm`, `portable-atomic`, and `critical-section` are shortcuts to
enable the relevant features in dependencies, making the usage of this
crate on atomically challenged platforms possible and simpler.
- `smol_str` is gated as it doesn't support atomically challenged
platforms (e.g., Raspberry Pi Pico). I have an issue and a
[PR](rust-analyzer/smol_str#91) to discuss this
upstream.
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `portable-atomic`
  - `critical-section`

## Testing

- CI

## Notes

- `portable-atomic`, and `critical-section` are shortcuts to enable the
relevant features in dependencies, making the usage of this crate on
atomically challenged platforms possible and simpler.
- This PR is blocked until bevyengine#17027 is merged (as it depends on fixes for
the `once!` macro). Once merged, the change-count for this PR should
reduce.
ecoskey pushed a commit to ecoskey/bevy that referenced this issue Jan 6, 2025
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `alloc` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `alloc` feature added to allow using this crate in `no_alloc`
environments.
- `bevy_reflect` was previously always enabled when `bevy-support` was
enabled, which isn't how most other crates handle reflection. I've
brought this in line with how most crates gate `bevy_reflect`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Cross-Cutting Impacts the entire engine C-Dependencies A change to the crates that Bevy depends on C-Feature A new feature, making something new possible C-Tracking-Issue An issue that collects information about a broad development initiative D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes O-Embedded Weird hardware and no_std platforms X-Contentious There are nontrivial implications that should be thought through
Projects
None yet
Development

No branches or pull requests

10 participants