Skip to content

Enable no_std builds and expand platform abstractions across steel#557

Open
mparkachov wants to merge 34 commits into
mattwparas:masterfrom
mparkachov:mwp-no-std-feature
Open

Enable no_std builds and expand platform abstractions across steel#557
mparkachov wants to merge 34 commits into
mattwparas:masterfrom
mparkachov:mwp-no-std-feature

Conversation

@mparkachov

Copy link
Copy Markdown
Contributor

I put together changes which allow build of steel-core for no_std configuration as per #535. I assumed that alloc is still available. Tests were gated with std feature, so part of them now run in no_std build. I want to stress, that these tests still bring default test harness, which pulls std, so running tests are not 100% guarantee that they will work in pure no_std mode. This could be done with custom harness, but I didn't implemented it yet, wanted to get first feedback. There are a lot of changes, but I wanted to submit PR with green build for no_std. From functional perspective they could be summarised as following:

  • Make std opt-in across the core crates so the workspace builds with --no-default-features, including the new #![no_std] entry points and default feature adjustments in steel-core, steel-parser, and steel-gen (crates/steel-core/src/lib.rs (line 1), crates/steel-core/Cargo.toml (line 127), crates/steel-parser/src/lib.rs (line 1), crates/steel-gen/src/lib.rs (line 2)).
  • Add crate-local shims that replace std functionality when absent—covering collections, sync primitives, paths, OS strings, deterministic time, and randomness—to centralize environment differences (crates/steel-core/src/collections.rs (line 1), crates/steel-core/src/sync.rs (line 1), crates/steel-core/src/path.rs (line 1), crates/steel-core/src/os_strings.rs (line 1), crates/steel-core/src/time.rs (line 1), crates/steel-core/src/rand.rs (line 1)).
  • Refactor compiler, VM, and primitive modules to lean on those shims, tighten cfg(feature = "std") guards around I/O and OS integrations, and wire the new abstractions through the runtime (crates/steel-core/src/primitives/fs.rs (line 1), crates/steel-core/src/steel_vm/engine.rs (line 1), crates/steel-language-server/src/backend.rs (line 19)).
  • Expand optional dependency surface (e.g., hashbrown, getrandom) and align feature gating so std-only integrations are marked optional while sync now depends on std (crates/steel-core/Cargo.toml (line 40), crates/steel-core/Cargo.toml (line 129)).
  • Refresh CI workflows to modern actions and explicitly build/test the workspace under no-std, wasm32, sync, and redox targets, ensuring coverage also exercises the --no-default-features configuration (.github/workflows/rust.yml (line 20)).

Now cargo ... --no-default-features builds without std assumed. Following are green:

cargo test --all
cargo test --no-default-features
cargo build -p steel-core --target wasm32-unknown-unknown 
cargo build -p steel-core --target wasm32-unknown-unknown --no-default-features

There are some issue with nix job in actions, but the reason is that current stable version of rust and version of rust in nix are different and they report differently fmt issues. Seeing recent update on old rust, maybe project should set on particular version, or create several builds for different rust versions.

There is modules feature defined, but I could not figure out from implementation what it is supposed to do, but feels like something related.

@mattwparas

Copy link
Copy Markdown
Owner

👋 Thanks for putting in the time on this, this is a big change set, so apologies but it will take me a while to go through it.

Could you expand on your use case here? I'd just like to understand what your eventual goal is and make sure that moving forward steel can support that without a large maintenance burden (i.e. making sure that keeping steel no_std compliant doesn't become too difficult)

I'd like to have steel be no_std, so this is something I'd like to have 😄

@mparkachov

Copy link
Copy Markdown
Contributor Author

Thanks for taking the time to look at this. I realise this is a pretty large change set. My main goal was to explore what would be required to get Steel building without std.

I’m happy to split this into smaller PRs. There are a few natural separable steps. The first one could focus only on replacing std::… usage with core::… / alloc::… where possible. This should cover most of the surface-level changes without any functional impact.

To reduce maintenance burden in the future, I think adding CI + real tests for the no_std configuration would help quite a lot. I can’t commit to maintaining no_std support long-term, but for now my goals are:

  1. Build + test Steel for WASM in no_std mode.
  2. Build a small firmware for ESP32 (similar to MicroPython), providing a REPL interface. This obviously requires more than just no_std support, but it’s a necessary first step.

Let me know if that approach (splitting into smaller PRs, starting with core/alloc replacements) works for you! I’m happy to iterate.

@gold-silver-copper

gold-silver-copper commented Nov 19, 2025

Copy link
Copy Markdown
Contributor

I was researching no_std steel / lisps in rust today. Nothing serious, but was thinking itd be fun to make like a portable cyberdeck lisp machine built with rust and some embedded hardware... That's all.

Something like one of these: http://www.ulisp.com/show?4JAO , there's more in the sidebar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants