Skip to content

Include startup crt objects on WASI for more outputs - #161421

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
alexcrichton:more-wasi-crt-objects
Aug 28, 2026
Merged

Include startup crt objects on WASI for more outputs#161421
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
alexcrichton:more-wasi-crt-objects

Conversation

@alexcrichton

Copy link
Copy Markdown
Member

This commit adds the crt1-reactor.o object file in the list of pre-link-crt-objects for the {Dynamic,Static}Dylib output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional _initialize function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required.

@rustbot rustbot added 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 Aug 20, 2026
@rustbot

rustbot commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

r? @fee1-dead

rustbot has assigned @fee1-dead.
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 18 candidates

@rust-log-analyzer

This comment has been minimized.

@alexcrichton
alexcrichton force-pushed the more-wasi-crt-objects branch from bab467a to db284c5 Compare August 20, 2026 19:28
@rustbot

rustbot commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

The run-make-support library was changed

cc @jieyouxu

@rustbot rustbot added the A-run-make Area: port run-make Makefiles to rmake.rs label Aug 20, 2026
@@ -127,6 +127,8 @@ pub(super) fn pre_wasi_self_contained() -> CrtObjects {
(LinkOutputKind::StaticNoPicExe, &["crt1-command.o"]),
(LinkOutputKind::StaticPicExe, &["crt1-command.o"]),
(LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]),

@bjorn3 bjorn3 Aug 21, 2026

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.

Do we still need the separate flag to enable usage of crt1-reactor.o?

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't recall the history here myself, but I suspect not, no.

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.

cc #108097 That PR also changed from --no-entry to --entry _initialize, though not just on wasi, but all wasm targets.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'd like to only handle WASI targets here, not all targets. That PR also never landed I believe? The goal of this change is to handle ABI details for the upcoming wasip3 target which is broken without linking these files.

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.

I'd like to only handle WASI targets here, not all targets.

I'm aware.

That PR also never landed I believe?

Indeed. I was looking at why it never landed. I think because it was also touching other targets.

Wouldn't this PR also need to copy the --no-entry -> --entry _initialize change from that PR, but just for wasi? And maybe copy the table doc table change.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sure, I've updated the table. I don't believe the --no-entry change is necessary -- with this PR _initialize is still exported works as intended.

@alexcrichton
alexcrichton force-pushed the more-wasi-crt-objects branch from db284c5 to 2188d93 Compare August 25, 2026 16:31
@rustbot

rustbot commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@fee1-dead

Copy link
Copy Markdown
Member

Sorry, not familiar enough to review :)

@rustbot reroll

@rustbot rustbot assigned folkertdev and unassigned fee1-dead Aug 26, 2026
@folkertdev

Copy link
Copy Markdown
Contributor

r? @bjorn3

@rustbot rustbot assigned bjorn3 and unassigned folkertdev Aug 26, 2026
@alexcrichton
alexcrichton force-pushed the more-wasi-crt-objects branch from 2188d93 to 2089220 Compare August 26, 2026 15:29
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 26, 2026
@alexcrichton alexcrichton reopened this Aug 26, 2026
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 26, 2026
Comment thread tests/run-make/wasm-symbols-not-exported/rmake.rs
Comment thread src/tools/run-make-support/src/external_deps/rustc.rs Outdated
@bjorn3 bjorn3 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 27, 2026
This commit adds the `crt1-reactor.o` object file in the list of
pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for
WASI targets. These previously were omitted I believe by accident and
this means that the conventional `_initialize` function is not present
which runs constructor functions, for example. This is additionally
needed for the upcoming wasip3 target where this startup object file is
more load bearing than it was previously and will become required.
@alexcrichton
alexcrichton force-pushed the more-wasi-crt-objects branch from 2089220 to f9ad9e1 Compare August 27, 2026 15:26
@bjorn3

bjorn3 commented Aug 27, 2026

Copy link
Copy Markdown
Member

@bors r+

@rust-bors

rust-bors Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

📌 Commit f9ad9e1 has been approved by bjorn3

It is now in the queue for this repository.

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 27, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 27, 2026
…, r=bjorn3

Include startup crt objects on WASI for more outputs

This commit adds the `crt1-reactor.o` object file in the list of pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional `_initialize` function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Aug 27, 2026
…, r=bjorn3

Include startup crt objects on WASI for more outputs

This commit adds the `crt1-reactor.o` object file in the list of pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional `_initialize` function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required.
rust-bors Bot pushed a commit that referenced this pull request Aug 28, 2026
Rollup of 14 pull requests

Successful merges:

 - #150075 (Implement clamp_to)
 - #159103 (fix(reborrow): recursive implementation)
 - #160848 (std: avoid aliasing violations when wrapping opaque C types)
 - #161421 (Include startup crt objects on WASI for more outputs)
 - #161805 (Prefer ambiguous candidates when deduplicating traits in scope, so `ambiguous_glob_imported_traits` doesn't depend on import order)
 - #161862 (Put data segment in specified section with link_section on wasm)
 - #161866 (delegation: add tests fixating behavior of delegating to default trait implementations)
 - #161456 (reduce perf impact of scalar size checks)
 - #161666 (Print vendor instructions in `x vendor`)
 - #161730 (Improve type mismatch annotation for lets with block-wrapped initializers)
 - #161828 (Never type after-stabilization cleanup)
 - #161860 (atomicptr.rs test: remove unused import)
 - #161870 (bind to [::1] instead of 127.0.0.1 in documentation examples for v6 UDP methods)
 - #161876 (rustdoc: Correctly handle when a macro generates multiple items in `--generate-macro-expansion`)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 28, 2026
…, r=bjorn3

Include startup crt objects on WASI for more outputs

This commit adds the `crt1-reactor.o` object file in the list of pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional `_initialize` function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 28, 2026
…, r=bjorn3

Include startup crt objects on WASI for more outputs

This commit adds the `crt1-reactor.o` object file in the list of pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional `_initialize` function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required.
rust-bors Bot pushed a commit that referenced this pull request Aug 28, 2026
…uwer

Rollup of 21 pull requests

Successful merges:

 - #158609 (Update sccache to 0.16.0)
 - #150075 (Implement clamp_to)
 - #159103 (fix(reborrow): recursive implementation)
 - #160562 (add target feature ABI checks for SPARC)
 - #160848 (std: avoid aliasing violations when wrapping opaque C types)
 - #161421 (Include startup crt objects on WASI for more outputs)
 - #161805 (Prefer ambiguous candidates when deduplicating traits in scope, so `ambiguous_glob_imported_traits` doesn't depend on import order)
 - #161862 (Put data segment in specified section with link_section on wasm)
 - #161866 (delegation: add tests fixating behavior of delegating to default trait implementations)
 - #161456 (reduce perf impact of scalar size checks)
 - #161528 (Add regression test to ensure optimal compilation)
 - #161666 (Print vendor instructions in `x vendor`)
 - #161730 (Improve type mismatch annotation for lets with block-wrapped initializers)
 - #161828 (Never type after-stabilization cleanup)
 - #161859 (Do not optimize MIR for comptime ConstFns)
 - #161860 (atomicptr.rs test: remove unused import)
 - #161870 (bind to [::1] instead of 127.0.0.1 in documentation examples for v6 UDP methods)
 - #161876 (rustdoc: Correctly handle when a macro generates multiple items in `--generate-macro-expansion`)
 - #161889 (Add link to ownership section in ptr::read docs)
 - #161890 (rustdoc: some clarifying comments)
 - #161891 (Mark `extern_item_impls` feature as incomplete)

Failed merges:

 - #161702 (Use `drop_guard` in some places in {core,alloc,std})
rust-bors Bot pushed a commit that referenced this pull request Aug 28, 2026
…uwer

Rollup of 21 pull requests

Successful merges:

 - #150075 (Implement clamp_to)
 - #159103 (fix(reborrow): recursive implementation)
 - #160562 (add target feature ABI checks for SPARC)
 - #160848 (std: avoid aliasing violations when wrapping opaque C types)
 - #161421 (Include startup crt objects on WASI for more outputs)
 - #161805 (Prefer ambiguous candidates when deduplicating traits in scope, so `ambiguous_glob_imported_traits` doesn't depend on import order)
 - #161862 (Put data segment in specified section with link_section on wasm)
 - #161866 (delegation: add tests fixating behavior of delegating to default trait implementations)
 - #157218 (Track items behind `cfg_select` in the same way we do for `cfg`)
 - #161456 (reduce perf impact of scalar size checks)
 - #161528 (Add regression test to ensure optimal compilation)
 - #161666 (Print vendor instructions in `x vendor`)
 - #161730 (Improve type mismatch annotation for lets with block-wrapped initializers)
 - #161828 (Never type after-stabilization cleanup)
 - #161859 (Do not optimize MIR for comptime ConstFns)
 - #161860 (atomicptr.rs test: remove unused import)
 - #161870 (bind to [::1] instead of 127.0.0.1 in documentation examples for v6 UDP methods)
 - #161876 (rustdoc: Correctly handle when a macro generates multiple items in `--generate-macro-expansion`)
 - #161889 (Add link to ownership section in ptr::read docs)
 - #161890 (rustdoc: some clarifying comments)
 - #161891 (Mark `extern_item_impls` feature as incomplete)

Failed merges:

 - #161702 (Use `drop_guard` in some places in {core,alloc,std})
@rust-bors
rust-bors Bot merged commit 012aad4 into rust-lang:main Aug 28, 2026
13 checks passed
@rustbot rustbot added this to the 1.100.0 milestone Aug 28, 2026
rust-bors Bot pushed a commit that referenced this pull request Aug 28, 2026
Rollup merge of #161421 - alexcrichton:more-wasi-crt-objects, r=bjorn3

Include startup crt objects on WASI for more outputs

This commit adds the `crt1-reactor.o` object file in the list of pre-link-crt-objects for the `{Dynamic,Static}Dylib` output kinds for WASI targets. These previously were omitted I believe by accident and this means that the conventional `_initialize` function is not present which runs constructor functions, for example. This is additionally needed for the upcoming wasip3 target where this startup object file is more load bearing than it was previously and will become required.
Brooooooklyn added a commit to napi-rs/napi-rs that referenced this pull request Sep 9, 2026
rust-lang/rust#161421 added `crt1-reactor.o` to the pre-link crt objects for
the dylib output kinds on WASI, landing in Rust 1.100. It was omitted before
that, which is why this crate passes the object by hand to obtain the
conventional `_initialize`. On a toolchain that now links it, passing it
again makes the link fail:

    wasm-ld: error: duplicate symbol: _initialize

Probe rather than compare versions: link a trivial cdylib for the target and
read its export section. One short rustc invocation, measured at ~50ms, and
exact on every channel — a version gate would misread the nightlies between
1.100.0-nightly opening and the change landing.

Searching the module bytes for the name does not work: `_initialize` also
occurs inside the linked standard library, so it matches whether or not the
startup object was linked. Only the export section answers the question,
hence the small section walker.

When the probe cannot run the old behaviour is kept, so a toolchain that
still needs the object never loses it.

Verified on examples/napi, wasm32-wasip1-threads:

    stable 1.98,  no WASI_SDK_PATH   build ok, _initialize exported
    nightly 09-08, WASI_SDK_PATH=33  build ok, _initialize exported
    nightly 09-08, same, fix reverted -> wasm-ld: duplicate symbol: _initialize

The nightly runs pin wasi-sdk 33 so the futex ABI stays consistent and only
the startup object is exercised; the emnapi archive selection for wasi-sdk 34
is a separate change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so
Brooooooklyn added a commit to napi-rs/napi-rs that referenced this pull request Sep 9, 2026
rust-lang/rust#161421 added `crt1-reactor.o` to the pre-link crt objects for
the dylib output kinds on WASI, landing in Rust 1.100. It was omitted before
that, which is why this crate passes the object by hand to obtain the
conventional `_initialize`. On a toolchain that now links it, passing it
again makes the link fail:

    wasm-ld: error: duplicate symbol: _initialize

Probe rather than compare versions: link a trivial cdylib for the target and
read its export section. One short rustc invocation, measured at ~50ms, and
exact on every channel — a version gate would misread the nightlies between
1.100.0-nightly opening and the change landing.

Searching the module bytes for the name does not work: `_initialize` also
occurs inside the linked standard library, so it matches whether or not the
startup object was linked. Only the export section answers the question,
hence the small section walker.

When the probe cannot run the old behaviour is kept, so a toolchain that
still needs the object never loses it.

Verified on examples/napi, wasm32-wasip1-threads:

    stable 1.98,  no WASI_SDK_PATH   build ok, _initialize exported
    nightly 09-08, WASI_SDK_PATH=33  build ok, _initialize exported
    nightly 09-08, same, fix reverted -> wasm-ld: duplicate symbol: _initialize

