Skip to content

Emit the emscripten entry point as __main_argc_argv#158937

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
guybedford:emscripten-pthread-main
Jul 9, 2026
Merged

Emit the emscripten entry point as __main_argc_argv#158937
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
guybedford:emscripten-pthread-main

Conversation

@guybedford

@guybedford guybedford commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Fixes support for building wasm32-unknown-emscripten under the -sPROXY_TO_PTHREAD linking option.

The wasm32-unknown-emscripten target uses the argc/argv form of main but emitted the entry point under the raw name main. That links on the default entry path (emscripten calls it via callMain), but fails on entry paths that reference the mangled symbol directly from wasm. In particular -sPROXY_TO_PTHREAD links crt1_proxy_main.o, whose call chain bottoms out at __main_argc_argv, so linking a Rust binary fails with:

    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main

This sets entry_name = "__main_argc_argv" so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays _main, since emscripten bridges _main to the wasm __main_argc_argv export internally (whereas it wouldn't for ___main_argc_argv).

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
@rustbot

rustbot commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

These commits modify compiler targets.
(See the Target Tier Policy.)

@rustbot rustbot added A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 8, 2026
@rustbot

rustbot commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

r? @jieyouxu

rustbot has assigned @jieyouxu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 75 candidates
  • Random selection from 19 candidates

Comment thread compiler/rustc_codegen_ssa/src/back/linker.rs Outdated
@jieyouxu

jieyouxu commented Jul 8, 2026

Copy link
Copy Markdown
Member

Maybe r? @bjorn3 (since you are already looking at it and actually know stuff about wasm)

@rustbot rustbot assigned bjorn3 and unassigned jieyouxu Jul 8, 2026

@bjorn3 bjorn3 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Makes sense. Code changes LGTM. And I will trust your judgement as someone with write permissions to Emscripten that this is a change that should be done.

r=me with or without the comment changed.

View changes since this review

@bjorn3

bjorn3 commented Jul 8, 2026

Copy link
Copy Markdown
Member

@bors r+

@rust-bors

rust-bors Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 15f9829 has been approved by bjorn3

It is now in the queue for this repository.

🌲 The tree is currently closed for pull requests below priority 10. This pull request will be tested once the tree is reopened.

Reason for tree closure: spurious failures

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 8, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 8, 2026
…, r=bjorn3

Emit the emscripten entry point as `__main_argc_argv`

Fixes support for building `wasm32-unknown-emscripten` under the `-sPROXY_TO_PTHREAD` linking option.

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 8, 2026
…, r=bjorn3

Emit the emscripten entry point as `__main_argc_argv`

Fixes support for building `wasm32-unknown-emscripten` under the `-sPROXY_TO_PTHREAD` linking option.

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 8, 2026
…, r=bjorn3

Emit the emscripten entry point as `__main_argc_argv`

Fixes support for building `wasm32-unknown-emscripten` under the `-sPROXY_TO_PTHREAD` linking option.

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
rust-bors Bot pushed a commit that referenced this pull request Jul 8, 2026
…uwer

Rollup of 25 pull requests

Successful merges:

 - #158871 (add relnotes for 1.97.0)
 - #158968 (stdarch subtree update)
 - #154445 (rustdoc: Represent `--output-format=json` coverage and ir differently)
 - #156370 (Reject linked dylib EII default overrides)
 - #157153 (allow `Allocator`s to be used as `#[global_allocator]`s)
 - #158495 (Rename HAS_CT_PROJECTION to HAS_CONST_ALIAS)
 - #158617 (allow mGCA const arguments to fall back to anon consts)
 - #158645 (Fix splat ICEs and ban it in closures)
 - #158655 (Fix coroutine MIR saved local remapping)
 - #158666 (Carry the `b_offset` inside `BackendRepr::ScalarPair`)
 - #158912 (Introduce new bootstrap config section for PGO configuration)
 - #158920 (Update wasm-component-ld to 0.5.26)
 - #158926 (wrapping_sh* methods: clarify underspecified reference)
 - #158927 (add core test run with `-Zforce-intrinsic-fallback`)
 - #158932 (Do not build the compiler when invoking `x perf compare`)
 - #158937 (Emit the emscripten entry point as `__main_argc_argv`)
 - #151379 (Stabilize `VecDeque::retain_back` from `truncate_front`)
 - #156548 ( Library support for aarch64-unknown-linux-pauthtest target)
 - #158307 (CI job for parallel frontend ui tests)
 - #158347 (Improve generic parameters handling for #[diagnostic::on_const])
 - #158722 (delegation: do not always inherit `ConstArgHasType` predicates)
 - #158741 (Simplify `Option::into_flat_iter` signature)
 - #158807 (Add regression test for CString::clone_into unwind safety)
 - #158862 (Fix the span for parameter suggestion )
 - #158883 (tests: fix enum-match.rs to handle LLVM 23)
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 8, 2026
…, r=bjorn3

Emit the emscripten entry point as `__main_argc_argv`

Fixes support for building `wasm32-unknown-emscripten` under the `-sPROXY_TO_PTHREAD` linking option.

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
rust-bors Bot pushed a commit that referenced this pull request Jul 8, 2026
Rollup of 25 pull requests

Successful merges:

 - #158871 (add relnotes for 1.97.0)
 - #158968 (stdarch subtree update)
 - #157690 (codegen_ssa: pack small const aggregates into immediate stores)
 - #158541 (Move `std::io::Write` to `core::io`)
 - #154445 (rustdoc: Represent `--output-format=json` coverage and ir differently)
 - #156370 (Reject linked dylib EII default overrides)
 - #157153 (allow `Allocator`s to be used as `#[global_allocator]`s)
 - #158495 (Rename HAS_CT_PROJECTION to HAS_CONST_ALIAS)
 - #158617 (allow mGCA const arguments to fall back to anon consts)
 - #158645 (Fix splat ICEs and ban it in closures)
 - #158655 (Fix coroutine MIR saved local remapping)
 - #158666 (Carry the `b_offset` inside `BackendRepr::ScalarPair`)
 - #158870 (std: merge the unix-like io::error modules into one file)
 - #158920 (Update wasm-component-ld to 0.5.26)
 - #158926 (wrapping_sh* methods: clarify underspecified reference)
 - #158927 (add core test run with `-Zforce-intrinsic-fallback`)
 - #158932 (Do not build the compiler when invoking `x perf compare`)
 - #158937 (Emit the emscripten entry point as `__main_argc_argv`)
 - #151379 (Stabilize `VecDeque::retain_back` from `truncate_front`)
 - #156144 (Better docs for PartialEq (includes macro rename))
 - #156548 ( Library support for aarch64-unknown-linux-pauthtest target)
 - #158307 (CI job for parallel frontend ui tests)
 - #158347 (Improve generic parameters handling for #[diagnostic::on_const])
 - #158722 (delegation: do not always inherit `ConstArgHasType` predicates)
 - #158741 (Simplify `Option::into_flat_iter` signature)
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 9, 2026
…, r=bjorn3

Emit the emscripten entry point as `__main_argc_argv`

Fixes support for building `wasm32-unknown-emscripten` under the `-sPROXY_TO_PTHREAD` linking option.

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
rust-bors Bot pushed a commit that referenced this pull request Jul 9, 2026
Rollup of 23 pull requests

Successful merges:

 - #158968 (stdarch subtree update)
 - #154445 (rustdoc: Represent `--output-format=json` coverage and ir differently)
 - #158495 (Rename HAS_CT_PROJECTION to HAS_CONST_ALIAS)
 - #158666 (Carry the `b_offset` inside `BackendRepr::ScalarPair`)
 - #158870 (std: merge the unix-like io::error modules into one file)
 - #158920 (Update wasm-component-ld to 0.5.26)
 - #158926 (wrapping_sh* methods: clarify underspecified reference)
 - #158927 (add core test run with `-Zforce-intrinsic-fallback`)
 - #158932 (Do not build the compiler when invoking `x perf compare`)
 - #158937 (Emit the emscripten entry point as `__main_argc_argv`)
 - #151379 (Stabilize `VecDeque::retain_back` from `truncate_front`)
 - #156144 (Better docs for PartialEq (includes macro rename))
 - #156548 ( Library support for aarch64-unknown-linux-pauthtest target)
 - #157995 (`Vec::dedup_by` docs explicit function argument order)
 - #158307 (CI job for parallel frontend ui tests)
 - #158741 (Simplify `Option::into_flat_iter` signature)
 - #158807 (Add regression test for CString::clone_into unwind safety)
 - #158862 (Fix the span for parameter suggestion )
 - #158894 (Make the ordering of non-terminal binds in ambiguity error messages deterministic)
 - #158902 (add codegen test for range length bound propagation)
 - #158913 (Update `browser-ui-test` version to `0.24.1`)
 - #158935 (std: support real fd methods on Emscripten)
 - #158978 (Add regression test for too-big by-value ABI args)
@rust-bors rust-bors Bot merged commit c706c84 into rust-lang:main Jul 9, 2026
13 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Jul 9, 2026
rust-timer added a commit that referenced this pull request Jul 9, 2026
Rollup merge of #158937 - guybedford:emscripten-pthread-main, r=bjorn3

Emit the emscripten entry point as `__main_argc_argv`

Fixes support for building `wasm32-unknown-emscripten` under the `-sPROXY_TO_PTHREAD` linking option.

The `wasm32-unknown-emscripten` target uses the argc/argv form of main but emitted the entry point under the raw name `main`. That links on the default entry path (emscripten calls it via `callMain`), but fails on entry paths that reference the mangled symbol directly from wasm. In particular `-sPROXY_TO_PTHREAD` links `crt1_proxy_main.o`, whose call chain bottoms out at `__main_argc_argv`, so linking a Rust binary fails with:

```
    wasm-ld: error: crt1_proxy_main.o: undefined symbol: main
```

This sets `entry_name = "__main_argc_argv"` so the entry point is emitted under the C-ABI name emscripten's crt/libc expects, and then works in both cases.

The JS-visible name of the entry point stays `_main`, since emscripten bridges `_main` to the wasm `__main_argc_argv` export internally (whereas it wouldn't for `___main_argc_argv`).
@guybedford guybedford deleted the emscripten-pthread-main branch July 9, 2026 21:47
guybedford added a commit to guybedford/nix that referenced this pull request Jul 10, 2026
Adds wasm32-unknown-emscripten as a target for nix, plus a temporary harness
to run the full test suite under Node.

Source changes to compile on emscripten (which behaves like a Linux/musl libc):

* ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten
  (src/sys/ioctl, src/sys/mod.rs).
* resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit.
* socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed)
  decode arms.
* unistd: sethostname is unavailable on emscripten, so gate it out.

Test harness (temporary, documented in .cargo/config.toml):

* em-proxy.json is a wasm32-unknown-emscripten spec with entry-name overridden
  to __main_argc_argv, reproducing rust-lang/rust#158937 without a patched
  toolchain.
* JSPI + pthread-proxy build (-sPROXY_TO_PTHREAD -sJSPI) with NODERAWFS/
  NODERAWSOCKETS, -Zbuild-std, and a local libc patch (Cargo.toml) carrying the
  emscripten externs.
* Requires nightly + rust-src, emcc on PATH, and a JSPI-capable Node (26+).

Genuinely-unsupported operations are gated with
#[cfg_attr(target_os = "emscripten", ignore = "...")] rather than cfg'd out,
covering fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock,
if_nametoindex, pipe2, AF_UNIX SCM_RIGHTS/datagram, and thread signal swap.

Suite result: 146 passed, 34 ignored, and 4 failing only as host artifacts
(chown/fchown/fchownat need root; linkat_no_follow_symlink differs on macOS) -
all green on Linux CI.
pull Bot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Jul 10, 2026
Rollup of 23 pull requests

Successful merges:

 - rust-lang/rust#158968 (stdarch subtree update)
 - rust-lang/rust#154445 (rustdoc: Represent `--output-format=json` coverage and ir differently)
 - rust-lang/rust#158495 (Rename HAS_CT_PROJECTION to HAS_CONST_ALIAS)
 - rust-lang/rust#158666 (Carry the `b_offset` inside `BackendRepr::ScalarPair`)
 - rust-lang/rust#158870 (std: merge the unix-like io::error modules into one file)
 - rust-lang/rust#158920 (Update wasm-component-ld to 0.5.26)
 - rust-lang/rust#158926 (wrapping_sh* methods: clarify underspecified reference)
 - rust-lang/rust#158927 (add core test run with `-Zforce-intrinsic-fallback`)
 - rust-lang/rust#158932 (Do not build the compiler when invoking `x perf compare`)
 - rust-lang/rust#158937 (Emit the emscripten entry point as `__main_argc_argv`)
 - rust-lang/rust#151379 (Stabilize `VecDeque::retain_back` from `truncate_front`)
 - rust-lang/rust#156144 (Better docs for PartialEq (includes macro rename))
 - rust-lang/rust#156548 ( Library support for aarch64-unknown-linux-pauthtest target)
 - rust-lang/rust#157995 (`Vec::dedup_by` docs explicit function argument order)
 - rust-lang/rust#158307 (CI job for parallel frontend ui tests)
 - rust-lang/rust#158741 (Simplify `Option::into_flat_iter` signature)
 - rust-lang/rust#158807 (Add regression test for CString::clone_into unwind safety)
 - rust-lang/rust#158862 (Fix the span for parameter suggestion )
 - rust-lang/rust#158894 (Make the ordering of non-terminal binds in ambiguity error messages deterministic)
 - rust-lang/rust#158902 (add codegen test for range length bound propagation)
 - rust-lang/rust#158913 (Update `browser-ui-test` version to `0.24.1`)
 - rust-lang/rust#158935 (std: support real fd methods on Emscripten)
 - rust-lang/rust#158978 (Add regression test for too-big by-value ABI args)
guybedford added a commit to guybedford/nix that referenced this pull request Jul 11, 2026
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the
full test suite under Node.

Source changes to compile on emscripten (which behaves like a Linux/musl libc):

* ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten
  (src/sys/ioctl, src/sys/mod.rs).
* resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit.
* socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed)
  decode arms.
