Skip to content

[wasm] Emit producers and build_id custom sections (native, webcil, R2R) - #130768

Open
pavelsavara with Copilot wants to merge 11 commits into
mainfrom
copilot/research-implementation-direction
Open

pavelsavara with Copilot wants to merge 11 commits into
mainfrom
copilot/research-implementation-direction

Conversation

Copilot AI commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

Emits the two WebAssembly tool-conventions custom sections — producers and build_id — into WebAssembly artifacts produced by the .NET toolchain for both Mono and CoreCLR.

Where the sections are emitted

Artifact producers build_id
dotnet.native.wasm relocatable object merged by wasm-ld during native relink and preserved through Emscripten managed task stamps a project-local runtime-pack copy or an already project-local relinked module
Webcil modules appended by WebcilWasmWrapper explicit $(WasmNativeBuildId) or per-file SHA-256 content hash
R2R Webcil appended by WebCilObjectWriter --wasm-native-build-id or a content hash

All paths reuse WasmCustomSectionWriter for custom-section encoding.

Workload-free build_id

$(WasmNativeBuildId) accepts a hexadecimal value and no longer forces a native relink or requires wasm-tools.

WasmStampBuildId:

  1. selects the relinked module when one exists, otherwise the runtime-pack module;
  2. stamps a relinked/project-local module in place;
  3. copies a shared runtime-pack module to a project-local intermediate before stamping it;
  4. substitutes the stamped runtime-pack copy only into the Wasm build-asset candidates, preserving standard fx/.../_framework materialization without enrolling it in normal publish copying;
  5. replaces equivalent runtime-pack publish candidates with one project-local publish-stamped copy;
  6. runs before static-web-asset fingerprinting, integrity calculation, compression, and bundling;
  7. registers generated outputs in @(FileWrites) for clean and incrementality.

The shared runtime-pack/NuGet file is never modified. The normalized ID is also emitted into the boot configuration so runtimeBuildInfo.buildId agrees with the stamped Wasm module without a native relink.

Invalid IDs fail in the managed task before asset processing.

producers

The .NET entries are:

  • language=C#
  • processed-by=<Mono|CoreCLR|WebCIL>
  • sdk=.NET

For native relinks, WasmEmitProducersObject contributes a small relocatable object. wasm-ld merges it with compiler-provided metadata, and -sEMIT_PRODUCERS_SECTION=1 prevents Emscripten from stripping the merged section. Set $(WasmEmitProducersSection)=false to disable it.

JavaScript exposure

runtimeBuildInfo.buildId receives the application ID through generated boot configuration. Relinked native modules may also provide the same value through their Emscripten footer; the native value takes precedence.

MSBuild properties

Property Meaning
WasmNativeBuildId Hexadecimal ID stamped into project-local native and Webcil Wasm artifacts. Does not force native relinking.
WasmEmitProducersSection Emit and preserve native producers metadata. Defaults to true.

Tests

WasmMetadataSectionsTests covers:

  • workload-free native runtime-pack stamping;
  • explicit native-relink stamping;
  • enabled and disabled native producers;
  • Webcil content-hash and pinned IDs;
  • invalid IDs without a workload;
  • fingerprinted asset paths, publish-root hygiene, and boot configuration.

CleanTests verifies:

  • the stamped runtime-pack module is materialized under fx/.../_framework;
  • stamped Wasm and dotnet-producers.o are removed by clean.

Local validation

  • Passed — Browser/CoreCLR baseline:

    .\build.cmd -bl -os browser -subset clr+libs+host -c Debug /p:StaticWebAssetsEnabled=false

    0 warnings, 0 errors.

  • Passed — WebAssembly pack and runtime WebAssembly SDK rebuilds.

  • Passed — workload-free metadata tests:

    .\dotnet.cmd build -bl /p:TargetOS=browser /p:TargetArchitecture=wasm /p:RuntimeFlavor=CoreCLR -c Debug -t:Test .\src\mono\wasm\Wasm.Build.Tests\ /p:InstallWorkloadForTesting=false /p:TestUsingWorkloads=false /p:XUnitClassName=Wasm.Build.NativeRebuild.Tests.WasmMetadataSectionsTests

    4 passed, 0 failed, 0 skipped.

  • Passed — stamped build/clean regression:

    .\dotnet.cmd build -bl /p:TargetOS=browser /p:TargetArchitecture=wasm /p:RuntimeFlavor=CoreCLR -c Debug -t:Test .\src\mono\wasm\Wasm.Build.Tests\ /p:InstallWorkloadForTesting=false /p:TestUsingWorkloads=true /p:XUnitMethodName=Wasm.Build.Tests.Blazor.CleanTests.Blazor_BuildIdStampedFile_ThenClean

    1 passed, 0 failed, 0 skipped.

  • Passed — explicit CoreCLR native relink with the current targets/tasks:

    • no .wasm files at the publish root;
    • fingerprinted native module contains C#, CoreCLR, and .NET producers;
    • build_id is 1a2b3c4d5e6f7788;
    • emcc response no longer contains --build-id.
  • Passed — build and publish with WasmBuildNative=false and a pinned ID:

    • no emcc/wasm-ld invocation;
    • stamped and fingerprinted modules contain the ID;
    • shared runtime-pack module hash remains unchanged.
  • Passed — runtime startup under Node:

    • runtimeBuildInfo.buildId and getConfig().buildId report the normalized ID.
  • Passed — incrementality:

    • identical IDs preserve Wasm and boot-config hashes/timestamps;
    • changing or removing the ID invalidates both.
  • Passed — CoreCLR Browser TypeScript rollup and Mono Browser lint.

