Skip to content

wasip2: build uucore and env standalone, don't trap on empty argv - #14562

Open
Aditya1404Sal wants to merge 4 commits into
uutils:mainfrom
Aditya1404Sal:wasip2-fixes
Open

Aditya1404Sal wants to merge 4 commits into
uutils:mainfrom
Aditya1404Sal:wasip2-fixes

Conversation

@Aditya1404Sal

@Aditya1404Sal Aditya1404Sal commented Sep 14, 2026

Copy link
Copy Markdown

fixes #14561

Four commits

  1. uucore: enable rustix/std so its fs and io modules compile on wasm32-wasip2
    One line in src/uucore/Cargo.toml: the optional rustix dependency gains
    features = ["std"]. std is a rustix default feature the graph already ends up with on unix
    via clapclap_builderterminal_size, which depends on rustix with its defaults;
    terminal_size is absent on wasm32-wasip2, so nothing enables it there and the std-backed
    API those modules use (AsFd, Arg for &Path, From<Errno> for io::Error) is not compiled.
    The requirement is put on the dependency rather than repeated across the seven features that
    activate it (fs, entries, mode, pipes, process, checksum, uptime), all of which
    use that API. Deliberately scoped to uucore: setting features = ["std"] on the workspace
    rustix works too, but changes rustix for every member. The narrow version is enough for the
    whole wasm build — including uu_tee, the one other crate whose own rustix dependency is
    live on target_os = "wasi", which picks up std through uucore in any build that contains
    both (and every uu_* crate depends on uucore).

  2. env: build on wasm32-wasip2 without the unstable std::os::wasi::ffi (encoded-bytes conversions)
    native_int_str.rs keeps the std::os::wasi::ffi import for target_env = "p1" and gains a
    small wasip2_ffi module for p2: as_bytesas_encoded_bytes, into_vec
    into_encoded_bytes, and from_vec through String::from_utf8 (lossy only for bytes that
    cannot have come from the host — the component model defines strings as UTF-8). No unsafe,
    matching the module's stated rule and the approach uucore::os_str_from_bytes /
    os_string_from_vec already take on this target. One consequence: from_native_int_representation
    returns an owned OsStr on p2 where it could borrow before, because bytes → OsStr has to go
    through str.

  3. env: return to feat_common_core now that it builds on wasm32-wasip1 and wasip2
    Reverts the env half of c9077c764: env goes back into feat_common_core (so back into
    feat_wasm, which is now ["feat_common_core", "nproc"]) and out of feat_Tier1, where it had
    been moved to keep it out of the wasm build. This is what gives commit 2 CI coverage — the
    existing wasip1 and wasip2 jobs both build feat_wasm, so a regression in the env conversions
    fails the build rather than going unnoticed. The other four utilities that commit moved out stay
    where they are: df, du and more genuinely do not compile for wasip2, and tac does but
    nothing in this PR changed it, so restoring it is your call, not mine. Drop this commit if you
    would rather keep env out of the wasm set for reasons beyond the build failure.

  4. uucore: don't index an empty argv on wasip2 (guests embedded as libraries have none)
    On target_os = "wasi", ARGV is initialised with a single fallback element when
    std::env::args_os() is empty, so UTIL_NAME/EXECUTION_PHRASE resolve to a stable name
    instead of panicking. Other targets are unchanged. If you prefer this unconditional (a library
    consumer on any OS can have an empty argv), it is a one-line cfg change — I kept it to wasi to
    match where it was observed.

Testing

  • cargo check --target wasm32-wasip2 --no-default-features --features feat_wasm,env -p coreutils
    — the wasip2 CI job's own flags plus env: E0658 on main, clean with the patch. With commit
    3 the same holds for plain --features feat_wasm (no explicit env) on both wasm32-wasip1
    and wasm32-wasip2, which is what the two CI jobs run; --features feat_os_unix still builds
    natively.
  • cargo check --target wasm32-wasip2 -p uucore -p uu_cat -p uu_ls -p uu_wc -p uu_head -p uu_sort -p uu_mkdir -p uu_rm -p uu_mv -p uu_cp -p uu_env -p uu_cut -p uu_tr -p uu_uniq -p uu_tail -p uu_tee -p uu_touch -p uu_sleep -p uu_printf — clean (12 errors → 0; env builds).
  • cargo clippy -p uu_env --all-targets -- -D warnings, native and --target wasm32-wasip2 — clean;
    cargo fmt --check clean; cargo test -p uucore --lib passes.
  • Under wasmtime 46 on the target, the built env.wasm behaves: wasmtime --env X=1 env.wasm
    prints X=1, and env -u X drops it.
  • The equivalent of (4) has been running for two months inside a shell component that calls
    eighteen uu_* crates as library functions.

@Aditya1404Sal
Aditya1404Sal marked this pull request as ready for review September 14, 2026 19:20
Copilot AI lite review requested due to automatic review settings September 14, 2026 19:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Add WASI Preview 2 coverage and regression tests for the new conversion and empty-argv paths.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Enables standalone wasm32-wasip2 builds for uucore and env, while preventing empty-WASI-argv traps.

Changes:

  • Enables rustix/std for uucore.
  • Adds WASI Preview 2 encoded-byte conversions for env.
  • Restores env to common/WASI features and adds an empty-argv fallback.
File summaries
File Description
src/uucore/src/lib/lib.rs Prevents empty-argv indexing on WASI.
src/uucore/Cargo.toml Enables required rustix standard-library APIs.
src/uu/env/src/native_int_str.rs Adds WASI Preview 2 string conversions.
Cargo.toml Includes env in common/WASI features.
Review details

Suppressed comments (1)

Cargo.toml:140

  • This move does not provide the wasip2 CI coverage claimed in the PR description: .github/workflows/wasi.yml gates the feat_wasm build to wasip1 and excludes env from the wasip2 package-test list. Add a wasip2 compile/test step or correct the description before relying on this feature move for regression protection.
  "env",
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +31 to +32
#[cfg(all(target_os = "wasi", not(target_env = "p1")))]
mod wasip2_ffi {
Comment thread src/uucore/src/lib/lib.rs
Comment on lines +377 to +381
#[cfg(all(not(windows), target_os = "wasi"))]
static ARGV: LazyLock<Vec<OsString>> = LazyLock::new(|| {
let argv: Vec<OsString> = std::env::args_os().collect();
if argv.is_empty() {
vec![OsString::from("uu")]
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.

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

2 participants