Skip to content

[msbuild] Generate C code for runtimeconfig properties (CoreCLR). Fixes #26334 - #26335

Open
rolfbjarne wants to merge 4 commits into
dev/rolf/runtimeconfig-dev-jsonfrom
dev/rolf/issue-26334-msbuild-generate-c-code-for-the-runtime-6e7ef8
Open

[msbuild] Generate C code for runtimeconfig properties (CoreCLR). Fixes #26334#26335
rolfbjarne wants to merge 4 commits into
dev/rolf/runtimeconfig-dev-jsonfrom
dev/rolf/issue-26334-msbuild-generate-c-code-for-the-runtime-6e7ef8

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

For CoreCLR-based apps we currently produce the binary runtimeconfig.bin, ship it in the app bundle, then mmap and decode it at startup to feed the configProperties into coreclr_initialize. That's an extra file to ship and extra decoding work at launch, for data that is fully known at build time.

This bakes the runtimeconfig.json configProperties directly into the app as compiled-in C arrays (emitted into the generated main.mm and assigned to new xamarin_runtime_config_property_* globals in libxamarin). xamarin_bridge_compute_properties now reads those globals instead of locating, mmapping and decoding runtimeconfig.bin, and the mobile-runtimeconfig decode helpers are removed.

Approach

  • Runtime: add xamarin_runtime_config_property_count/keys/values globals in runtime.m (assigned from the app's generated main, same pattern as xamarin_runtime_configuration_name), and rewrite xamarin_bridge_compute_properties in coreclr-bridge.m to copy from them.
  • Linker: GenerateMainStep parses runtimeOptions.configProperties from the merged runtimeconfig.json for CoreCLR (matching the value stringification done by dotnet/runtime's RuntimeConfigParserTask), rejects reserved properties (error 2322) and unsupported value kinds (error 2321), and Target.cs emits the C arrays plus the global assignment in xamarin_setup_impl.
  • MSBuild: the binary runtimeconfig format is now gated to MonoVM only. CoreCLR gets the merged json handed to the linker; NativeAOT already embeds its configuration at publish time and never read runtimeconfig.bin, so it stops shipping the unused file too.

MonoVM is unchanged: it still needs the blob for monovm_runtimeconfig_initialize.

Notes

Fixes: #26334

🤖 Pull request created by Copilot

rolfbjarne and others added 3 commits July 28, 2026 17:40
…reCLR

For CoreCLR, generate C arrays for the runtimeconfig.json 'configProperties'
in the app's generated main (assigned to globals defined in libxamarin) instead
of producing the binary runtimeconfig format, shipping it in the bundle, and
mmap+decoding it at startup.

MonoVM still needs the binary blob (for monovm_runtimeconfig_initialize) and
NativeAOT doesn't call xamarin_bridge_vm_initialize, so both keep the previous
behaviour.

- runtime: add xamarin_runtime_config_property_count/keys/values globals
  (runtime.m + main.h) and rewrite xamarin_bridge_compute_properties
  (coreclr-bridge.m) to use them; drop the now-unused mmap/decode helpers.
- linker: GenerateMainStep parses runtimeOptions.configProperties from the
  merged runtimeconfig.json (value stringification matching dotnet/runtime's
  RuntimeConfigParser) with a reserved-property check, and Target.cs emits the
  C arrays + global assignment for CoreCLR. The merged json path is passed to
  the linker via RuntimeConfigurationFilePath.
- msbuild: for CoreCLR skip RuntimeConfigParserTask and don't ship/merge
  runtimeconfig.bin; hand the merged json to the linker and leave
  xamarin_runtime_configuration_name NULL.
- tests: new RuntimeConfigurationTest (property baked into the generated main,
  no runtimeconfig.bin for CoreCLR), gate the BundleStructureTest expectation,
  and drop runtimeconfig.bin from the CoreCLR app-size expectation files.

Fixes #26334

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
NativeAOT never reads runtimeconfig.bin at runtime: the only reader is
monovm-bridge.m (compiled only when CORECLR_RUNTIME is not defined) and
xamarin_bridge_compute_properties (only called from xamarin_bridge_vm_initialize,
which is #if !defined(NATIVEAOT)). NativeAOT builds are compiled with
-DCORECLR_RUNTIME -DNATIVEAOT, so neither applies - the runtime configuration is
embedded into the executable by the ILC compiler at publish time instead.

So only MonoVM actually needs the binary runtimeconfig format. Change the gating
from '!= CoreCLR' to '== MonoVM' so NativeAOT, like CoreCLR, no longer produces
or ships runtimeconfig.bin. Drop it from the NativeAOT app-size expectation files.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the postfix '!' null-forgiving operator (banned by repo rules) with
direct null-narrowing checks in Target.cs and a null-coalescing fallback in
GenerateMainStep.cs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81ba6c1d-1061-43f4-8064-c81f5a181e2f
Copilot AI review requested due to automatic review settings July 28, 2026 16:18

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 removes the need to generate/ship/decode runtimeconfig.bin for CoreCLR (and avoids shipping it for NativeAOT), by baking runtimeOptions.configProperties into the generated main.*.mm as compiled-in C arrays and exposing them to the CoreCLR bridge via new xamarin_runtime_config_property_* globals.

Changes:

  • Linker reads merged runtimeconfig.merged.json and stores configProperties on the Application model for CoreCLR, rejecting reserved keys/unsupported value kinds.
  • Main generator emits static const char* arrays for runtimeconfig property keys/values and assigns them to new runtime globals during xamarin_setup_impl.
  • Runtime CoreCLR bridge now builds the coreclr_initialize property arrays from the baked-in globals (no mmap/decode), and MSBuild/tests stop expecting/shipping runtimeconfig.bin except for MonoVM.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/dotnet-linker/Steps/GenerateMainStep.cs Parses merged runtimeconfig JSON for CoreCLR and populates Application.RuntimeConfigProperties; enforces reserved keys/unsupported kinds.
tools/dotnet-linker/LinkerConfiguration.cs Adds RuntimeConfigurationFilePath passthrough from MSBuild to the linker.
tools/dotnet-linker/Compat.cs Adds Application.RuntimeConfigProperties storage for CoreCLR main generation.
tools/common/Target.cs Emits C arrays for runtimeconfig properties into generated main.*.mm and assigns new runtime globals.
runtime/xamarin/main.h Declares new xamarin_runtime_config_property_* globals.
runtime/runtime.m Defines new runtimeconfig property globals (assigned by generated main).
runtime/coreclr-bridge.m Replaces runtimeconfig.bin mmap/decode path with copying from baked-in globals.
dotnet/targets/Xamarin.Shared.Sdk.targets Gates runtimeconfig.bin generation/shipping to MonoVM; passes merged JSON path to linker for CoreCLR.
tests/dotnet/UnitTests/RuntimeConfigurationTest.cs New unit test verifying CoreCLR properties are baked into generated main and no runtimeconfig.bin is shipped.
tests/dotnet/UnitTests/BundleStructureTest.cs Updates expected bundle contents: CoreCLR no longer ships runtimeconfig.bin.
tests/dotnet/UnitTests/expected/-NativeAOT-size.txt Updates size baselines to reflect runtimeconfig.bin no longer being shipped for NativeAOT.
tests/dotnet/UnitTests/expected/-CoreCLR-size.txt Updates size baselines to reflect runtimeconfig.bin no longer being shipped for CoreCLR.

Comment thread tools/dotnet-linker/Steps/GenerateMainStep.cs Outdated
Comment thread tools/common/Target.cs
- Emit the runtimeconfig C arrays sorted by key so the generated main is
  deterministic regardless of the dictionary's enumeration order.
- Fail the build (error 2323) when 'runtimeOptions.configProperties' is present
  but isn't a JSON object, instead of silently ignoring the configuration.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 81ba6c1d-1061-43f4-8064-c81f5a181e2f
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 9d7a954396af1d8496612756fcd070943ac18413 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #9d7a954] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 203 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. [attempt 2] Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 19 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 18 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 19 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 19 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 9d7a954396af1d8496612756fcd070943ac18413 [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[msbuild] Generate C code for the runtimeconfig properties instead of the binary runtimeconfig format (CoreCLR)

3 participants