The plain full build remains independently blocked in WasmAppHost.csproj by the installed SDK reporting:

Microsoft.NET.Sdk.BlazorWeb.DotNetWatch#[.{fingerprint}]!.lib.module.js
has no matching endpoint

The same error reproduced after an MSBuild clean and while building the SDK pack directly. Disabling static-web-assets processing only for the local baseline avoids that unrelated SDK issue. The affected task assemblies, loader assets, workload-free tests, build/publish paths, clean path, and explicit relink path were validated separately as listed above.

The Mono targets parse successfully and Mono Browser lint passes. A Mono runtime build was not run locally because this worktree contains CoreCLR artifacts.

Not included / deferred

  • Mutating or application-stamping the shared runtime-pack file itself.
  • Registration of the .NET producer names in the WebAssembly tool-conventions repository.

Design notes: docs/design/mono/wasm-custom-sections.md.

Merged current main at 5114fa5cd78d9da73b195c2cd3b0924e5495687e in merge commit a94b7d84a6bf5bf8649181c040dedadf65e9c978. This includes the serial Helix dependency-staging fix from #136764.

Resolves #96334
Resolves #91049

Note

This PR description was updated with the assistance of GitHub Copilot.

Copilot AI and others added 2 commits July 15, 2026 10:30
Co-authored-by: pavelsavara <271576+pavelsavara@users.noreply.github.com>
Co-authored-by: pavelsavara <271576+pavelsavara@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot July 15, 2026 10:43
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI review requested due to automatic review settings July 15, 2026 20:35
@pavelsavara
pavelsavara temporarily deployed to copilot-pat-pool July 15, 2026 20:35 — with GitHub Actions Inactive
@pavelsavara
pavelsavara temporarily deployed to copilot-pat-pool July 15, 2026 20:36 — with GitHub Actions Inactive

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.

Pull request overview

This PR prototypes emitting WebAssembly tool-conventions custom sections (producers, build_id) and surfacing a buildId value through the browser-wasm JavaScript API, wiring it through the Mono/CoreCLR relink pipelines and stamping WebCIL/R2R wasm outputs.

Changes:

  • Add a reusable managed WasmCustomSectionWriter and an MSBuild task to generate a linkable wasm object contributing .NET entries to the producers section during relink.
  • Plumb WasmNativeBuildId through build targets/tasks and expose runtimeBuildInfo.buildId in the JS public API surface.
  • Add WBT coverage for relink/webcil metadata sections and a design doc describing the approach.

Reviewed changes

