Update GenerateRuntimeConfigurationFiles task to generate Hot Reload runtime options - #53715
Conversation
|
Due to lack of recent activity, this PR has been labeled as 'Stale'. It will be closed if no further activity occurs within 7 more days. Any new comment will remove the label. |
0036777 to
1a70afa
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the SDK’s runtimeconfig generation pipeline so runtimeconfig.dev.json can be generated for Hot Reload runtime switches (in addition to the existing probing-paths behavior), aligning with the Hot Reload runtime options requirements described in dotnet/runtime#126606.
Changes:
- Split
GenerateRuntimeConfigurationFilesdev-config generation into two independent switches: probing paths vs Hot Reload runtime options. - Update
Microsoft.NET.Sdk.targetsto computeGenerateRuntimeConfigDevFilebased on the new switches and pass the new parameters to the task. - Add unit tests validating
runtimeconfig.dev.jsoncontents for Hot Reload-only, probing-paths-only, both enabled, and both disabled scenarios.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| test/Microsoft.NET.Build.Tasks.Tests/GivenAGenerateRuntimeConfigMultiThreading.cs | Adds coverage for Hot Reload runtime options emission into runtimeconfig.dev.json under different switch combinations. |
| src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets | Introduces new MSBuild properties for dev-config generation and wires them into the GenerateRuntimeConfigurationFiles task invocation. |
| src/Tasks/Microsoft.NET.Build.Tasks/GenerateRuntimeConfigurationFiles.cs | Implements Hot Reload runtime switch emission into runtimeconfig.dev.json and gates probing-path generation behind a dedicated switch. |
c56c492 to
3f6c162
Compare
87a437a to
28f6636
Compare
0d022a1 to
8c817a5
Compare
…runtime options to runtimeconfig.dev.json Update dotnet-watch to recognize the new setting.
8c817a5 to
0a61b66
Compare
|
@DustinCampbell @baronfel ptal |
|
@tmat does this mean that hot reload now uses a "special" build and you might need to rebuild to run hot reload? (or that the build is always "hot reload" enabled). |
No, it's not a special build. The regular |
|
I think we will need to start loading the cc @maraf Maybe Android too |
@pavelsavara Do you mean that if the WASM targets aren't loading it in .NET 11, will something break? |
Historically, we were converting I have not make detailed research, I could be wrong. |
There are two switches: After this change is merged So, ideally WASM targets will get updated to consider |
|
@pavelsavara Filed: dotnet/runtime#130823 If a fix does not make it to .NET 11 I'll add a workaround to dotnet-watch to ignore |
Is this going to be necessary for Net10 browser after the SDK was upgraded ? |
|
It is not; projects that target SDKs < v11 are already handled differently. |
Context: dotnet/sdk#53715 Starting with `11.0.100-preview.7.26376.106`, the .NET SDK emits a `<App>.runtimeconfig.dev.json` file for `Debug` builds containing the Hot Reload feature switches: { "runtimeOptions": { "configProperties": { "System.Reflection.Metadata.MetadataUpdater.IsSupported": true, "System.StartupHookProvider.IsSupported": true } } } `hostfxr` layers this file on top of `*.runtimeconfig.json` at startup, but .NET for Android does not use `hostfxr`: it bakes the runtime properties into the application at build time. So the file was simply ignored, and the switches never reached the app. Do the same layering at build time for CoreCLR: read the dev file after `*.runtimeconfig.json` in `RuntimePropertiesParser`, so its `configProperties` win. This matches what Blazor WebAssembly does in dotnet/runtime#130825. This does not conflict with the switches we set ourselves. `$(StartupHookSupport)` is only set to `false` when `'$(Optimize)' == 'true'`, and the SDK only generates the dev file for `Debug` builds, so the two are disjoint in practice. We never set `$(MetadataUpdaterSupport)`. Mono is unchanged: it reads runtime properties from the `rc.bin` blob produced by `RuntimeConfigParserTask`, which only accepts a single input file. Teaching that task about multiple files requires a change in dotnet/runtime. While here, add both `runtimeconfig` files to `_GetGeneratePackageManagerJavaInputs`. Neither was an input before, so editing them would not trigger a rebuild. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b158ad70-1e5e-44cd-a1f2-60353f3bb560
Changes: dotnet/dotnet@cb8306a...283ef97 - **Dependency Updates**: - From [11.0.0-beta.26365.101 to 11.0.0-beta.26378.119][3] - Microsoft.DotNet.Arcade.Sdk - Microsoft.DotNet.Build.Tasks.Feed - From [0.11.5-preview.26365.101 to 0.11.5-preview.26378.119][3] - Microsoft.DotNet.Cecil - From [11.0.0-preview.7.26365.101 to 11.0.0-preview.7.26378.119][3] - Microsoft.NET.ILLink - Microsoft.NETCore.App.Ref - From [11.0.100-preview.7.26365.101 to 11.0.100-preview.7.26378.119][3] - Microsoft.NET.Sdk - Microsoft.TemplateEngine.Authoring.Tasks [3]: dotnet/dotnet@cb8306a...283ef97 ### Apply `*.runtimeconfig.dev.json` to CoreCLR apps Context: dotnet/sdk#53715 Starting with `11.0.100-preview.7.26376.106`, the .NET SDK emits a `<App>.runtimeconfig.dev.json` file for `Debug` builds containing the Hot Reload feature switches: { "runtimeOptions": { "configProperties": { "System.Reflection.Metadata.MetadataUpdater.IsSupported": true, "System.StartupHookProvider.IsSupported": true } } } `hostfxr` layers this file on top of `*.runtimeconfig.json` at startup, but .NET for Android does not use `hostfxr`: it bakes the runtime properties into the application at build time. So the file was simply ignored, and the switches never reached the app. Do the same layering at build time for CoreCLR: read the dev file after `*.runtimeconfig.json` in `RuntimePropertiesParser`, so its `configProperties` win. This matches what Blazor WebAssembly does in dotnet/runtime#130825. This does not conflict with the switches we set ourselves. `$(StartupHookSupport)` is only set to `false` when `'$(Optimize)' == 'true'`, and the SDK only generates the dev file for `Debug` builds, so the two are disjoint in practice. We never set `$(MetadataUpdaterSupport)`. Mono is unchanged: it reads runtime properties from the `rc.bin` blob produced by `RuntimeConfigParserTask`, which only accepts a single input file. Teaching that task about multiple files requires a change in dotnet/runtime. While here, add both `runtimeconfig` files to `_GetGeneratePackageManagerJavaInputs`. Neither was an input before, so editing them would not trigger a rebuild. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b158ad70-1e5e-44cd-a1f2-60353f3bb560 ### Ignore `DotNetNewAndroidTest` for `dotnet test` Context: #12254 Starting with .NET SDK `11.0.100-preview.7.26376.106`, `dotnet test` is device-aware: it selects a device with `ComputeAvailableDevices`, then deploys with `DeployToDevice` and computes the launch command with `ComputeRunArguments`. Those are separate `ProjectInstance.Build ()` calls against the same `ProjectInstance`, so `ProcessFrameworkReferences` runs twice. MSBuild task outputs append, so `@(ResolvedRuntimePack)` ends up with two `Microsoft.NETCore.App` entries and `ResolveFrameworkReferences` throws: error MSB4018: The "ResolveFrameworkReferences" task failed unexpectedly. System.ArgumentException: An item with the same key has already been added. Key: Microsoft.NETCore.App This reproduces with a stock SDK and the released `Microsoft.Android.Sdk.Windows` `37.0.0-preview.6.59`, so it is not caused by anything in this repo. Pinning a single `$(RuntimeIdentifier)` does not help, and `dotnet run` works on the same project, so there is nothing we can do from our targets. Ignore the `dotnet test` cases until the fix flows back from dotnet/sdk. The `dotnet run` case is unaffected and stays enabled. ### [ci] Work around broken `dotnet test` by using `dotnet run` `dotnet test` currently fails to deploy to a device, so every APK instrumentation lane fails with "Deployment to device failed. Fix any deployment errors and run again." See #12254. Drive the instrumentation with `dotnet run` instead. We do not lose the test report: the on-device runner writes its own TRX and reports the location back through the instrumentation bundle as `INSTRUMENTATION_RESULT: resultsPath=<device path>`. `dotnet run` invokes `adb shell am instrument -w`, which prints that bundle, so the path can be scraped and the TRX pulled to where `PublishTestResults` expects it. No product code changes; revert to `dotnet test` once the SDK fix lands. Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Context: dotnet/sdk#53715 Port of #12249 (which targets `release/11.0.1xx-preview7`) to `main`. Starting with `11.0.100-preview.7.26376.106`, the .NET SDK emits a `<App>.runtimeconfig.dev.json` file for `Debug` builds containing the Hot Reload feature switches: ```json { "runtimeOptions": { "configProperties": { "System.Reflection.Metadata.MetadataUpdater.IsSupported": true, "System.StartupHookProvider.IsSupported": true } } } ``` `hostfxr` layers this file on top of `*.runtimeconfig.json` at startup, but .NET for Android does not use `hostfxr`: it bakes the runtime properties into the application at build time. So the file was simply ignored, and the switches never reached the app. Do the same layering at build time for CoreCLR: read the dev file after `*.runtimeconfig.json` in `RuntimePropertiesParser`, so its `configProperties` win. This matches what Blazor WebAssembly does in dotnet/runtime#130825. This does not conflict with the switches we set ourselves. `$(StartupHookSupport)` is only set to `false` when `'$(Optimize)' == 'true'`, and the SDK only generates the dev file for `Debug` builds, so the two are disjoint in practice. We never set `$(MetadataUpdaterSupport)`. Mono is unchanged: it reads runtime properties from the `rc.bin` blob produced by `RuntimeConfigParserTask`, which only accepts a single input file. Teaching that task about multiple files requires a change in dotnet/runtime. While here, add both `runtimeconfig` files to `_GetGeneratePackageManagerJavaInputs`. Neither was an input before, so editing them would not trigger a rebuild. ## Differences from #12249 The SDK `main` currently builds against does not yet emit the dev file. `Microsoft.NET.Sdk.targets` turns it off for every modern TFM: ```xml <GenerateRuntimeConfigDevFile Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0'))">false</GenerateRuntimeConfigDevFile> ``` That condition is "6.0 or newer", so it applies to our `net11.0-android` projects. With `$(GenerateRuntimeConfigDevFile)` false the SDK neither writes the file nor gives `$(ProjectRuntimeConfigDevFilePath)` a default. dotnet/sdk#53715 is what flips this back on. Two adjustments follow: * The new `RuntimeConfigDevJsonIsApplied` device test writes the dev file and sets `$(ProjectRuntimeConfigDevFilePath)` itself. Both can be dropped once `main` picks up the newer SDK. * The `expectedFiles.Add ($"{proj.ProjectName}.runtimeconfig.dev.json")` assertion that #12249 adds to `BuildTest.DotNetBuild` is **not** ported, since it would fail on the current SDK. It should be added when `main` gets the newer SDK. ## Additional fix beyond #12249 `AddConfigProperties` originally used `GetProperty ("configProperties")` for the base file, which throws `KeyNotFoundException` when the key is absent. Both files now use `TryGetProperty`, matching `hostfxr`. Covered by the new `ConfigWithoutConfigPropertiesStillGetsDevProperties` test. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Update
GenerateRuntimeConfigurationFilestask to generate Hot Reload runtime options toruntimeconfig.dev.jsonifEnableHotReloadInRuntimeConfigDevFileproperty is set. The property is set totrueby default inDebugconfiguration.The goal is to enable Hot Reload runtime switches in all Debug builds even if the project publishes AOT binaries.
We do so by generating
runtimeconfig.dev.json, which overrides settings specified inruntimeconfig.json. The latter gets published while the former is only used for local development, thus the value of runtime switches of the published app can be different (Hot Reload disabled) than for dev builds (Hot Reload enabled).This approach used to be blocked by dotnet/runtime#126606, which was recently fixed via
dotnet/runtime#128383. If the project targets .NET 10 or older the
runtimeconfig.dev.jsonsettings won't overrideruntimeconfig.json. We generate the dev.json file regardless as there is no harm to do so and it keeps the logic simpler.See also discussion on dotnet/runtime#126546
Additionally, enable Hot Reload in dontet-watch when
runtimeconfig.dev.jsonis generated with Hot Reload settings.UPDATE: PR dotnet/runtime#130825 updates WASM build targets to apply
runtimeconfig.dev.json.