* unistd: sethostname is unavailable on emscripten, so gate it out.

The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).

Genuinely-unsupported operations are ignored with
#[cfg_attr(target_os = "emscripten", ignore)] rather than cfg'd out, covering
fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex,
pipe2 FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, thread signal masking, and
setrlimit; a few tests are cfg'd out where the feature is entirely absent
(raw signal actions, socketpair) or the host differs (linkat symlink follow).

Temporary, until the dependencies land upstream:

* Cargo.toml patches libc to guybedford/libc#libc-0.2-emscripten for the
  emscripten externs (rust-lang/libc#5270).
* the CI job builds against the guybedford/emscripten `cf` fork, which carries
  the NODEFS/socket/blocking patches this target depends on
  (emscripten-core/emscripten#27305, #27306).

Suite result: 148 passed, 0 failed, 35 ignored under Node - green on Linux CI.
guybedford added a commit to guybedford/nix that referenced this pull request Jul 11, 2026
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the
full test suite under Node.

Source changes to compile on emscripten (which behaves like a Linux/musl libc):

* ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten
  (src/sys/ioctl, src/sys/mod.rs).
* resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit.
* socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed)
  decode arms.
* unistd: sethostname is unavailable on emscripten, so gate it out.

The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).

Genuinely-unsupported operations are ignored with
#[cfg_attr(target_os = "emscripten", ignore)] rather than cfg'd out, covering
fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex,
pipe2 FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, thread signal masking, and
setrlimit; a few tests are cfg'd out where the feature is entirely absent
(raw signal actions, socketpair) or the host differs (linkat symlink follow).

