dotnet / android

.NET for Android provides open-source bindings of the Android SDK for use with .NET managed languages such as C#
MIT License
1.93k stars 527 forks source link

How to exclude some libraries to be trimmed in .NET 8 for Android, not MAUI? #8975

Open FANMixco opened 5 months ago

FANMixco commented 5 months ago

Android application type

.NET Android (net7.0-android, net8.0-android, etc.)

Affected platform version

VS2022

Description

I'm migrating my app from Xamarin.Android to .NET 8 and I'm getting some issues since I don't have an option to exclude some libs that existed in Xamarin:

Skip Libs

But in .NET 8 for Android in Visual Studio 2022, there is nothing like that:

VS 2022

I tried to add some code like this one in the .csproj:

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
  <EnableLLVM>True</EnableLLVM>
  <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
  <AndroidKeyStore>False</AndroidKeyStore>
  <TrimMode>link</TrimMode>
  <PublishTrimmed>True</PublishTrimmed>
  <RunAOTCompilation>True</RunAOTCompilation>
  <AndroidLinkTool>r8</AndroidLinkTool>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
  <EnableLLVM>True</EnableLLVM>
  <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
  <AndroidKeyStore>False</AndroidKeyStore>
  <TrimMode>link</TrimMode>
  <RunAOTCompilation>True</RunAOTCompilation>
</PropertyGroup>
<ItemGroup>
  <TrimmerRootAssembly Include="Xamarin-MaterialSearchBar" RootMode="CopyUsed" />
</ItemGroup>
<ItemGroup>
  <TrimmerRootAssembly Include="Xamarin-MaterialSearchBar" RootMode="CopyUsed" />
</ItemGroup>

Or like this:

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
  <EnableLLVM>True</EnableLLVM>
  <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
  <AndroidKeyStore>False</AndroidKeyStore>
  <TrimMode>link</TrimMode>
  <PublishTrimmed>True</PublishTrimmed>
  <RunAOTCompilation>True</RunAOTCompilation>
  <AndroidLinkTool>r8</AndroidLinkTool>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
  <EnableLLVM>True</EnableLLVM>
  <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
  <AndroidKeyStore>False</AndroidKeyStore>
  <TrimMode>link</TrimMode>
  <RunAOTCompilation>True</RunAOTCompilation>
</PropertyGroup>
<ItemGroup>
  <TrimmerRootAssembly Include="Xamarin-MaterialSearchBar" />
</ItemGroup>

And I got error like these ones:

Severity Code Description Project File Line Suppression State Error MSB4096 The item "Xamarin-MaterialSearchBar" in item list "TrimmerRootAssembly" does not define a value for metadata "RootMode"

Severity Code Description Project File Line Suppression State Error IL1037 Invalid assembly root mode 'CopyUsed'.

Severity Code Description Project File Line Suppression State Error NETSDK1144 Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false.

Without the trimming, my app increases almost twice its size. Any idea how can I exclude this library?

Steps to Reproduce

  1. Try to exclude any library from being trimmed in the properties of Visual Studio: VS 2022

Did you find any workaround?

No, it used to work in Xamarin.Android.

Relevant log output

N/A
dellis1972 commented 5 months ago

@FANMixco take a look through these documents, it should help https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/OneDotNet.md#linker-illink

dellis1972 commented 5 months ago

Also based on https://learn.microsoft.com/en-gb/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#trimming-granularity you probably need to set TrimMode to partial (<TrimMode>partial</TrimMode>) to enable assembly level TrimmableAssembly items.

FANMixco commented 5 months ago

TrimMode

I tried the partial one, but the error persists:

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <EnableLLVM>True</EnableLLVM>
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <AndroidKeyStore>False</AndroidKeyStore>
    <TrimMode>partial</TrimMode>
    <PublishTrimmed>True</PublishTrimmed>
    <RunAOTCompilation>True</RunAOTCompilation>
    <AndroidLinkTool>r8</AndroidLinkTool>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <EnableLLVM>True</EnableLLVM>
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <AndroidKeyStore>False</AndroidKeyStore>
    <TrimMode>link</TrimMode>
    <RunAOTCompilation>True</RunAOTCompilation>
  </PropertyGroup>
  <ItemGroup>
    <TrimmerRootAssembly Include="Xamarin-MaterialSearchBar" RootMode="CopyUsed" />
  </ItemGroup>

image

FANMixco commented 5 months ago

