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:
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
/cc @maraf @lewing @pavelsavara
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-ldreports ~40 undefined symbols pulled in bypinvoke-table.o, all of themGlobalizationNative_*entry points.Example failing run:
WBT-NoWorkload-CLR-ST-Wasm.Build.Tests.InvariantGlobalizationTestsRepresentative error lines:
Test failure summary:
Analysis
When
InvariantGlobalization=true, the generatedpinvoke-table.ostill references theGlobalizationNative_*PInvoke entry points (because managed code inSystem.Private.CoreLib/System.Globalizationdeclares them), butlibSystem.Globalization.Native.ais intentionally not linked into the CoreCLR browser-wasm app. There is no providing object for these symbols, sowasm-ldfails.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_databeing excluded fromlibBrowserHost.footer.jscommonDeps— that fix addresses the JS Emscripten library dependency graph, not the nativewasm-ldPInvoke link.Proposed fix
Provide an empty stub library for
System.Globalization.Nativethat gets linked into the CoreCLR browser-wasm app whenInvariantGlobalization=true. The stub exports the sameGlobalizationNative_*symbols (as no-op / unreachable /abort()implementations) sowasm-ldcan satisfypinvoke-table.oreferences, 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
InvariantGlobalizationTestsis 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
/cc @maraf @lewing @pavelsavara