[net11.0] Move feature switch RHCO items to static evaluation to fix IL3050 on Android NativeAOT#35134
[net11.0] Move feature switch RHCO items to static evaluation to fix IL3050 on Android NativeAOT#35134
Conversation
Move PropertyGroup defaults and RuntimeHostConfigurationOption items out of _MauiPrepareForILLink (a target) into static PropertyGroup/ItemGroup blocks that are evaluated at import time. This ensures RHCO items are visible before any MSBuild targets run, so _PrepareTrimConfiguration can snapshot them into _TrimmerFeatureSettings for both ILLink and ILC. Previously these were added in _MauiPrepareForILLink (BeforeTargets= "PrepareForILLink"), but runtime PR dotnet/runtime#124801 moved the RHCO → _TrimmerFeatureSettings conversion to an earlier target (_PrepareTrimConfiguration), causing MAUI's feature switches to be missed by ILC on Android NativeAOT. The property conditions (PublishAot/TrimMode) are static project properties available at evaluation time, so there is no need for these to run inside a target. The Warning task for MA002 remains in _MauiPrepareForILLink since MSBuild tasks require a target context. Fixes dotnet/runtime#127017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Assisted-by: Claude:claude-opus-4.6-1m
Capture the user-specified _EnableMauiAspire value into a sentinel property (_EnableMauiAspireUserOverride) before setting the default. The MA002 warning now checks the sentinel instead of _EnableMauiAspire itself, so it only fires when the user explicitly set the property. Previously the Warning ran inside a target before _EnableMauiAspire was set, so checking '!= empty' correctly detected user overrides. Now that _EnableMauiAspire is set statically, MAUI always populates it, so the sentinel is needed to distinguish user vs MAUI values. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Assisted-by: Claude:claude-opus-4.6-1m
|
🚀 Dogfood this PR with:
curl -fsSL https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35134Or
iex "& { $(irm https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35134" |
There was a problem hiding this comment.
Pull request overview
Moves MAUI feature switch defaults and RuntimeHostConfigurationOption items to MSBuild evaluation-time so the runtime’s earlier trim configuration snapshot (_PrepareTrimConfiguration) can pick them up, fixing missing --feature flags in Android NativeAOT scenarios.
Changes:
- Relocates feature-switch property defaults and
RuntimeHostConfigurationOptionitems out of_MauiPrepareForILLinkinto staticPropertyGroup/ItemGroupblocks. - Adds
_EnableMauiAspireUserOverrideto preserve the ability to warn only on user overrides after defaults moved to evaluation time. - Keeps MA002 warning emission in
_MauiPrepareForILLink(target context).
| evaluation time, before _PrepareTrimConfiguration snapshots RHCO items into | ||
| _TrimmerFeatureSettings. Previously these lived inside _MauiPrepareForILLink | ||
| (BeforeTargets="PrepareForILLink"), but that fires after _PrepareTrimConfiguration | ||
| runs, so ILC never received - -feature flags for MAUI switches on Android NativeAOT. |
There was a problem hiding this comment.
The comment says "ILC never received - -feature flags". This looks like a typo; it should be "--feature" (double hyphen) to match the actual ILC option name.
| runs, so ILC never received - -feature flags for MAUI switches on Android NativeAOT. | |
| runs, so ILC never received --feature flags for MAUI switches on Android NativeAOT. |
| <!-- Capture user-specified value before setting the default, so the MA002 | ||
| warning can detect external overrides. --> | ||
| <_EnableMauiAspireUserOverride>$(_EnableMauiAspire)</_EnableMauiAspireUserOverride> | ||
| <!-- Set _EnableMauiAspire based on whether optimizations are enabled when not already set --> | ||
| <_EnableMauiAspire Condition="'$(_EnableMauiAspire)' == '' and '$(Optimize)' != 'true'">true</_EnableMauiAspire> | ||
| <_EnableMauiAspire Condition="'$(_EnableMauiAspire)' == ''">false</_EnableMauiAspire> |
There was a problem hiding this comment.
_EnableMauiAspireUserOverride is only captured when PublishAot is true or TrimMode is full. If a user sets _EnableMauiAspire manually in an optimized build without those settings, MA002 will no longer trigger (the warning condition now checks only _EnableMauiAspireUserOverride). Consider capturing _EnableMauiAspireUserOverride unconditionally (e.g., in a separate PropertyGroup before any defaults are applied, and guarded so it doesn't overwrite) so the warning continues to detect external overrides in all optimized builds.
MauiCssEnabled's condition uses '@(MauiCss->Count())' which is an item list reference not allowed in static PropertyGroup conditions (MSB4099). Move it and its RHCO item back into _MauiPrepareForILLink. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Assisted-by: Claude:claude-opus-4.6-1m
| <RuntimeHostConfigurationOption Include="Microsoft.Maui.RuntimeFeature.IsCssEnabled" | ||
| Condition="'$(MauiCssEnabled)' != ''" | ||
| Value="$(MauiCssEnabled)" | ||
| Trim="true" /> |
There was a problem hiding this comment.
Why isn't this one moved too? Is it because MauiCssEnabled is evaluated later based on the presence of any @(MauiCss) items?
There was a problem hiding this comment.
<!-- MauiCssEnabled depends on @(MauiCss) item list which cannot be evaluated
in a static PropertyGroup condition (MSB4099). -->I overlooked this comment.
Won't this cause the same issues which were caused by placing the other RHCO inside of the target? Could it happen that this feature switch is set too late due to some unexpected targets ordering?
Replace the @(MauiCss->Count()) item list check with a property-based condition on EnableDefaultCssItems. MSBuild does not allow @() item references in static PropertyGroup conditions (MSB4099). When EnableDefaultCssItems is not 'true', no CSS glob runs, so MauiCssEnabled defaults to false. When it is 'true', MauiCssEnabled stays unset (CSS enabled by default) regardless of whether CSS files exist on disk — the CSS code paths are present but never invoked if no stylesheets are loaded, so there is no runtime behavior change. This empties _MauiPrepareForILLink of all property/item logic, leaving only the MA002 Warning task which requires a target context. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Assisted-by: Claude:claude-opus-4.6-1m
Note
This PR was created with assistance from AI.
Summary
Move
RuntimeHostConfigurationOptionitems and their property defaults out of the_MauiPrepareForILLinktarget into staticPropertyGroup/ItemGroupblocks evaluated at import time. This requires no runtime changes.Problem
dotnet/runtime#124801 moved the
RuntimeHostConfigurationOption→_TrimmerFeatureSettingsconversion fromPrepareForILLinkinto an earlier internal target (_PrepareTrimConfiguration). MAUI's_MauiPrepareForILLinkhooksBeforeTargets="PrepareForILLink", which fires after the snapshot. ILC never receives--featureflags for MAUI's switches on Android NativeAOT, causing spurious IL3050 warnings forHybridWebViewHandler.Fix
The property conditions (
PublishAot,TrimMode,Optimize) are all static project properties available at evaluation time — there's no reason for these to be set inside a target. Moving them to static blocks makes them visible before any targets run, so_PrepareTrimConfigurationpicks them up regardless of target ordering.A sentinel property (
_EnableMauiAspireUserOverride) captures the user-specified_EnableMauiAspirevalue before the default is set, so the MA002 warning correctly detects external overrides without false positives from MAUI's own default.The
Warningtask (MA002 Aspire validation) remains in_MauiPrepareForILLinksince MSBuild tasks require a target context.This approach requires no runtime changes.
Verified
Tested locally with an Android NativeAOT MAUI app:
--feature:Microsoft.Maui.RuntimeFeature.IsHybridWebViewSupported=falsemissing from ILC rsp → IL3050--featureflag present → IL3050 suppressed by FeatureGuardFixes dotnet/runtime#127017
cc @sbomer @simonrozsival @MichalStrehovsky