Temporary, until the dependencies land upstream:

* Cargo.toml patches libc to guybedford/libc#libc-0.2-emscripten for the
  emscripten externs (rust-lang/libc#5270).
* the CI job builds against the guybedford/emscripten `cf` fork, which carries
  the NODEFS/socket/blocking patches this target depends on
  (emscripten-core/emscripten#27305, #27306).

Suite result: 148 passed, 0 failed, 35 ignored under Node - green on Linux CI.
guybedford added a commit to guybedford/nix that referenced this pull request Jul 11, 2026
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the
full test suite under Node.

Source changes to compile on emscripten (which behaves like a Linux/musl libc):

* ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten
  (src/sys/ioctl, src/sys/mod.rs).
* resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit.
* socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed)
  decode arms.
* unistd: sethostname is unavailable on emscripten, so gate it out.

The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).

Genuinely-unsupported operations are ignored with
#[cfg_attr(target_os = "emscripten", ignore)] rather than cfg'd out, covering
fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex,
pipe2 FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, thread signal masking, and
setrlimit; a few tests are cfg'd out where the feature is entirely absent
(raw signal actions, socketpair) or the host differs (linkat symlink follow).

Temporary, until the dependencies land upstream:

* Cargo.toml patches libc to guybedford/libc#libc-0.2-emscripten for the
  emscripten externs (rust-lang/libc#5270).
* the CI job builds against the guybedford/emscripten `cf` fork, which carries
  the NODEFS/socket/blocking patches this target depends on
  (emscripten-core/emscripten#27305, #27306).

Suite result: 148 passed, 0 failed, 35 ignored under Node - green on Linux CI.
guybedford added a commit to guybedford/nix that referenced this pull request Jul 11, 2026
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the
full test suite under Node.

Source changes to compile on emscripten (which behaves like a Linux/musl libc):

* ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten
  (src/sys/ioctl, src/sys/mod.rs).
* resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit.
* socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed)
  decode arms.
* unistd: sethostname is unavailable on emscripten, so gate it out.

The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).