If I use CopyUsed, then I get another error:

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <EnableLLVM>True</EnableLLVM>
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <AndroidKeyStore>False</AndroidKeyStore>
    <TrimMode>CopyUsed</TrimMode>
    <PublishTrimmed>True</PublishTrimmed>
    <RunAOTCompilation>True</RunAOTCompilation>
    <AndroidLinkTool>r8</AndroidLinkTool>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <EnableLLVM>True</EnableLLVM>
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <AndroidKeyStore>False</AndroidKeyStore>
    <TrimMode>link</TrimMode>
    <RunAOTCompilation>True</RunAOTCompilation>
  </PropertyGroup>

image

FANMixco commented 5 months ago

I did the following changes:

  1. I disabled the AOT,
  2. I used the CopyUsed as TrimMode,
  3. I removed the Lib (since it gave errors) from the "exclusion" group,
  4. and I added the class in the Proguard: -keep class tk.supernovaic.MaterialSearchBar.** { *; }:
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <EnableLLVM>True</EnableLLVM>
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <AndroidKeyStore>False</AndroidKeyStore>
    <TrimMode>CopyUsed</TrimMode>
    <PublishTrimmed>True</PublishTrimmed>
    <RunAOTCompilation>False</RunAOTCompilation>
    <AndroidLinkTool>r8</AndroidLinkTool>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <EnableLLVM>True</EnableLLVM>
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <AndroidKeyStore>False</AndroidKeyStore>
    <TrimMode>link</TrimMode>
    <RunAOTCompilation>False</RunAOTCompilation>
  </PropertyGroup>

But I don't think it's working at all since the library is still being deleted:

Android.Views.InflateException: Binary XML file line #1 in tk.supernova.tipsal:layout/activity_main: Binary XML file line #1 in tk.supernova.tipsal:layout/app_bar_main: Error inflating class crc64f9f7571c828bfc75.MaterialSearchBar 05-22 22:53:58.370 8472 8472 I DOTNET : ---> Android.Views.InflateException: Binary XML file line #1 in tk.supernova.tipsal:layout/app_bar_main: Error inflating class crc64f9f7571c828bfc75.MaterialSearchBar 05-22 22:53:58.370 8472 8472 I DOTNET : ---> Java.Lang.Reflect.InvocationTargetException: Exception_WasThrown, Java.Lang.Reflect.InvocationTargetException 05-22 22:53:58.370 8472 8472 I DOTNET : ---> System.NotSupportedException: Could not activate JNI Handle 0x7ffcae9df190 (key_handle 0x93ee181) of Java type 'crc64f9f7571c828bfc75/MaterialSearchBar' as managed type 'tk.supernovaic.MaterialSearchBar.MaterialSearchBar'.

This doesn't happen if I avoid trimming it, but then the app doubles its size.

Any suggestions?

dellis1972 commented 5 months ago

@FANMixco Looks like the valid values for RootMode changed in the latest versions of dotnet . See https://github.com/dotnet/runtime/blob/4c8a235abd8b510a3f8a5161bea03abd5b69896c/src/tools/illink/src/linker/Linker/AssemblyRootMode.cs#L8 for a list of valid values.

I'm not 100% what each of those do but the code for the process is at https://github.com/dotnet/runtime/blob/main/src/tools/illink/src/linker/Linker.Steps/RootAssemblyInputStep.cs#L13.

I suspect you might need a RootMode of Library but I could be wrong about that.

FANMixco commented 5 months ago

@FANMixco Looks like the valid values for RootMode changed in the latest versions of dotnet . See https://github.com/dotnet/runtime/blob/4c8a235abd8b510a3f8a5161bea03abd5b69896c/src/tools/illink/src/linker/Linker/AssemblyRootMode.cs#L8 for a list of valid values.

I'm not 100% what each of those do but the code for the process is at https://github.com/dotnet/runtime/blob/main/src/tools/illink/src/linker/Linker.Steps/RootAssemblyInputStep.cs#L13.

I suspect you might need a RootMode of Library but I could be wrong about that.

Hi @dellis1972 or @jonathanpeppers, I suspect this is a bug in Visual Studio since copying the configuration from the project that used the same library is working perfectly:

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
    <EnableLLVM>True</EnableLLVM>
    <AndroidLinkTool>r8</AndroidLinkTool>
    <RunAOTCompilation>False</RunAOTCompilation>
  </PropertyGroup>

