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

Improve wasm compatiblity of cli demo #254

Merged
merged 2 commits into from
Feb 20, 2025
Merged

Conversation

HeroicKatora
Copy link
Contributor

@HeroicKatora HeroicKatora commented Feb 19, 2025

While the wasm32-unknown-unknown environment makes little sense for the cli due to
the absence of any file handling, there is a case for supporting wasm32
anyways. With the wasi system interface the underlying platform provides
all the IO required, making this a viable std target. In particular,
WebAssembly ensures a high degree of reproducibility (especially under
implementations that ensure canonical NaN handling).

As a demo, we can pack the compiled module into an HTML page and
polyfill the file data in Javascript such as bjorn3's wasi shim.

I've only locally verified against Rust's wasm32-wasip1 target but
forsee no reason for newer wasi preview versions to work any worse when
they are stabilized. To indicate compatibility with future versions it
would be helpful to ensure CI coverage for this target, if maintenance
effort allows it.

The main overheads of such compatibility in the core of fidget and its
rhai embedding appear with the wasm32 target architecture itself, not
the -wasi platform. This is already covered as a Tier 1 target. There
are some subtleties with libraries that the CLI may depend on in the
future. The common terminal API libraries that would be used for
interactive modes generally do not work with wasm targets, many depend
on UNIX-ly libc functionality etc. Again though, this would hold even
less true for wasm32-unknown-unknown where definitionally no system
interface can be defined at all.


As an example, consider the following HTML file (packed in a zip for Github compatibility). Opening it in the browser runs a WebAssembly instance of fidget on the gyroid sphere example to generate a render on your machine instead of packing that image file itself. Seems pretty neat to me 🙂. (On a web deployment you might of course fetch the binary dynamically but packing it for a self-contained file is also neat.

fidget-html.zip

Chrome/Chromium and Firefox should work effortlessly for viewing the render through the HTML file.


Note: the HTML file is actually a polyglot, it's also a tar archive. This archive is the root file system which WASI shim then emulates—each file data encoded base64—so you can inspect the rhai source code that was used by extracting the archive. Admittedly, part of the reason for creating this PR was to show that trick off 😁

While the wasm32-unknown-unknown environment makes little sense due to
the absence of any file handling, there is a case for supporting wasm32
anyways. With the wasi system interface the underlying platform provides
all the IO required, making this a viable `std` target. In particular,
WebAssembly ensures a high degree of reproducibility (especially under
implementations that ensure canonical NaN handling).

As a demo, we can pack the compiled module into an HTML page and
polyfill the file data in Javascript such as bjorn3's wasi shim.

I've only locally verified against Rust's `wasm32-wasip1` target but
forsee no reason for newer wasi preview versions to work any worse when
they are stabilized. To indicate compatibility with future versions it
would be helpful to ensure CI coverage for this target, if maintenance
effort allows it.

The main overheads of such compatibility in the core of `fidget` and its
rhai embedding appear with the `wasm32` target architecture itself, not
the `-wasi` platform. This is already covered as a Tier 1 target. There
are some subtleties with libraries that the CLI may depend on in the
future. The common terminal API libraries that would be used for
interactive modes generally do not work with `wasm` targets, many depend
on UNIX-ly libc functionality etc. Again though, this would hold even
less true for `wasm32-unknown-unknown` where definitionally no system
interface can be defined at all.
Removing those dependencies, and in particular the whole `regex` tree,
allows shaving off quite a bit of codegen significantly reducing the
compiled outputs size. That is valuable for any web targets and general
wasm embedding.

Comparison (with hakari and a size-optimized profile):

    # Otherwise this is pointless, gets those features from other demos
    cargo hakari disable
    export RUSTFLAGS="-C strip=symbols -C debuginfo=none"

    cargo install --target wasm32-wasip1 --root . --path ./fidget/demos/cli/ fidget-cli --no-default-features
    ls -sh bin/fidget-cli.wasm
    3,5M bin/fidget-cli.wasm

    cargo install --target wasm32-wasip1 --root . --path ./fidget/demos/cli/ fidget-cli --no-default-features --features=logger_full
    ls -sh bin/fidget-cli.wasm
    4,3M bin/fidget-cli.wasm
@mkeeter mkeeter merged commit d3eaf69 into mkeeter:main Feb 20, 2025
13 checks passed
@mkeeter
Copy link
Owner

mkeeter commented Feb 20, 2025

443


To indicate compatibility with future versions it would be helpful to ensure CI coverage for this target, if maintenance effort allows it.

Yup, I'd definitely support a follow-up PR that adds this to CI as well, to prevent it from regressing.

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.

2 participants