Lucky4Luuk commented on issue #1158:
Is this still being worked on? What are the current issues blocking no_std support?
alexcrichton added the wasmtime:platform-support label to Issue #1158.
alexcrichton commented on issue #1158:
I'm at least not personally aware of this being worked on, but no blocker other than "just needs some elbow grease". If you'd be up for it PRs would be most welcome!
marceline-cramer commented on issue #1158:
I made a pretty half-assed attempt at this but managed to dig up some useful info: a major blocker to getting this to work is getting several dependencies involved in
std::io::Write-ing to objects to work onno_std. Here's a non-exhaustive list (i've been doing this for hours and i am exhausted enough):
- the
leb128crate used bywasm-encoderhas a hard dependency onstd::io- the
termcolorcrate has a hard dependency onstd::ioindexmap/stdis enabled bywasmparser/stdis enabled bywasmprinter(which has no features that could be used to disable the dep feature)gimli/writehas a hard dependency onstd::ioobject/writehas a hard dependency onstd::ioAll of those issues come from the
wasmtime-environcrate with thecompilefeature, which as far as I can tell, is pretty necessary to the functioning ofwasmtime-cranelift. I don't know how necessary that is, but if it is absolutely crucial to havecompileworking, those crates need to be either factored out, guarded behindstd, or in the worst case, modified upstream to not usestd::io. Much bureaucracy ensues.The really obnoxious part about removing
std::iofrom those crates is that there is no equivalentioAPI incoreoralloc, making ergonomicno_stda great endeavor per project.Aside from
wasmtime-environ,wasmtime-codegen/unwindhas a similar breaking dependency ongimli/writefor itswritefeature, which usesstd::ioto write objects. Disabling theunwindfeature also causes a cascade of missing API items in thewasmtime-codegencrate ANDwasmtime-cranelift. Today, I did manage to getwasmtime-codegencompiling locally inno_stdbut because I hadn't gotten theunwindfeature to work I had to give up.
thread_localalso breaks inwasmtime-codegenbecause that'sstd-only. I managed to take care of that with nightly#[thread_local]for now but obviously that's not optimal. More research is needed.
OnceLockcan be replaced withonce_cell::OnceCelltrivially, although that uses the scary-soundingcritical-sectionfeature. More research is needed.My personal opinion is that the best way to keep
no_stdsupported in the future is to just makewasmtime-codegenno_std-only. It only seems to be defining complex types of its own without a whole lot of interop with standard library types or interfaces anyways, and it was surprisingly easy to root out all of thestd-specific code.stddoes provide hash maps, butrustc-hash,hashbrown, andahashare already in the dependency tree.I haven't tried to get
thiserrorworking yet but I will.I would really appreciate some guidance for what to work towards next. This is clearly going to take a LOT of work to get
wasmtime-craneliftworking onno_stdconsistently on all platforms but I'm pretty invested in it. Also, if I've made any mistakes in my probing (I'm a newcomer to the codebase), please let me know.
marceline-cramer edited a comment on issue #1158:
I made a pretty half-assed attempt at this but managed to dig up some useful info: a major blocker to getting this to work is getting several dependencies involved in
std::io::Write-ing to objects to work onno_std. Here's a non-exhaustive list (i've been doing this for hours and i am exhausted enough):
- the
leb128crate used bywasm-encoderhas a hard dependency onstd::io- the
termcolorcrate has a hard dependency onstd::ioindexmap/stdis enabled bywasmparser/stdis enabled bywasmprinter(which has no features that could be used to disable the dep feature)gimli/writehas a hard dependency onstd::ioobject/writehas a hard dependency onstd::ioAll of those issues come from the
wasmtime-environcrate with thecompilefeature, which as far as I can tell, is pretty necessary to the functioning ofwasmtime-cranelift. I don't know how necessary that is, but if it is absolutely crucial to havecompileworking, those crates need to be either factored out, guarded behindstd, or in the worst case, modified upstream to not usestd::io. Much bureaucracy ensues.The really obnoxious part about removing
std::iofrom those crates is that there is no equivalentioAPI incoreoralloc, making ergonomicno_stda great endeavor per project.Aside from
wasmtime-environ,wasmtime-codegen/unwindhas a similar breaking dependency ongimli/write, which usesstd::ioto write objects. Disabling theunwindfeature also causes a cascade of missing API items in thewasmtime-codegencrate ANDwasmtime-cranelift. Today, I did manage to getwasmtime-codegencompiling locally inno_stdbut because I hadn't gotten theunwindfeature to work I had to give up.
thread_localalso breaks inwasmtime-codegenbecause that'sstd-only. I managed to take care of that with nightly#[thread_local]for now but obviously that's not optimal. More research is needed.
OnceLockcan be replaced withonce_cell::OnceCelltrivially, although that uses the scary-soundingcritical-sectionfeature. More research is needed.My personal opinion is that the best way to keep
no_stdsupported in the future is to just makewasmtime-codegenno_std-only. It only seems to be defining complex types of its own without a whole lot of interop with standard library types or interfaces anyways, and it was surprisingly easy to root out all of thestd-specific code.stddoes provide hash maps, butrustc-hash,hashbrown, andahashare already in the dependency tree.I haven't tried to get
thiserrorworking yet but I will.I would really appreciate some guidance for what to work towards next. This is clearly going to take a LOT of work to get
wasmtime-craneliftworking onno_stdconsistently on all platforms but I'm pretty invested in it. Also, if I've made any mistakes in my probing (I'm a newcomer to the codebase), please let me know.
marceline-cramer edited a comment on issue #1158:
I made a pretty half-assed attempt at this but managed to dig up some useful info: a major blocker to getting this to work is getting several dependencies involved in
std::io::Write-ing to objects to work onno_std. Here's a non-exhaustive list (i've been doing this for hours and i am exhausted enough):
- the
leb128crate used bywasm-encoderhas a hard dependency onstd::io- the
termcolorcrate has a hard dependency onstd::ioindexmap/stdis enabled bywasmparser/stdis enabled bywasmprinter(which has no features that could be used to disable the dep feature)gimli/writehas a hard dependency onstd::ioobject/writehas a hard dependency onstd::ioAll of those issues come from the
wasmtime-environcrate with thecompilefeature, which as far as I can tell, is pretty necessary to the functioning ofwasmtime-cranelift. I don't know how necessary that is, but if it is absolutely crucial to havecompileworking, those crates need to be either factored out, guarded behindstd, or in the worst case, modified upstream to not usestd::io. Much bureaucracy ensues.The really obnoxious part about removing
std::iofrom those crates is that there is no equivalentioAPI incoreoralloc, making ergonomicno_stda great endeavor per project.Aside from
wasmtime-environ,wasmtime-codegen/unwindhas a similar breaking dependency ongimli/write, which usesstd::ioto write objects. Disabling theunwindfeature also causes a cascade of missing API items in thewasmtime-codegencrate ANDwasmtime-cranelift. Today, I did manage to getwasmtime-codegencompiling locally inno_stdbut because I hadn't gotten theunwindfeature to work I had to give up.
thread_localalso breaks inwasmtime-codegenbecause that'sstd-only. I managed to take care of that with nightly#[thread_local]for now but obviously that's not optimal. More research is needed.
OnceLockcan be replaced withonce_cell::OnceCelltrivially, although that uses the scary-soundingcritical-sectionfeature. More research is needed.I haven't tried to get
thiserrorworking yet but I will.I would really appreciate some guidance for what to work towards next. This is clearly going to take a LOT of work to get
wasmtime-craneliftworking onno_stdconsistently on all platforms but I'm pretty invested in it. Also, if I've made any mistakes in my probing (I'm a newcomer to the codebase), please let me know.
bjorn3 commented on issue #1158:
#[thread_local]is generally unavailable on no_std targets too.
alexcrichton commented on issue #1158:
My recommendation would be to first start off by gating "easy" things behind on-by-default Cargo features. For example
wasmprinterdoesn't need to be included in no_std builds (northread_localusage ortermcolor). Basically anything that's optional functionality can be hard-disabled at compile time and that can greatly help to prune the dependency tree of crates that don't support no_std.After that next bit that I would recommend is to do this incrementally. The main crate in question I believe is
cranelift-codegenbut there are other crates as well that it depends on. I'd recommend starting at the leaves (e.g.cranelift-entity) and adding a "ratchet" to add support forno_stdto ensure they don't regress. For example on CI you'd add lines around here where that ensures that crates build on a no_std target. Eventually as you work your way up tocranelift-codegenyou'll already have added support to a number of other crates and handled a number of these issues.At that point I think it might be worth reevaluating taking stock of what's remaining. I think it would be useful to classify dependencies as you've done, but with a refreshed list at that point. Some of these are going to be somewhat hard like
gimli/writeandobject/writebut we might be able to work with upstream to have new crate versions that support no_std needs, but that also sort of depends on what exactly Cranelift needs. That's why I'd recommend doing everything exceptcranelift-codegenfirst if possible so we can get the most precise picture of what Cranelift needs from its dependencies with no_std.
marceline-cramer commented on issue #1158:
I'm having a hard time with removing
thread_localusage fromcranelift/codegen/src/timing.rs. What alternative tothread_localstatics should I use withno_std, if any? As far as I can tell, thetimingmodule and those statics can't be configured out. One idea I have is to just configure out all thetimingusage with API-compatible no-op stub functions onno_std, but I don't know enough about the codebase to understand the consequences of something like that.
marceline-cramer edited a comment on issue #1158:
I'm having a hard time with removing
thread_localusage fromcranelift/codegen/src/timing.rs. What alternative tothread_localstatics should I use withno_std, if any? As far as I can tell, thetimingmodule and those statics can't be configured out. One idea I have is to just configure out all thetimingusage with API-compatible no-op stub functions onno_std, but I don't know enough about the codebase to understand the consequences of something like that.I should also point out that the
set_thread_profiler()function is not used anywhere in the codebase.
marceline-cramer commented on issue #1158:
For now, I just put no-op stubs in the
timingAPI when thetimingfeature is not enabled and made thetimingfeature enable thestdfeature automatically.thread_local! {}is still in use as long as thetimingfeature is enabled.Right now, my development approach is to hack on all of these intersecting API changes and changes to the dependency trees on a fork, which I have set up to be running the full CI PR test suite: https://github.com/marceline-cramer/wasmtime/pull/1 Once that branch on my fork is to a place I'm happy with and all the pieces fit together practically as a rough sketch, I can start decomposing it into finer-grained, more polished things to implement as upstream-facing PRs. I did implement the "ratcheting" approach to get down to
cranelift-codegenas quickly as I could and discovered all but one of its workspace dependencies already work fine inno_std. The one exception wascranelift-control, which to compile tono_stdI slapped in a Git dep for a pending PR onarbitrarywithno_stdsupport: https://github.com/rust-fuzz/arbitrary/pull/177I added a field to
CodegenOptionsincranelift-isleto emitno_std-compatible code by adding a short prelude to generated source files, because most CI compiles ISLE withstdbutcranelift-codegendoes not. If that's an acceptable change for upstream, I'd be happy to make a little PR to get that moving along.The reason I had gotten as far with
cranelift-codegenas to be hacking onthread_localis because getting it to compile to ano_stdtarget turned out to be pretty easy. I mainly just swapped out all of the uses ofrustc-hashwith a combination ofhashbrownandahashand replaced any lingering uses ofstdwithcoreandalloc. I also replaced any use of floating-point arithmetic in the instrinics code with thecore_mathcrate, which just implementsstd-compatible arithmetic operators oncorefloats usinglibm. There may be some security concerns with regards to the use ofahashin ano_stdenvironment but I have decided that taking a deeper look into that is Tomorrow Marceline's problem.The main kicker with
cranelift-codegenright now is that so far, I've only gottenall-archandtrace-logfeatures, with no others, to compile, and only in nightly. The reason it has to be in nightly for now is because there are some cases ofimpl std::error::Errorthat I'm too afraid tocfgout, so for now I'm using nightly andcore::error::Erroruntil I can figure out what to do with potentialno_stdAPI users ofcranelift-codegen. I figure that the already-discussed use ofthiserroronno_stdwould force us to use nightly for now anyways.That's about where I am now. The CI mostly passes, although Cranelift's unit tests fail with slightly different code output compared to the expected code. I can chalk that up to either an impatient use of
cargo updatethat may have minorly changed some semantics of dependencies involved in codegen, or something related to the switching ofrustc-hashtohashbrown. Both are easy to test.The main issue now is that, by default,
cranelift-codegenis configured to havestd,unwind,trace-logenabled.trace-logworks inno_stdindependently ofstd, butunwindis still blocked by that peskygimli/writedep and its use ofstd::io. I can take a deeper look into how exactly that is used and what an alternative to that either in Cranelift or upstream Gimli might look like when I have more time and can afford to lock in on specific issues like that. I'm becoming a lot more comfortable navigating the codebase but there's still a lot of cognitive overhead and even swapping out dependencies takes a lot of attention.
bjorn3 commented on issue #1158:
I should also point out that the set_thread_profiler() function is not used anywhere in the codebase.
It is used by cg_clif to include performance timings collected by Cranelift in rustc self profile profiles. Having thr timing module be a nop for no_std builds is fine.
bjorn3 commented on issue #1158:
I added a field to CodegenOptions in cranelift-isle to emit no_std-compatible code by adding a short prelude to generated source files
Unconditionally using core instead of std should work fine. In std builds, core is still available.
alexcrichton commented on issue #1158:
For now, I just put no-op stubs in the timing API when the timing feature is not enabled and made the timing feature enable the std feature automatically
Sounds good! I'd recommend gating
set_thread_profilerbehind this Cargo feature entirely (and having the feature enabled by default probably too). That would avoid the confusion of callingset_thread_profilerand having it do nothing.The one exception was cranelift-control, which to compile to no_std I slapped in a Git dep for a pending PR on arbitrary with no_std support: https://github.com/rust-fuzz/arbitrary/pull/177
I'd probably recommend adding a
fuzzfeature or similar to avoid needing to update thearbitrarycrate (although updating that is definitely ok too). Basically gating this functionality on a Cargo feature is fine. (this Cargo feature may even be able to be off-by-default too)I also replaced any use of floating-point arithmetic in the instrinics code with the core_math crate, which just implements std-compatible arithmetic operators on core floats using libm. There may be some security concerns with regards to the use of ahash in a no_std environment but I have decided that taking a deeper look into that is Tomorrow Marceline's problem.
This sounds generally fine and possible for us to land. When making PRs if you wouldn't mind leaving
cranelift-codegen's no_std support for a single standalone PR that'll make this easiest to review and discuss.The main kicker with cranelift-codegen right now is that so far, I've only gotten all-arch and trace-log features
FWIW I think it's definitely ok to not get the entire crate and all its features compiling with no_std. Only getting a subset working (albeit we still need a useful subset, but the one you have is useful) is more than ok. Can always work to improve the subset supported later on.
The reason it has to be in nightly for now is because there are some cases of impl std::error::Error
I'm assuming that you're probably going to add a
stdfeature to thecranelift-codegencrate no matter what, and would it be possible to gate these impls on thestdfeature? That is, "just" omit them for a no_std build?The main issue now is that, by default, cranelift-codegen is configured to have std,unwind,trace-log enabled
In the spirit of ratcheting and progress over time I'll reiterate it's completely ok to get only some features working and not others. In this workspace most dependencies disable default features and then individual crates will enable features in addition to specifying
workspace = true. That would enable a state wherecranelift-codegenitself builds with no_std butwasmtime-craneliftdoesn't work just yet. That'd help figure out all the dependencies as we go along and get to a working state at least for one crate while the blockers of the next crate are tackled.One example here is that the
unwindfeature is only used in Wasmtime forConfig::native_unwind_infowhich would be easy to gate behind a Cargo feature. In that sense there's no need to unconditionally enableunwindin Cranelift given possible future changes.If your target is
wasmtime-craneliftthe bigger problem is probably going to beobject::writeas that's pretty intrinsically depended on. It's probably best to cross that bridge when we get there though and it's the "only" remaining issue. If your target is justcranelift-codegenonno_stdthen you can disregard this last part from me :)
marceline-cramer commented on issue #1158:
I added a field to CodegenOptions in cranelift-isle to emit no_std-compatible code by adding a short prelude to generated source files
Unconditionally using core instead of std should work fine. In std builds, core is still available.
It would work fine if not for the
impl Length for Vecin the codegen. In no_std, that would have to be replaced with thealloccrate, and no_std or not, thealloccrate has to be manually declaredextern crate alloc;.
marceline-cramer commented on issue #1158:
Sounds good! I'd recommend gating
set_thread_profilerbehind this Cargo feature entirely (and having the feature enabled by default probably too). That would avoid the confusion of callingset_thread_profilerand having it do nothing.Sounds great, I'll remember that when I open the
cranelift-codegenno_stdPR.I'd probably recommend adding a
fuzzfeature or similar to avoid needing to update thearbitrarycrate (although updating that is definitely ok too). Basically gating this functionality on a Cargo feature is fine. (this Cargo feature may even be able to be off-by-default too)Not including the
arbitrarycrate breaksControlPlane::arbitrary()andControlPlane::get_arbitrary(), so I've made it on by default so that none of the dependencies need to manually enable it. We can discuss that more in thecranelift-controlPR I'm about to open. :)This sounds generally fine and possible for us to land. When making PRs if you wouldn't mind leaving
cranelift-codegen's no_std support for a single standalone PR that'll make this easiest to review and discuss.FWIW I think it's definitely ok to not get the entire crate and all its features compiling with no_std. Only getting a subset working (albeit we still need a useful subset, but the one you have is useful) is more than ok. Can always work to improve the subset supported later on.
I'm assuming that you're probably going to add a
stdfeature to thecranelift-codegencrate no matter what, and would it be possible to gate these impls on thestdfeature? That is, "just" omit them for a no_std build?Yeah, I suppose that is definitely the easiest way of going about it. I would definitely be glad to have just stripped-down
cranelift-codegenworking inno_stdupstream for now.One example here is that the
unwindfeature is only used in Wasmtime forConfig::native_unwind_infowhich would be easy to gate behind a Cargo feature. In that sense there's no need to unconditionally enableunwindin Cranelift given possible future changes.If your target is
wasmtime-craneliftthe bigger problem is probably going to beobject::writeas that's pretty intrinsically depended on. It's probably best to cross that bridge when we get there though and it's the "only" remaining issue. If your target is justcranelift-codegenonno_stdthen you can disregard this last part from me :)I was not aware that the dependency on
unwindwas so light, glad to hear! Yes, I am most interested in using the entirety of Wasmtime JIT functionality itself in ano_stdenvironment. Once I can get the lower-level features working though I'll see what I can get done with theobjectcrate and I'll come back here to make the rest of the push. :)
alexcrichton removed the wasmtime:platform-support label from Issue #1158.
Last updated: Dec 13 2025 at 19:03 UTC