However, I cannot find a way to leave it like this in VS using the properties. Any other option breaks the app and causes different errors since the library is partially copied, changed, etc. How can we report this bug? This seems to be a serious problem.

dellis1972 commented 5 months ago

@FANMixco so the issue is with the Visual Studio UI not providing the right options? or it breaks the settings in the csproj?

cc @tondat

FANMixco commented 5 months ago

@FANMixco so the issue is with the Visual Studio UI not providing the right options? or it breaks the settings in the csproj?

cc @tondat

There are two bugs in Visual Studio:

  1. You cannot exclude specific Libs. This was possible in Xamarin.Android: Skip Libs

  2. You cannot revert or reach the configuration I shared if you don't modify via it Code. This is for sure a VS bug. I'm not sure if it's the default configuration of a new project since I've been migrating everything from Xamarin.Android to .NET 8, and I was doing multiple tests in each app since I have migrated 4 apps. This one that is relatively one of the easiest and with more libs was the most complex one.

dellis1972 commented 5 months ago

@FANMixco if its definately an issue in VS I'm sure @tondat would advise you to raise an issue using the Report an Issue menu item In visual studio, this way the issue will get routed to the correct team. The VS team use a differnt bug reporting system to this project because it is not an open source project.

FANMixco commented 5 months ago

I can understand that VS is not an open-source solution, however, perhaps, @tondat should make us the favor to raise the ticket in such a scenario since they might listen to him. As an almost decade-old Windows Insider and someone who has reported several serious bugs over the years, I have serious doubts, that the dev team will ever consider it even if it impacts the full .NET 8 for Android migrations. Some months ago, I even read a Twit where someone from Microsoft asked about how our status migrating apps and recalled us the VS provided "solution."

image

To be honest, I don't know what I could have replied to that Microsoft employee. The VS solution does not work as expected since it transforms your Xamarin.Android project into a MAUI.NET, not a .NET for Android without a prior warning.

image

image

Would it work? Maybe, but it's something different. I had to learn on my own how to do it since the documentation was harder to follow and did not work at all in the end. It was easier to add a new project to my solution, copy most of the files, replace Xamarin.Essentials with Microsoft.Maui.Essentials, and rename some stuff than following the documentation. That was all quicker and faster than the provided documentation or the VS "solution."

If I raised the ticket, I'm sure it would go to a random backlog, waiting for votes that might never get or close since it didn't get too much attention (my own experience) even if in the next update after it was closed, you should raise it again.

I sound quite negative, but even recently, I even reported a considerable bug from an enterprise paid Azure account from a large client and have 100% doubts, it will be fixed in the foreseeable future even though the UI and links are broken, blocking any user to use the Azure service. I have no hope, if @tondat would expect that I should raise the "ticket" that anyone from the VS dev team would ever check it.

Let's take another example of a similar topic that was fully ignored for years: https://github.com/xamarin/GoogleApisForiOSComponents

It was even archived on May 1st, 2024, without a prior warning, documentation, alternatives, or comments.

image

At least there are some new comments in the Android one

image

But would the new version support Android and iOS? Or would it be for Android only? So, what happened to the iOS devs? Who knows, it's unclear.

In my opinion, some comments should be added if the iOS project is dead, so people can redirect their efforts properly. In the iOS one, devs were requesting support for some serious bugs, perhaps some documentation of how to use it, the status of the project or to know what to do. Some Microsoft repo users even suggested us to contact @davidortinau, who sadly never replied: https://github.com/xamarin/GoogleApisForiOSComponents/issues/628

I even reached him twice via Twitter/X, but no replies. Perhaps, because I'm not a massive influencer yet. That's why, my hopes are non-existent if it's expected that I should create a new bug request in the VS backlog. I have raised several VS bugs over the years with minimal to no impact that were real bugs some of them even crashed VS. I eventually even stopped raising tickets since many turned on deaf ears.

jonathanpeppers commented 4 months ago

@(TrimmerRootAssembly) is the replacement for the "Skip linking assemblies" project option. There is no project option page for most trimmer settings.

They have it documented here:

And we even use it here, to preserve unit test cases: https://github.com/xamarin/xamarin-android/blob/f5fcd4ddc5bacdb9699c50f6dad80627b80d72c8/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj#L45

Does this not work for you?

For your other comments about the IDE, can you file a Help > Send Feedback? We can't help much with those here.