uutils / uutils/coreutils

`uucore` and `env` do not build for `wasm32-wasip2` when used as a library / standalone

Open
#14,561 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

U - env
Dominant language
Rust
Stars
24.1k
Forks
2k
Avg merge
1d 5h
Merged PRs (30d)
365

Description

Since #12653 the workspace builds for wasm32-wasip2, and that is great I run most of the
common utilities inside a WebAssembly component today. But three things still break for anyone
who consumes the crates rather than building the whole workspace, and I would like to contribute
the fixes (PR to follow soon).

1. uucore with its fs feature does not compile on wasm32-wasip2 on its own.

$ cargo check --target wasm32-wasip2 -p uu_cat -p uu_cp -p uu_printf     # any subset of the workspace
error[E0277]: the trait bound `impl AsFd: rustix::fd::AsFd` is not satisfied      --> src/uucore/src/lib/features/fs.rs:65:38
error[E0277]: `?` couldn't convert the error to `std::io::Error`                 --> src/uucore/src/lib/features/fs.rs:65:43
error[E0277]: the trait bound `&Path: rustix::path::Arg` is not satisfied         --> src/uucore/src/lib/features/fs.rs:88:34
error[E0277]: the trait bound `&Path: rustix::path::Arg` is not satisfied         --> src/uucore/src/lib/features/fs.rs:90:35
error[E0277]: `?` couldn't convert the error to `std::io::Error`                 --> src/uucore/src/lib/features/fs.rs:92:25
error[E0277]: the trait bound `Stdin: rustix::fd::AsFd` is not satisfied          --> src/uucore/src/lib/features/fs.rs:922:45
error[E0277]: the trait bound `T: rustix::fd::AsFd` is not satisfied              --> src/uucore/src/lib/mods/io.rs:39:27
error[E0277]: the trait bound `std::io::Error: From<Errno>` is not satisfied      --> src/uucore/src/lib/mods/io.rs:39:46
error[E0277]: the trait bound `std::io::Error: From<Errno>` is not satisfied      --> src/uucore/src/lib/mods/io.rs:39:9
error[E0277]: the trait bound `T: rustix::fd::AsFd` is not satisfied              --> src/uucore/src/lib/mods/io.rs:49:28
error[E0277]: the trait bound `std::io::Error: From<Errno>` is not satisfied      --> src/uucore/src/lib/mods/io.rs:49:47
error[E0277]: the trait bound `std::io::Error: From<Errno>` is not satisfied      --> src/uucore/src/lib/mods/io.rs:49:9
error: could not compile `uucore` (lib) due to 12 previous errors

Why: the workspace declares rustix = { version = "1.1.4", default-features = false } and
uucore's features turn on rustix/fs, rustix/process, rustix/pipe — but never rustix/std.
rustix::fd::AsFd, rustix::path::Arg for &Path and From<Errno> for io::Error all live behind
rustix's std feature, so without it those impls do not exist and every call site fails to
type-check.

Why it passes on unix and not here: uucoreclapclap_builderterminal_size depends on
rustix with its default features, std among them, so feature unification switches std on
for the whole graph and uucore's own rustix/fs-only edge compiles anyway. On wasm32-wasip2
terminal_size is not in the graph, nothing else enables std, and the same code stops compiling.
So the gap only shows on this target, and only for a build that does not happen to include a
crate pulling rustix's defaults.

Note when reproducing: cargo check -p uucore alone succeeds, but not because std is on —
uucore's rustix dependency is optional = true and is activated only by fs, entries,
mode, pipes, process, checksum and uptime, so with none of them selected there is no
rustix-using code to compile. (The rustix that shows up in cargo tree there is tempfile's,
a dev-dependency, which the lib build never sees.) Use -p uucore --features fs, or any uu_*
crate as above.

2. env does not compile on wasm32-wasip2, and it has just been dropped from the wasm build
because of it.

Using the same flags the wasip2 CI job uses (CICD.yml:391), plus env:

$ cargo check --target wasm32-wasip2 --no-default-features --features feat_wasm,env -p coreutils
error[E0658]: use of unstable library feature `wasip2`
  --> src/uu/env/src/native_int_str.rs:19:14
   |
19 | use std::os::wasi::ffi::{OsStrExt, OsStringExt};
   |              ^^^^
error: could not compile `uu_env` (lib) due to 2 previous errors

uucore solved this same import in #12653 by gating std::os::wasi::ffi to target_env = "p1"
and using the stable encoded-bytes API on p2; env's native_int_str.rs predates that and still
has the unconditional import. I see that c9077c764 ("reconsider feat_{wasm,common_core,Tier1}
for wasi", yesterday) worked around it from the other side — feat_wasm became
["feat_common_core", "nproc"] and env moved out of feat_common_core into feat_Tier1, so
the wasip2 job no longer builds it. The fix below makes env compile on the target, and its last
commit puts env back into feat_common_core so the two wasm CI jobs cover it; with the patch,
the command above succeeds, as does plain --features feat_wasm on wasip1 and wasip2.

3. Embedding uucore where argv is empty aborts the component.

EXECUTION_PHRASE (lib.rs) does ARGV[0], and util_name() indexes ARGV[argv_index]. On a
CLI that is always fine. In a WebAssembly component — a library linked into a host program, or a
guest whose host supplies no command line — std::env::args_os() is empty, and the first
uucore::util_name() call panics, which on wasm is a trap that takes the whole instance down. We
hit this running cat/ls/… as in-process library calls from a shell compiled to a component.

What I would like: uucore (with fs) and every utility in feat_wasm plus env to build on
wasm32-wasip2 standalone, and uucore not to trap when there is no argv. All three fixes are
small and confined to this target — one feature flag on uucore's own optional rustix
dependency, one cfg-gated module in env, one cfg(target_os = "wasi") guard in uucore.
Native behaviour does not change. Happy to add a CI step that builds one uu_* crate with -p
on the target so (1) cannot regress.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/uucore/src/lib/features/fs.rs and src/uucore/src/lib/mods/io.rs, then inspect the optional rustix dependency features. Read src/uu/env/src/native_int_str.rs and the wasm feature definitions around CICD.yml:391, and inspect uucore's lib.rs for the argv indexing. Done means standalone wasm32-wasip2 builds cover uucore and env, and empty argv no longer traps; verify with the cargo checks shown in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
build-system, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.