Skip to content
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

[net10.0] Aggressive attribute trimming breaks NativeAOT builds #22065

Open
simonrozsival opened this issue Jan 28, 2025 · 4 comments · May be fixed by #22151
Open

[net10.0] Aggressive attribute trimming breaks NativeAOT builds #22065

simonrozsival opened this issue Jan 28, 2025 · 4 comments · May be fixed by #22151
Assignees
Labels
bug If an issue is a bug or a pull request a bug fix
Milestone

Comments

@simonrozsival
Copy link
Contributor

simonrozsival commented Jan 28, 2025

Apple platform

Mac Catalyst, iOS

Framework version

net10.0-*

Affected platform version

.NET 10 P1

Description

The recent addition of the switch/build property MobileAggressiveAttributeTrimming which enables aggressive attribute trimming in .NET 10 (#21314) causes problems with NativeAOT builds. This problem surfaced in dotnet/maui#27103

When the feature switch is enabled (the default behavior), ILLink removes all [DynamicallyAccessedMembers] and when ILC builds a NativeAOT binary, it cannot see these annotations anymore and it produces trim warnings and the final binary most likely won't work as expected.

I see two possible fixes:

  • Disable MobileAggressiveAttributeTrimming for NativeAOT builds and let ILC trim unnecessary attributes
  • Remove DynamicallyAccessedMembersAttribute from TrimAttributes.LinkDescription.xml.
    • My hunch is that this will reveal other problems, because the NativeAOT compiler uses other attributes from the System.Diagnostics.CodeAnalysis namespace for static analysis of the program, such as the FeatureGuardAttribute.

/cc @rolfbjarne @jonathanpeppers @sbomer

Steps to Reproduce

  1. Create a new MAUI project
  2. Add <PublishAot Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">true</PublishAot> to the project file
  3. Build the project with a local build of .NET MAUI from the net10.0 branch with this command:
    $(MAUI_DIR)/dotnet-local.sh publish -f net10.0-maccatalyst -r maccatalyst-arm64 -p:TrimmerSingleWarn=false

Did you find any workaround?

Set $(MobileAggressiveAttributeTrimming)=false in the MAUI project.

Build logs

 TestApp net10.0-maccatalyst succeeded with 18 warning(s) (37.4s) → bin/Release/net10.0-maccatalyst/maccatalyst-arm64/TestApp.dll
    /.../Projects/dotnet/maui/src/Controls/src/Core/BindableProperty.cs(93): Trim analysis warning IL2067: Microsoft.Maui.Controls.BindableProperty.BindableProperty(String,Type,Type,Object,BindingMode,BindableProperty.ValidateValueDelegate,BindableProperty.BindingPropertyChangedDelegate,BindableProperty.BindingPropertyChangingDelegate,BindableProperty.CoerceValueDelegate,BindableProperty.BindablePropertyBindingChanging,Boolean,BindableProperty.CreateDefaultValueDelegate): 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The parameter '#1' of method 'Microsoft.Maui.Controls.BindableProperty.BindableProperty(String,Type,Type,Object,BindingMode,BindableProperty.ValidateValueDelegate,BindableProperty.BindingPropertyChangedDelegate,BindableProperty.BindingPropertyChangingDelegate,BindableProperty.CoerceValueDelegate,BindableProperty.BindablePropertyBindingChanging,Boolean,BindableProperty.CreateDefaultValueDelegate)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    ILC : Trim analysis warning IL2070: Microsoft.Extensions.DependencyInjection.ActivatorUtilities.TryFindMatchingConstructor(Type,Type[],ConstructorInfo&,Nullable`1<Int32>[]&): 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructors()'. The parameter '#0' of method 'Microsoft.Extensions.DependencyInjection.ActivatorUtilities.TryFindMatchingConstructor(Type,Type[],ConstructorInfo&,Nullable`1<Int32>[]&)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    ILC : Trim analysis warning IL2067: Microsoft.Extensions.Internal.ParameterDefaultValue.<TryGetDefaultValue>g__CreateValueType|0_0(Type): 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in call to 'System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(Type)'. The parameter '#0' of method 'Microsoft.Extensions.Internal.ParameterDefaultValue.<TryGetDefaultValue>g__CreateValueType|0_0(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
 ...

Build succeeded with 18 warning(s) in 29.0s
@ivanpovazan
Copy link
Contributor

@simonrozsival

Set $(MobileAggressiveAttributeTrimming)=true in the MAUI project.

Isn't the workaround setting the feature to false?

@ivanpovazan ivanpovazan added the bug If an issue is a bug or a pull request a bug fix label Jan 28, 2025
@ivanpovazan ivanpovazan added this to the .NET 10 milestone Jan 28, 2025
jonathanpeppers added a commit to dotnet/maui that referenced this issue Jan 28, 2025
Context: xamarin/xamarin-macios#22065

The introduction of a new `$(MobileAggressiveAttributeTrimming)`
MSBuild property in .NET 10 breaks NativeAOT builds in two ways:

* C# attributes are stripped away by ILLink, hence:

* Trimmer warnings are introduced.

* App crashes can result, with IL removed that *shouldn't* be.

Let's set `$(MobileAggressiveAttributeTrimming)` to `false` for now
to avoid these issues.

In a future PR, we can address xamarin-macios#22065 in the iOS workload.
rmarinho pushed a commit to dotnet/maui that referenced this issue Jan 28, 2025
Context: xamarin/xamarin-macios#22065

The introduction of a new `$(MobileAggressiveAttributeTrimming)`
MSBuild property in .NET 10 breaks NativeAOT builds in two ways:

* C# attributes are stripped away by ILLink, hence:

* Trimmer warnings are introduced.

* App crashes can result, with IL removed that *shouldn't* be.

Let's set `$(MobileAggressiveAttributeTrimming)` to `false` for now
to avoid these issues.

In a future PR, we can address xamarin-macios#22065 in the iOS workload.
@vitek-karas
Copy link
Contributor

If we really need this (personally I would prefer slightly bigger apps which work more often, over slightly smaller apps which break more often, but this is up to the iOS team to decide) I think we should make two changes to this:

  • Only enable it if TrimMode=partial, if we turn on full trimming which also enables all the trim analysis warnings, we should "play by the book" and keep attributes which trimmer can't remove. The promise of TrimMode=full and no warnings is that the app never breaks, we should keep that promise.
  • Not enable it for NativeAOT (which would happen from the above as well, since NativeAOT requires TrimMode=full) - the size impact of keeping attributes in NativeAOT is smaller than in IL apps, and again, NativeAOT should have a predictable behavior.

rolfbjarne added a commit that referenced this issue Feb 11, 2025
…ativeAOT. Fixes #22065.

Aggressive attribute trimming removes attributes used by the trimmer. This is
fine as long as we don't run _two_ trimmers - because then the first pass
would remove attributes needed by the second pass, which is exactly what
happens when we're building using NativeAOT: we first run ILLink, then
NativeAOT's trimmer.

If aggressive attribute trimming is enabled in this scenario, ILLink will
remove attributes required by NativeAOT to work correctly, so disable
aggressive attribute trimming.

Fixes #22065.
@rolfbjarne
Copy link
Member

  • Only enable it if TrimMode=partial, if we turn on full trimming which also enables all the trim analysis warnings, we should "play by the book" and keep attributes which trimmer can't remove. The promise of TrimMode=full and no warnings is that the app never breaks, we should keep that promise.

This might result in a rather unintuitive result: TrimMode=full apps can end up bigger than TrimMode=partial apps.

  • Not enable it for NativeAOT

I've created a PR with this change. We have fewer compatibility concerns with NativeAOT, while at the same time we have a bigger correctness promise, so this seemed like the best way forward.

@rolfbjarne rolfbjarne self-assigned this Feb 11, 2025
@vitek-karas
Copy link
Contributor

This might result in a rather unintuitive result: TrimMode=full apps can end up bigger than TrimMode=partial apps.

I think the same thing you mentioned for NativeAOT applies to TrimMode=full: "We have fewer compatibility concerns with NativeAOT, while at the same time we have a bigger correctness promise".
Yes - in theory it might make the app bigger, but in this mode we show trim warnings, and thus the expected behavior is that if there are now warnings, the app will work - removing attributes may break some apps without trim warnings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug If an issue is a bug or a pull request a bug fix
Projects
None yet
4 participants