-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Trimming] Add a feature flag to disable XAML loading at runtime #19310
Conversation
src/Workload/Microsoft.Maui.Sdk/Sdk/Microsoft.Maui.Sdk.Before.targets
Outdated
Show resolved
Hide resolved
src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs
Outdated
Show resolved
Hide resolved
Oh thinking about it more, should |
@@ -6,4 +6,6 @@ class TrimmerConstants | |||
internal const string SerializerTrimmerWarning = "Data Contract Serialization and Deserialization might require types that cannot be statically analyzed. Make sure all of the required types are preserved."; | |||
|
|||
internal const string NativeBindingService = "This method properly handles missing properties, and there is not a way to preserve them from this method."; | |||
|
|||
internal const string XamlLoadingTrimmerWarning = "Loading XAML at runtime might require types that cannot be statically analyzed. Make sure all of the required types are preserved."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will I get this warning in an app which doesn't call any of the affected public APIs, but if I just enable the feature switch?
If so, then this should mention the feature switch and how to disable it (as that's the way to "fix" this).
Or maybe a better way to put it - I create an app, and enable this feature. Then I AOT the app. Is there any case where the behavior of the app would change after AOT in this case? Especially is there a way to hit one of the new exceptions? If the answer is yes, then we should make it to produce a warning. We do this for example for startup hooks - if you enable startup hooks, you will get trim warning. It may be that at runtime you don't run startup hooks and so you never hit the problem - but we "play it safe" and produce a warning regardless.
I would expect similar behavior here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also a good idea to add the Url
property to the RUC so that we have a way to direct users to a longer and much more detailed description of the problem and how to solve it. In this case one such solution would be to discuss XamlC for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will I get this warning in an app which doesn't call any of the affected public APIs, but if I just enable the feature switch?
No, this warning will only show up in apps that call .LoadFromXaml(...)
explicitly.
It's also a good idea to add the Url property to the RUC so that we have a way to direct users to a longer and much more detailed description of the problem and how to solve it.
I think we'll need to revisit this later. We currently don't have any documentation or guidelines that we could point to.
{ | ||
if (!FeatureFlags.IsXamlLoadingEnabled) | ||
{ | ||
throw new InvalidOperationException($"The resource '{resourcePath}' has not been compiled using XamlC. " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like the place which should produce a warning if the feature is enabled. Note that RUC warnings (IL2026
) have a special behavior and they're not part of the "singlewarn" behavior - so the user should see the actual message, and not just "MAUI has trimming problems". This behavior was specifically designed for cases like this.
@jonathanpeppers the RUC attribute cannot be applied to enum values (it's just for classes, methods, and constructors). Could we produce these warnings whenever XamlC runs into one of these attributes? One similar scenario: We should probably emit warning when |
Ok, yeah it kind of makes sense you can't put ILLink attributes on an enum. It's only because we have a custom MSBuild task that rewrites IL -- that makes this even possible. So, I think we could manually warn in a couple places: maui/src/Controls/src/Build.Tasks/XamlCTask.cs Lines 87 to 88 in 7acd5c2
maui/src/Controls/src/Build.Tasks/XamlCTask.cs Lines 102 to 103 in 7acd5c2
maui/src/Controls/src/Build.Tasks/XamlCTask.cs Lines 132 to 133 in 7acd5c2
I think we could pass in the MSBuild property to this task to know if the new feature flag is enabled. It might should even be an error? |
This has been discussed several times in the past, but it's difficult. In IL enums look like ints ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I reran some lanes and things look green now.
@@ -21,4 +21,14 @@ | |||
<_MauiUsingDefaultRuntimeIdentifier>true</_MauiUsingDefaultRuntimeIdentifier> | |||
</PropertyGroup> | |||
|
|||
<!-- Feature switches --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a lot of xaml-related things in here, so maybe this should be defined here too?
Line 136 in c1dfd70
<!-- XamlC --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if that is the right place to put the feature flag defaults. This feature flag is related to XAML but I think there will be more feature switches that aren't related to it.
But I can definitely imagine moving this to a separate .targets
file with a target that sets up the feature switches before the RunILLink
target runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@simonrozsival do you know offhand if any of the trimmer warnings so far are from Microsoft.Maui.dll
/ Core.csproj
, or are they all from Microsoft.Maui.Controls.dll
& Microsoft.Maui.Controls.Xaml.dll
?
It might make sense to put the trimmer switches in "Controls", as it is possible to create an app that uses parts of MAUI and not Microsoft.Maui.Controls.dll
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warnings we're getting are mostly from Microsoft.Maui.Controls.dll
, but for example the DI related ones are in Microsoft.Maui.dll
(for example the MauiFactory related code). Yesterday we talked about putting the existing reflection-based image source service resolution code behind a feature flag. Wouldn't we need a new separate setup with a separate ILLink.Subsitutions.xml to introduce that feature flag if we moved this feature flag from Core into Controls?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think another reason to move from src/Workload/Microsoft.Maui.Sdk/Sdk/Microsoft.Maui.Sdk.Before.targets
, is this file is in the workload, and wouldn't be able to be updated independently with $(MauiVersion)
or the PackageReference
in the project template.
@mattleibow is there a .targets
file that would also include a way for feature flags to exist in Core/Microsoft.Maui.dll
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I can move the code to Microsoft.Maui.Controls.targets
. Even with the code in that targets file, we can still define IL substitutions for the RuntimeFeature
class which will stay in Core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's the way to go for now, I was looking in:
"C:\Program Files\dotnet\library-packs\Microsoft.Maui.Controls.Core.8.0.3.nupkg"
And there are no .targets
files in there currently.
06717be
06717be
to
bf76c49
Compare
@simonrozsival as you noticed locally, template tests are also failing on CI with:
this is due to a new version of This was already done on
|
The general problem here happens if MSBuild changes the |
There are still some failing tests, but they don't seem unique to this PR, and I can see the same failures in other CI runs. |
Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
7a2e8f4
to
abb35ee
Compare
Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com>
/rebase |
If this is green, I think we are OK to merge: I am testing how green CI is, in general, at: |
Agreed. FWIW, the last tip of
|
Description of Change
This PR adds a feature flag that allows developers to disable XAML loading at runtime. This is useful when XAML files are compiled using XamlC and the
LoadFromXaml
andXamlLoader
code is never used anyway. The file size savings I'm seeing with NativeAOT on iOS with the feature disabled is 5.1% (378 kB).Moreover, the XAML loading code is not trimming-friendly. The XAML document can reference arbitrary types and the static analysis cannot find them. For this reason, the feature should be disabled by default for NativeAOT apps.
Discussion points:
XamlLoadingIsEnabled
->MauiXamlRuntimeParsingSupport
FeatureFlags.IsXamlLoadingEnabled
->Microsoft.Maui.RuntimeFeature.IsXamlRuntimeParsingSupported
How to handleResourceDictionary.SetAndLoadSource
? The current implementation assumes that XamlC will compile all resource dictionaries and add the correct[XamlResourceId]
attributes so the codepath that throws exception is never hit. On the other hand, it breaks the principle that whenever there is a call to a method that can throw because the feature is disabled should produce a build time warning. After examining the code inSetAndLoadSource
and the code in XamlC that generates the call I wonder if we could avoid calling the method altogether and instead instantiate the generated resource dictionary directly. Is there a specific reason why we're not doing it, or is that something that wasn't worth implementing yet?Does it make sense to annotateIResourcesLoader
since it is an internal interface? I am a little confused why we have the interface in the first place and why we use it to accessResourceLoader
through DI in the first place. Could this setup be simplified?/cc @jonathanpeppers @StephaneDelcroix @mdh1418 @ivanpovazan @vitek-karas
Issues Fixed
Contributes to #18658 and #19397
Once this change is merged it should decrease the number of warnings tracked by the test that should be introduced by #19194
NativeAOT on iOS