Genuinely-unsupported operations are ignored with
fork/wait, pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex,
pipe2 FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, thread signal masking, and
setrlimit; a few tests are cfg'd out where the feature is entirely absent
(raw signal actions, socketpair) or the host differs (linkat symlink follow).

Temporary, until the dependencies land upstream:

* Cargo.toml patches libc to guybedford/libc#libc-0.2-emscripten for the
  emscripten externs (rust-lang/libc#5270).
* the CI job builds against the guybedford/emscripten `cf` fork, which carries
  the NODEFS/socket/blocking patches this target depends on
  (emscripten-core/emscripten#27305, #27306).

Suite result: 148 passed, 0 failed, 35 ignored under Node - green on Linux CI.
guybedford added a commit to guybedford/nix that referenced this pull request Jul 11, 2026
Adds wasm32-unknown-emscripten as a target for nix, plus a CI job that runs the
full test suite under Node.

Source changes to compile on emscripten (which behaves like a Linux/musl libc):

* ioctl: use the Linux ioctl module and a c_int ioctl_num_type on emscripten
  (src/sys/ioctl, src/sys/mod.rs).
* resource: enable getrlimit/setrlimit and the Resource enum via libc::rlimit.
* socket: include emscripten in the SockaddrStorage AF_UNIX (pathname/unnamed)
  decode arms.
* unistd: sethostname is unavailable on emscripten, so gate it out.

The suite spawns OS threads (signal and socket-peer tests), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).

Unsupported operations are ignored with #[cfg_attr(target_os = "emscripten",
ignore)] rather than cfg'd out wherever they still compile, covering fork/wait,
pty/termios, mkfifo, getpwnam/setgroups/acct, flock, if_nametoindex, pipe2
FD_CLOEXEC, AF_UNIX SCM_RIGHTS/datagram, getsockname, socketpair, setrlimit, and
the linkat symlink-follow host check. The signal-delivery tests (signal, killpg,
thread mask) and the AF_ROUTE test are cfg'd out instead: compiling their
extern "C" handlers in perturbs the wasm indirect function table and aborts the
runtime.

