[msbuild] Generate C code for runtimeconfig properties (CoreCLR). Fixes #26334 - #26335
[msbuild] Generate C code for runtimeconfig properties (CoreCLR). Fixes #26334#26335rolfbjarne wants to merge 7 commits into
Conversation
We bake the runtime configuration directly into the app and hand it to the runtime, bypassing hostfxr. hostfxr is what would normally merge the companion '*.runtimeconfig.dev.json' file (where the .NET SDK writes Debug-only switches such as Hot Reload's System.StartupHookProvider.IsSupported and System.Reflection.Metadata.MetadataUpdater.IsSupported) into the main runtime configuration, so those switches never reached the runtime. Add a new MergeRuntimeConfigFiles MSBuild task that overlays the dev file's 'runtimeOptions.configProperties' on top of the main file's (dev wins, matching hostfxr), and feed the merged file to the existing RuntimeConfigParserTask. Fixes #26330 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…, DeepClone. Address Copilot review feedback on MergeRuntimeConfigFiles: - Remove the banned null-forgiving (!) operator; use explicit null/length checks (netstandard2.0's string.IsNullOrEmpty isn't null-annotated). - Catch read/parse failures and report them as an MSBuild error (E7186) instead of letting the task crash. - Clone dev values with JsonNode.DeepClone () instead of serialize+parse. - Add a regression test for the invalid-JSON error path. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…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
There was a problem hiding this comment.
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.jsonand storesconfigPropertieson theApplicationmodel 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 duringxamarin_setup_impl. - Runtime CoreCLR bridge now builds the
coreclr_initializeproperty arrays from the baked-in globals (nommap/decode), and MSBuild/tests stop expecting/shippingruntimeconfig.binexcept 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. |
- 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
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…msbuild-generate-c-code-for-the-runtime-6e7ef8 # Conflicts: # dotnet/targets/Xamarin.Shared.Sdk.targets # msbuild/Xamarin.MacDev.Tasks/Tasks/MergeRuntimeConfigFiles.cs # tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt # tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-size.txt # tools/common/Target.cs # tools/dotnet-linker/Steps/GenerateMainStep.cs
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
🔥 [CI Build #78b8eca] Test results 🔥Test results❌ Tests failed on VSTS: test results 0 tests crashed, 1 tests failed, 204 tests passed. Failures❌ dotnettests tests (macOS)1 tests failed, 0 tests passed.Failed tests
Html Report (VSDrops) Download Successes✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
|
For CoreCLR-based apps we currently produce the binary
runtimeconfig.bin, ship it in the app bundle, thenmmapand decode it at startup to feed theconfigPropertiesintocoreclr_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
configPropertiesdirectly into the app as compiled-in C arrays (emitted into the generatedmain.mmand assigned to newxamarin_runtime_config_property_*globals in libxamarin).xamarin_bridge_compute_propertiesnow reads those globals instead of locating, mmapping and decodingruntimeconfig.bin, and the mobile-runtimeconfig decode helpers are removed.Approach
xamarin_runtime_config_property_count/keys/valuesglobals inruntime.m(assigned from the app's generated main, same pattern asxamarin_runtime_configuration_name), and rewritexamarin_bridge_compute_propertiesincoreclr-bridge.mto copy from them.GenerateMainStepparsesruntimeOptions.configPropertiesfrom the merged runtimeconfig.json for CoreCLR (matching the value stringification done by dotnet/runtime'sRuntimeConfigParserTask), rejects reserved properties (error 2322) and unsupported value kinds (error 2321), andTarget.csemits the C arrays plus the global assignment inxamarin_setup_impl.runtimeconfig.bin, so it stops shipping the unused file too.MonoVM is unchanged: it still needs the blob for
monovm_runtimeconfig_initialize.Notes
dev/rolf/runtimeconfig-dev-json); review that one first.Fixes: #26334
🤖 Pull request created by Copilot