ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何用 Bevy 编写兼容 no_std 嵌入式目标的库?

如何用 Bevy 编写兼容 no_std 嵌入式目标的库? 如何用 Bevy 编写兼容 no_std 嵌入式目标的库【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy如果你的库基于 Bevy 开发想让它能被运行在没有操作系统、无法链接std的嵌入式设备例如 Raspberry Pi Pico 这类没有线程和文件系统支持的设备使用需要把库改造成no_std兼容。Bevy 仓库自带一个完整的示范no_std 库示例 演示了一个no_std兼容的 Bevy 库 crate 如何编写以及 验证方法 说明了如何确认库真的没有依赖标准库。本文按该示例整理出一条完整路径声明 crate、编写兼容代码、暴露 Cargo feature、用无std的目标验证编译最后把检查固化到 CI。一个前提要先明确Bevy 本身重度依赖内存分配所以alloccrate需要全局分配器是硬性要求——没有它 Bevy 无法编译。你的no_std库可以摆脱std但不能摆脱alloc。在 lib.rs 中声明 no_std 并引入必要 crate在库的入口文件顶部添加以下声明摘自 示例 lib.rs// 1. 阻止自动链接 std并把所有模块的隐式 prelude 从 std::prelude 切换到 core::prelude #![no_std] // 2. 仅当 std feature 开启时条件性地重新引入 std。 // 它不会改变 prelude只是让 std 里的项可以被显式 import #[cfg(feature std)] extern crate std; // 3. Bevy 需要分配器因此 alloc 可以无条件引入。 // 这提供 Vec、String、Box 等分配原语 extern crate alloc;#![no_std]做两件事阻止std被自动链接进你的 crate以及把各模块隐式导入的 prelude 从std::prelude切到core::prelude。由于std本身就是对core项的再导出Option、Result、迭代器等std时代写的代码大多可以直接换成core路径例如// 用 core::time::Duration 替代 std::time::Duration // 两者是同一类型只是命名空间不同 use core::time::Duration;用 bevy::platform 替代 std 专有类型被std独占的类型HashMap、RwLock、Instant、原子类型等在bevy::platform中有对应的可移植实现。示例库中给出的对照导入如下use bevy::prelude::*; use bevy::platform::{ collections::{HashMap, HashSet}, hash::DefaultHasher, sync::{ atomic::{AtomicBool, AtomicUsize}, Arc, Barrier, LazyLock, Mutex, Once, OnceLock, RwLock, Weak, }, time::Instant, };原子类型需要特别注意不是所有no_std目标都完整支持原子操作所以Arc、AtomicBool等不一定可用。示例的建议是优先使用bevy::platform::sync而不是core::sync或alloc::syncBevy 会在必要时自动选择来自portable-atomic的回退实现无需你自己处理。确需手动判断时可以用#[cfg(target_has_atomic ptr)]等标志。库的公开 API 写法与普通 Bevy 库相同下面的延迟插入组件示例Plugin、Component、观察者、系统就是标准 Bevy 代码与no_std改造正交pub struct DelayedComponentPlugin; impl Plugin for DelayedComponentPlugin { fn build(self, app: mut App) { app.add_systems(Update, tick_timers); } }在 Cargo.toml 中暴露 feature 给下游库要同时服务std用户和no_std用户需要把关键 feature 透传给 Bevy。示例 Cargo.toml 的完整结构[package] name no_std_library version 0.1.0 edition 2024 # 正式发布的库使用 version x.y.z # 示例仓库内改用 path ../../../ 指向工作区根部的 bevy [dependencies.bevy] version x.y.z # std 是 Bevy 的默认 feature所以先关掉默认 feature default-features false # 只启用库实际需要的 Bevy feature。 # 注意某些 Bevy feature 依赖 stdno_std 目标下不能启用 features [ # bevy_color, # bevy_state, ] [features] # no_std 属于小众需求默认值照顾大多数 std 用户 default [std] # 使用 Rust 标准库 std [bevy/std] # 浮点函数改用 libm 实现 libm [bevy/libm] # 同步原语依赖 critical-section critical-section [bevy/critical-section] # 在 Web 环境下访问浏览器 API仅适用于 wasm32 架构 web [bevy/web] [lints.clippy] # 这些 lint 会在你本可用 core/alloc 却 import std 时发出警告。 # core 和 alloc 在任何有 std 的目标上都可用启用没有副作用 std_instead_of_core warn std_instead_of_alloc warn alloc_instead_of_core warn各 feature 在 Bevy 中的定义见根 Cargo.tomlstd允许使用stdcratelibm用libm数学库替代std/core提供的实现no_std下计算浮点函数需要它critical-section为同步原语提供跨平台含no_std的基础实现在原子支持弱或完全没有的平台上是必需的web访问浏览器 API目前仅适用于wasm32架构。Bevy 还提供了一个no_std应用的推荐 feature 集合根Cargo.toml中定义为default_no_std [libm, critical-section, bevy_color, bevy_state]可供应用侧参考。如果库直接依赖 bevy_platform而非经由 Bevy其std与alloc都是默认 feature使用no_std目标时同样要加default-features false该 README 指出critical-sectionfeature 用于原子支持很少或没有的平台。验证 no_std 兼容性编译到无 std 的目标只关闭stdfeature 并编译通过是不够的——即使顶层 crate 声明了#![no_std]依赖树里仍可能有 crate 带入了std。可靠的检查方式是直接编译到一个没有标准库的目标Tier 2 / Tier 3 目标通常拿不到std代码只有真正no_std兼容才能编译通过。文档推荐的三个检查目标及各自用途x86_64-unknown-none代表桌面架构与常见std目标最相似是移植现有库的起点wasm32v1-none功能最精简的 WebAssembly 目标类似于 Web 构建常用的wasm32-unknown-unknownthumbv6m-none-eabi代表嵌入式平台原子支持只有部分覆盖是暴露代码中原子不兼容问题的好探针。首次编译某个新目标前需要用rustup安装对应目标组件这一步会向本地 Rust 工具链添加组件rustup target add x86_64-unknown-none然后按目标检查库--no-default-features关掉库自己的std默认 feature--features libm,critical-section打开no_std所需路径cargo check --no-default-features --features libm,critical-section --target x86_64-unknown-none对另外两个目标把--target换成wasm32v1-none或thumbv6m-none-eabi即可。cargo check通过即说明库及其依赖链在该目标上可编译针对thumbv6m-none-eabi的编译尤其值得跑一遍因为它对原子操作的限制最接近真实嵌入式设备。把检查固化到 CI如果团队没有人在日常开发中实际使用no_std这类检查很容易被遗漏。示例 README 给出的 GitHub Action 对三个目标做了矩阵检查可以直接作为起点jobs: check-compiles-no-std: runs-on: ubuntu-latest strategy: fail-fast: false matrix: target: - x86_64-unknown-none - wasm32v1-none - thumbv6m-none-eabi steps: - uses: actions/checkoutv4 - name: Install toolchain env: RUST_TARGET: ${{ matrix.target }} run: | rustup toolchain install stable --no-self-update --profileminimal rustup target add ${{ env.RUST_TARGET }} --toolchain stable rustup override set stable cargo -V - name: Check Compile env: RUST_TARGET: ${{ matrix.target }} run: cargo check --no-default-features --features libm,critical-section --target ${{ env.RUST_TARGET }}限制与注意事项库启用的 Bevy feature 本身可能依赖std。示例 Cargo.toml 特意把bevy_color、bevy_state注释掉并注明 certain Bevy features rely onstd。启用新 feature 后必须重新跑一遍无std目标的cargo check确认没有引入隐性依赖。webfeature 仅适用于wasm32架构与纯嵌入式目标无关除非你的库要同时面向 Web否则不必暴露。alloc是绕不开的依赖no_std只是去掉stdBevy 没有全局分配器的目标下根本无法编译这一点在 no_std 示例总览 中有明确说明。三个检查目标通过并不保证某个具体设备可用——它们分别代表桌面、Wasm 和嵌入式三类约束最终设备仍应以自身的原子/分配器支持情况为准。完整可运行的参考实现见 examples/no_std/library包含std条件引入、alloc引入、bevy::platform替代类型以及一套标准的 Bevy 插件/组件/观察者写法。【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表