Temporary, until the dependencies land upstream:

* the emscripten CI job injects a libc patch (guybedford/libc#libc-0.2-emscripten,
  rust-lang/libc#5270) via `cargo --config`, so other targets and CI jobs are
  unaffected.
* it also builds against the guybedford/emscripten `cf` fork, which carries the
  NODEFS/socket/blocking patches this target depends on
  (emscripten-core/emscripten#27305, #27306).

Suite result: 148 passed, 0 failed, 38 ignored under Node - green on Linux CI.
guybedford added a commit to guybedford/mio that referenced this pull request Jul 11, 2026
Adds `wasm32-unknown-emscripten` as a target for mio, plus a CI job that runs
the suite under Node. Resolves tokio-rs#642.

Emscripten exposes a real epoll backed by its runtime event loop, so the
existing Linux epoll selector is reused rather than adding a new backend. The
wasm `compile_error!` guard is relaxed to let emscripten through, and the
`epoll`/`eventfd`/pipe-waker cfg lists gain emscripten.

Because emscripten cannot block in `epoll_wait` without JSPI/ASYNCIFY, two
non-blocking readiness paths are added alongside the normal `Poll::poll`:

* `Poll::new_with_callback` arms a persistent callback on the epoll fd via the
  runtime's `emscripten_epoll_set_callback`, delivering ready events on a fresh
  host tick whenever the set makes progress. The callback state is boxed, owned
  by the arming selector, and disarmed on drop; it may freely re-enter mio to
  (de)register sources.
* `Registry::poll_ready` does a zero-timeout drain of the same epoll set as a
  readiness probe where a blocking wait is impossible.

AF_UNIX support is stream-only: emscripten's node-backed sockets have no
datagram primitive, so `UnixDatagram` and the `socketpair`-based helpers are
not compiled there. Sockets set `O_NONBLOCK` via `fcntl` since emscripten's
`socket(2)` silently strips `SOCK_NONBLOCK`/`SOCK_CLOEXEC`.

The suite spawns OS threads (socket-peer test harnesses), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).
Doctests are skipped on this target: rustdoc does not apply the emcc link args,
so the examples cannot be linked with the socket/thread runtime.

Temporary, until the dependencies land upstream:

* Cargo.toml patches libc to guybedford/libc#emscripten for the emscripten
  epoll/pthread externs (rust-lang/libc#5270).
* the CI job builds against the guybedford/emscripten `cf` fork, which carries
  the epoll callback (emscripten-core/emscripten#27207), AF_UNIX pathname
  stream sockets, and multicast getsockopt patches this target depends on.

Suite result: 148 passed, 0 failed, 3 ignored under Node - green on CI.
guybedford added a commit to guybedford/mio that referenced this pull request Jul 11, 2026
Adds `wasm32-unknown-emscripten` as a target for mio, plus a CI job that runs
the suite under Node. Resolves tokio-rs#642.

Emscripten exposes a real epoll backed by its runtime event loop, so the
existing Linux epoll selector is reused rather than adding a new backend. The
wasm `compile_error!` guard is relaxed to let emscripten through, and the
`epoll`/`eventfd`/pipe-waker cfg lists gain emscripten.

Because emscripten cannot block in `epoll_wait` without JSPI/ASYNCIFY, two
non-blocking readiness paths are added alongside the normal `Poll::poll`:

* `Poll::new_with_callback` arms a persistent callback on the epoll fd via the
  runtime's `emscripten_epoll_set_callback`, delivering ready events on a fresh
  host tick whenever the set makes progress. The callback state is boxed, owned
  by the arming selector, and disarmed on drop; it may freely re-enter mio to
  (de)register sources.
* `Registry::poll_ready` does a zero-timeout drain of the same epoll set as a
  readiness probe where a blocking wait is impossible.

AF_UNIX support is stream-only: emscripten's node-backed sockets have no
datagram primitive, so `UnixDatagram` and the `socketpair`-based helpers are
not compiled there. Sockets set `O_NONBLOCK` via `fcntl` since emscripten's
`socket(2)` silently strips `SOCK_NONBLOCK`/`SOCK_CLOEXEC`.

The suite spawns OS threads (socket-peer test harnesses), so std is rebuilt
with atomics via -Zbuild-std and linked -pthread with -sPROXY_TO_PTHREAD so the
main thread can block; JSPI (-sJSPI) provides the return-to-host suspension for
blocking reads/writes, and NODERAWFS/NODERAWSOCKETS back the filesystem and
sockets with node's. This needs nightly + rust-src and a JSPI-capable Node
(26+, or 22 with --experimental-wasm-jspi). No custom target spec is required:
nightly now emits the __main_argc_argv entry point (rust-lang/rust#158937).
Doctests are skipped on this target: rustdoc does not apply the emcc link args,
so the examples cannot be linked with the socket/thread runtime.

Temporary, until the dependencies land upstream:

* Cargo.toml patches libc to guybedford/libc#emscripten for the emscripten
  epoll/pthread externs (rust-lang/libc#5270).
* the CI job builds against the guybedford/emscripten `cf` fork, which carries
  the epoll callback (emscripten-core/emscripten#27207), AF_UNIX pathname
  stream sockets, and multicast getsockopt patches this target depends on.

Suite result: 148 passed, 0 failed, 3 ignored under Node - green on CI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants