Repository navigation
Description
Note
This issue was authored with assistance from GitHub Copilot.
Summary
On CoreCLR-Wasm, Wasm.Build.Tests.InvariantGlobalizationTests.RelinkingWithoutAOT(invariantGlobalization: True) fails during the native relink step. wasm-ld reports ~40 undefined symbols pulled in by pinvoke-table.o, all of them GlobalizationNative_* entry points.
Example failing run:
- Helix workitem:
WBT-NoWorkload-CLR-ST-Wasm.Build.Tests.InvariantGlobalizationTests - https://helix.dot.net/api/2019-06-17/jobs/df2c7cc8-0f2c-40ec-8bf6-86c8bb48ed1b/workitems/WBT-NoWorkload-CLR-ST-Wasm.Build.Tests.InvariantGlobalizationTests/console
Representative error lines:
wasm-ld : error : pinvoke-table.o: undefined symbol: GlobalizationNative_ChangeCase
wasm-ld : error : pinvoke-table.o: undefined symbol: GlobalizationNative_CompareString
wasm-ld : error : pinvoke-table.o: undefined symbol: GlobalizationNative_LoadICU
wasm-ld : error : pinvoke-table.o: undefined symbol: GlobalizationNative_GetCalendars
... (~37 more GlobalizationNative_* symbols)
emcc : error : '.../wasm-ld ...' failed (returned 1)
BrowserWasmApp.CoreCLR.targets(625,5): error MSB3073: ... emcc ... exited with code 1.
Test failure summary:
Wasm.Build.Tests.InvariantGlobalizationTests.RelinkingWithoutAOT(config: Release, aot: False, invariantGlobalization: True) [FAIL]
Wasm.Build.Tests Total: 3, Errors: 0, Failed: 1, Skipped: 0, Time: 237.356s
Analysis
When InvariantGlobalization=true, the generated pinvoke-table.o still references the GlobalizationNative_* PInvoke entry points (because managed code in System.Private.CoreLib / System.Globalization declares them), but libSystem.Globalization.Native.a is intentionally not linked into the CoreCLR browser-wasm app. There is no providing object for these symbols, so wasm-ld fails.
On Mono-Wasm the same logical situation does not blow up because the Mono native link path provides stubs / weak resolution for the invariant case.
This is distinct from the related JS-side issue around wasm_load_icu_data being excluded from libBrowserHost.footer.js commonDeps — that fix addresses the JS Emscripten library dependency graph, not the native wasm-ld PInvoke link.
Proposed fix
Provide an empty stub library for System.Globalization.Native that gets linked into the CoreCLR browser-wasm app when InvariantGlobalization=true. The stub exports the same GlobalizationNative_* symbols (as no-op / unreachable / abort() implementations) so wasm-ld can satisfy pinvoke-table.o references, while ensuring the runtime never actually calls them (managed code guards on the invariant mode flag before calling into them).
This mirrors how other "no-op" native libraries are linked into the browser-wasm app (e.g. the TimeZoneData / Native variants already split by configuration).
Workaround until fixed
InvariantGlobalizationTests is gated to Mono-only via [ConditionalTheory(typeof(BuildTestBase), nameof(IsMonoRuntime))] in PR (link to follow). Once the stub library is in place, remove the gating to re-enable CoreCLR coverage.
Areas
- area-Codegen-Interop-coreclr
- area-System.Globalization
- arch-wasm
Activity
dotnet-policy-service commentedon May 14, 2026
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.
dotnet-policy-service commentedon May 14, 2026
Tagging subscribers to this area: @dotnet/area-system-globalization
See info in area-owners.md if you want to be subscribed.
[wasm][WBT] Gate InvariantGlobalizationTests to Mono only
pavelsavara commentedon Jun 12, 2026
This should be the workaround #129243
And duplicates #129242 #129324