The nightly runs pin wasi-sdk 33 so the futex ABI stays consistent and only
the startup object is exercised; the emnapi archive selection for wasi-sdk 34
is a separate change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so
Brooooooklyn added a commit to napi-rs/napi-rs that referenced this pull request Sep 9, 2026
…Rust nightly (#3492)

* fix(cli): pick the emnapi archives by wasi-sdk version

wasi-libc dropped the unused `int op` parameter from
`__wasilibc_futex_wait_atomic_wait` and `__wasilibc_futex_wait_maybe_busy`
(WebAssembly/wasi-libc#846), and wasi-sdk 34 is the first release shipping
the 3-argument signature. Linking the legacy 4-argument archives against a
wasi-sdk >= 34 sysroot makes wasm-ld report `function signature mismatch`
and emit an invalid wasm module:

    wasm-ld: function signature mismatch: __wasilibc_futex_wait_atomic_wait
      >>> defined as (i32, i32, i32, i64) -> i32 in
          emnapi/lib/wasm32-wasip1-threads/libemnapi-napi-rs-mt.a(wasi_wait.c.obj)
      >>> defined as (i32, i32, i64) -> i32 in
          wasi-sdk-34.0/.../libc.a(futex.c.obj)

emnapi already publishes a second archive set for the new ABI at
`emnapi/lib/wasm32-wasip1-threads-wasi-sdk-34`, but `setWasiEnv()` derived
the directory from the target triple alone and never picked it.

Add `wasiSdkMajorVersion()`, which reads `<root>/VERSION` and falls back to
`wasi/version.h`, and `selectEmnapiLinkDir()`, which uses the sdk-34
archives only when the target has threads, `WASI_SDK_PATH` resolves to a
wasi-sdk >= 34, and that directory exists. The legacy directory stays the
default: without `WASI_SDK_PATH`, cargo links through `rust-lld` against
the wasi-libc bundled with the Rust standard library, which still uses the
4-argument signature.

Also add a `wasi-sdk` CI job that links `@examples/napi` through a real
wasi-sdk, on both a pre-34 and a post-34 release, so the selection cannot
regress silently. The wasi-sdk 34 lane links only. Running the module needs
a Rust toolchain whose `crt1` was built with wasi-sdk >= 34, which is a
separate incompatibility tracked in #3491.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* fix(cli): gate the wasi-sdk job and clarify the missing-archive error

Review follow-ups on #3492.

- `done` is the aggregate check that blocks merges, but its `needs` list
  omitted the new `wasi-sdk` job, so an archive-selection regression would
  not have failed the required gate. Add it.
- The missing-archive error had a misleading branch: after falling back to
  the legacy directory, it named that directory as the missing one while
  telling the reader to install the wasi-sdk 34 archives. Split it into
  three cases and reuse the `fellBackToLegacy` condition the warning
  below already needs, so the two cannot drift apart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* fix(cli): detect the futex ABI from Rust's bundled wasi-libc too

Review follow-up on #3492.

Keying the archive choice off `WASI_SDK_PATH` alone was incomplete. Without
it, cargo links through `rust-lld` against the wasi-libc bundled with the
Rust standard library, and Rust picked up wasi-sdk 34 in
rust-lang/rust#161773, landing in 1.100. Such a toolchain needs the new
archives even though no wasi-sdk is configured; the old rule would have
selected the legacy 4-argument set and reproduced the very mismatch this
branch fixes.

Probe whichever wasi-libc actually gets linked. `wasiLibcHasNewFutexAbi()`
looks for the `futex.c.obj` archive member: wasi-libc moved the futex
helpers into `futex.c` in the same change that dropped `int op`
(WebAssembly/wasi-libc#846), while `__wait.c` survives for other symbols, so
the presence of `futex.c` — not the absence of `__wait.c` — separates the
two ABIs. Verified against wasi-sdk 33 and 34 sysroots and against Rust's
own bundled copies.

The Rust sysroot is resolved lazily, so a configured wasi-sdk never pays for
a `rustc` invocation, and an undetectable sysroot still degrades to the
legacy archives.

Measured on real toolchains:

    toolchain       bundled   no WASI_SDK_PATH   sdk 33    sdk 34
    stable 1.98     legacy    legacy             legacy    sdk-34
    nightly 09-08   new       sdk-34             legacy    sdk-34

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* perf(cli): skip the wasi-libc probe for threadless targets

`needsWasiSdk34` is already gated on `hasThreads`, but the ABI probe ran
before that test, so a threadless wasi build spawned `rustc --print sysroot`
and read a 3 MB archive to produce a value it then discarded. emnapi ships
no wasi-sdk 34 archive set for the threadless target, so the answer cannot
change the outcome. Move the `hasThreads` test in front of the probe.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* fix(build): skip crt1-reactor.o when rustc already links it

rust-lang/rust#161421 added `crt1-reactor.o` to the pre-link crt objects for
the dylib output kinds on WASI, landing in Rust 1.100. It was omitted before
that, which is why this crate passes the object by hand to obtain the
conventional `_initialize`. On a toolchain that now links it, passing it
again makes the link fail:

    wasm-ld: error: duplicate symbol: _initialize

Probe rather than compare versions: link a trivial cdylib for the target and
read its export section. One short rustc invocation, measured at ~50ms, and
exact on every channel — a version gate would misread the nightlies between
1.100.0-nightly opening and the change landing.

Searching the module bytes for the name does not work: `_initialize` also
occurs inside the linked standard library, so it matches whether or not the
startup object was linked. Only the export section answers the question,
hence the small section walker.

When the probe cannot run the old behaviour is kept, so a toolchain that
still needs the object never loses it.

Verified on examples/napi, wasm32-wasip1-threads:

    stable 1.98,  no WASI_SDK_PATH   build ok, _initialize exported
    nightly 09-08, WASI_SDK_PATH=33  build ok, _initialize exported
    nightly 09-08, same, fix reverted -> wasm-ld: duplicate symbol: _initialize

The nightly runs pin wasi-sdk 33 so the futex ABI stays consistent and only
the startup object is exercised; the emnapi archive selection for wasi-sdk 34
is a separate change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* test(ci): run the wasi-sdk 34 artifact on nightly

The lane was link-only because the module could not instantiate: wasi-sdk
34 deleted `__wasi_init_tp`, and Rust's pre-34 `crt1-reactor.o` still calls
it. Nightly ships an sdk-34 era `crt1` and links it itself, so the object
that carried the undefined symbol is no longer in the module at all.

Measured on `1.100.0-nightly (4aa1fbcf4 2026-09-08)` with wasi-sdk 34.0:
the example suite runs 268 passed / 10 skipped through the WASI binding,
and `wasm-objdump -j Import` shows no `__wasi_init_tp`.

This also gives `rustc_links_reactor_crt()` its only CI coverage. Stable
rustc does not link the startup object, so the sdk-33 lane never reaches
that branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* fix(cli): probe the Rust sysroot from the build cwd

`rustc` is a rustup shim: it resolves `rust-toolchain.toml` and directory
overrides from its working directory. `Builder.exec()` spawns Cargo with
`cwd: this.options.cwd`, but the futex ABI probe ran `rustc` from the
caller's directory. With `napi build --cwd <project>` the two can disagree.

Measured, one caller directory, two toolchains:

    cwd=<caller>   rustBundledWasiLibc() -> stable/.../libc.a   newFutexAbi=false
    cwd=<project>  rustBundledWasiLibc() -> nightly/.../libc.a  newFutexAbi=true

The probe would answer "legacy" while Cargo links nightly's wasi-libc,
which selects the wrong emnapi archives and produces the signature
mismatch this code exists to prevent.

Pass the build cwd, and honour `RUSTC` / `CARGO_BUILD_RUSTC`, which bypass
the shim; Cargo gives `RUSTC` precedence, so do the same. `execFileSync`
replaces `execSync` because an overridden path can contain spaces.
`build.rustc` from the project's `.cargo/config.toml` stays out of reach
without invoking cargo itself.

`selectEmnapiLinkDir()` takes its last two inputs as an options bag, so the
test injection point and the new cwd do not become positional arguments.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

* fix(build): honour link-self-contained in the reactor probe

`-C link-self-contained=no` tells rustc to leave out its own crt objects.
The probe ran without the user's rustflags, so it saw `_initialize`,
reported that rustc supplies the startup object, and made napi-build skip
ours. The real link then had neither, and the module shipped without the
export. It links cleanly, so nothing reports the loss.

Reproduced end to end on nightly, with `WASI_SDK_PATH` set so the missing
`-lc` resolves through the link search path napi-build already emits:

    CARGO_ENCODED_RUSTFLAGS = "-C\u{1f}link-self-contained=no"
    probe -> Some(true) -> skip manual crt
    exports: memory, wasi_thread_start          <- no _initialize

The same crate on the old always-link path exports `_initialize`, so this
is a regression the probe introduced, not a pre-existing hole.

Forward only `-C link-self-contained`. Passing the whole rustflags breaks
the probe on anything that does not apply to an empty crate: a lone
`-C link-arg=--export=napi_register_wasm_v1` makes it fail to link, which
returns `None` and brings back `duplicate symbol: _initialize`.

Cargo hands build scripts `CARGO_ENCODED_RUSTFLAGS`, never `RUSTFLAGS`, and
separates arguments with a unit separator. Both spellings Cargo can emit
are handled: `-C` plus value, and one glued `-C<value>`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzmUqCAaDMut4aQGUhj4so

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

6 participants