Copilot reviewed 38 out of 42 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/tasks/WasmAppBuilder/WebcilConverter.cs Exposes build-id/version passthrough to Webcil converter.
src/tasks/WasmAppBuilder/WasmEmitProducersObject.cs New task writing producers wasm object for linker merge.
src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilWasmWrapper.cs Appends producers/build_id to wrapped WebCIL wasm.
src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs Wires metadata options into wrapper output.
src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj Links shared custom-section writer into task assembly.
src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs Passes build-id/product version into WebCIL conversion.
src/native/rollup.config.defines.js Adds buildId rollup constant from env.
src/native/libs/System.Native.Browser/native/index.ts Overrides runtimeBuildInfo.buildId from relinked native module.
src/native/libs/System.Native.Browser/libSystem.Native.Browser.footer.js Exposes WASM_BUILD_ID via $DOTNET during emcc link.
src/native/libs/Common/JavaScript/types/public-api.ts Extends public RuntimeAPI typing with buildId.
src/native/libs/Common/JavaScript/types/ems-ambient.ts Adds buildId to emscripten ambient DOTNET shape.
src/native/libs/Common/JavaScript/loader/index.ts Seeds runtimeBuildInfo.buildId from rollup constant.
src/native/libs/Common/JavaScript/loader/dotnet.d.ts Updates generated public typings for buildId.
src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/WasmMetadataSectionsTests.cs New tests validating producers/build_id emission.
src/mono/wasm/build/WasmApp.Common.targets Forces native relink when WasmNativeBuildId is set.
src/mono/sample/wasm/Directory.Build.targets Propagates WasmNativeBuildId through nested builds.
src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj Sample configuration updates (currently problematic).
src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadManifest.targets.in Treats WasmNativeBuildId as relink-triggering.
src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets Passes build-id/version into ConvertDllsToWebCIL task.
src/mono/browser/runtime/types/internal.ts Adds buildId to emscriptenBuildOptions typing.
src/mono/browser/runtime/types/index.ts Extends runtime API typing with buildId.
src/mono/browser/runtime/rollup.config.js Adds buildId constant in mono runtime rollup config.
src/mono/browser/runtime/loader/globals.ts Formatting-only changes.
src/mono/browser/runtime/loader/assets.ts Formatting-only changes.
src/mono/browser/runtime/globals.ts Copies buildId from relinked module into runtimeBuildInfo.
src/mono/browser/runtime/exports.ts Seeds runtimeBuildInfo.buildId from rollup constant.
src/mono/browser/runtime/es6/dotnet.es6.lib.js Plumbs WASM_BUILD_ID into emcc-evaluated options blob.
src/mono/browser/runtime/dotnet.d.ts Updates generated public typings for buildId.
src/mono/browser/build/BrowserWasmApp.targets Mono relink: emits producers object + build-id linker/env wiring.
src/mono/browser/build/BrowserWasmApp.CoreCLR.targets CoreCLR relink: emits producers object + build-id linker/env wiring.
src/mono/browser/browser.proj Treats WasmNativeBuildId as runtime-pack defaultable property.
src/coreclr/tools/Common/Wasm/WasmCustomSectionWriter.cs New encoder/merger for producers/build_id custom sections.
src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs Stamps producers/build_id into R2R webcil wasm output.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj Links shared custom-section writer into ILC tool.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs Plumbs wasm build-id option through compilation pipeline.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs Carries wasm build-id into object emission.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs Passes wasm build-id through to WasmObjectWriter.
src/coreclr/tools/aot/crossgen2/Properties/Resources.resx Adds help text for new crossgen2 option.
src/coreclr/tools/aot/crossgen2/Program.cs Wires new option into ReadyToRun builder.
src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs Adds --wasm-native-build-id option.
src/coreclr/hosts/corerun/wasm/libCorerun.extpost.js Adds buildId field to corerun runtimeBuildInfo.
docs/design/mono/wasm-custom-sections.md Design doc describing custom section strategy and properties.

@pavelsavara pavelsavara changed the title [wasm] Emit producers and build_id custom sections (prototype) [wasm] Emit producers and build_id custom sections (native, webcil, R2R) Jul 15, 2026
Resolve Browser WASM custom-section conflicts with the current WebCIL writer and app-relink infrastructure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pavelsavara and others added 3 commits October 23, 2026 16:50
Resolve ReadyToRun WebCIL conflicts while preserving build IDs, debug information, and symbol maps.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Enable Emscripten's producers-section setting for Mono and CoreCLR links so the metadata merged by wasm-ld survives post-link processing. Cover both enabled and disabled emission.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use endian-safe WASM parsing, escape generated build IDs, fail invalid Webcil IDs early, retain task exception details, and restore the Browser runtime's linted formatting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pavelsavara and others added 4 commits October 29, 2026 18:38
Patch a project-local copy of dotnet.native.wasm before static asset fingerprinting instead of forcing a native relink. Flow the normalized ID through boot configuration and keep relinked producers support unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stamp relinked project-local modules in place and keep copied runtime-pack
modules on the standard build and publish asset paths. This preserves framework
materialization and avoids duplicate publish candidates.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Route the build-stamped runtime module only through Wasm build candidates so
standard publish copying cannot place it at the publish root. Update the clean
regression to verify the stamped framework materialization directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pavelsavara pavelsavara added arch-wasm WebAssembly architecture os-browser Browser variant of arch-wasm labels Nov 3, 2026
@pavelsavara pavelsavara added this to the 12.0.0 milestone Nov 3, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

@pavelsavara
pavelsavara marked this pull request as ready for review November 3, 2026 16:43
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

This branch was previously deployed

1 inactive (outdated) deployment
copilot-pat-pool — 457c3749 Deployed Jul 15, 2026 by pavelsavara via pat_pool #15245
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-Build-mono os-browser Browser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emit Producers section when compiling to wasm Blazor - WebAssembly build_id section

3 participants