Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[One .NET] new "greenfield" projects are trimmed by default (#8805)
Context: 5205a5f Context: 8a5b2a0 Context: #8724 Context: #8797 As we have solved all trimming warnings (5205a5f. 8a5b2a0) in the Android workload, we can now go "all in" on trimming. Early in .NET 6 (maybe even 5?) we "hid" many trimming warnings as we did not yet plan to solve them: <SuppressTrimAnalysisWarnings Condition=" '$(SuppressTrimAnalysisWarnings)' == '' ">true</SuppressTrimAnalysisWarnings> These warnings were not *actionable* at the time for customers, as many warnings were in `Mono.Android.dll`, `Java.Interop.dll`, etc. Going forward, let's stop suppressing these warnings for `$(TrimMode)`=full. We can also enable trimming for new projects: * `dotnet new android` * `dotnet new android-wear` New projects will have the [`$(TrimMode)`][0] property set to `Full` by default: <!-- Enable full trimming in Release mode. To learn more, see: https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options#trimming-granularity --> <PropertyGroup Condition="'$(Configuration)' == 'Release'"> <TrimMode>full</TrimMode> </PropertyGroup> We wouldn't want to do this for existing projects *yet*, as they might have existing code, NuGet packages, etc. where trimming warnings might be present. We can also improve the templates for Android class libraries: * `dotnet new androidlib` * `dotnet new android-bindinglib` New class library projects will have the [`$(IsTrimmable)`][1] property set to `true` by default: <!-- Enable trim analyzers for Android class libraries. To learn more, see: https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming --> <IsTrimmable>true</IsTrimmable> This way, new class libraries will be "trimmable" by default and be able to react to trimming warnings. We can also use `$(TrimMode)=full` in many of our existing tests: * MSBuild tests that assert 0 warnings can use `$(TrimMode)=full`. * On-device tests can use `$(TrimMode)=full`. ~~ General trimming warnings ~~ This was discovered through `Mono.Android-NET-Tests.csproj`, but there were a few trimmer warnings in the "layout bindings" feature: …\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(79,56): warning IL2091: Xamarin.Android.Design.LayoutBinding.<>c__DisplayClass8_0<T>.<FindFragment>b__0(Activity): 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.App.FragmentManager.FindFragmentById<T>(Int32)'. The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.<>c__DisplayClass8_0<T>' 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. …\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(35,5): warning IL2091: Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&): 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.App.Activity.FindViewById<T>(Int32)'. The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&)' 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. …\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(37,5): warning IL2091: Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&): 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.Views.View.FindViewById<T>(Int32)'. The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.FindView<T>(Int32, T&)' 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. We can `[DynamicallyAccessedMembers(Constructors)]` to fix these. ~~ Trimming warnings in tests ~~ Several tests that verify "trimming unsafe features" just specify: [RequiresUnreferencedCode ("Tests trimming unsafe features")] If the test might have an issue under NativeAOT, I used: // FIXME: #8724 #pragma warning disable IL3050 Places that use `Assembly.GetType()` can use `Type.GetType()` instead: -var JavaProxyThrowable_type = typeof (Java.Lang.Object) - .Assembly - .GetType ("Android.Runtime.JavaProxyThrowable"); +var JavaProxyThrowable_type = Type.GetType ("Android.Runtime.JavaProxyThrowable, Mono.Android"); `SystemTests.AppDomainTest` was just ignored (and had warnings). Update to just verify `PlatformNotSupportedException` is thrown. ~~ Test failures ~~ `JsonSerializerTest` requires setting [`$(JsonSerializerIsReflectionEnabledByDefault)`][2]=true: <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault> Otherwise, an exception is thrown: System.InvalidOperationException : JsonSerializerIsReflectionDisabled `Java.Interop-Tests` were initially not loaded at all, with the log message: W NUnit : Failed to load tests from assembly 'Java.Interop-Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 If we make `Java.Interop-Tests.dll` a `@(TrimmerRootAssembly)`: <TrimmerRootAssembly Include="Java.Interop-Tests" RootMode="All" /> Then all the tests cases are preserved and can be run, in the same way the "main app assembly" is preserved. `Android.GraphicsTests.NinePatchTests` failed with: The drawable created from resource tile should be a NinePatchDrawable. Expected: not null But was: null The only usage of `NinePatchDrawable` was: Assert.IsNotNull (d as NinePatchDrawable); `NinePatchDrawable` likely needs its interfaces and constructors preserved for this test to pass. I added an attribute for just `All` members for the test to pass: [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (NinePatchDrawable))] `Xamarin.Android.RuntimeTests.CustomWidgetTests` failed with: (Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView) at Java.Interop.JniEnvironment.InstanceMethods.CallObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* ) at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualObjectMethod(String , IJavaPeerable , JniArgumentValue* ) at Android.Views.LayoutInflater.Inflate(Int32 , ViewGroup ) at Xamarin.Android.RuntimeTests.CustomWidgetTests.<>c.<UpperCaseCustomWidget_ShouldNotThrowInflateException>b__0_0() at NUnit.Framework.Constraints.VoidInvocationDescriptor.Invoke() at NUnit.Framework.Constraints.ExceptionInterceptor.Intercept(Object ) --- End of managed Java.Lang.RuntimeException stack trace --- android.view.InflateException: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView Caused by: android.view.InflateException: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView Caused by: java.lang.ClassNotFoundException: Mono.Android_Test.Library.CustomTextView at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:454) at android.view.LayoutInflater.createView(LayoutInflater.java:815) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.inflate(LayoutInflater.java:682) at android.view.LayoutInflater.inflate(LayoutInflater.java:534) at android.view.LayoutInflater.inflate(LayoutInflater.java:481) at crc643df67da7b13bb6b1.TestInstrumentation_1.n_onStart(Native Method) at crc643df67da7b13bb6b1.TestInstrumentation_1.onStart(TestInstrumentation_1.java:32) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189) Caused by: java.lang.ClassNotFoundException: Didn't find class "Mono.Android_Test.Library.CustomTextView" on path In this case, `Mono.Android_Test.Library.CustomTextView` was used from an Android layout, but not used anywhere in managed code. To fix, I added: [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (Mono.Android_Test.Library.CustomTextView))] I could have also made `Mono.Android_Test.Library` a `@(TrimmerRootAssembly)`. TODO: `View` subclasses used within Android Layout `.axml` files should be automatically preserved; see #8797. [0]: https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#trimming-granularity [1]: https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming?pivots=dotnet-8-0#enable-project-specific-trimming [2]: https://learn.microsoft.com/dotnet/core/compatibility/serialization/8.0/publishtrimmed
- Loading branch information