Open Redth opened 3 years ago
CC @steveisok @marek-safar
One issue that came up about this that would need to be handled is that some bindings packages are not intended to be managed bindings, and exist simply to add the .jar
/.aar
to the application.
That is, they do this:
<remove-node path="/api/package" />
Which produces a .dll
containing the .jar
/.aar
and no managed code. In this case, the user would want to Java code added to their app even though the .dll
would be linked out.
I going to go ahead offer some ideas here but know that I could be way off mark since I'm not very familiar with the details of the build system.
Would it be possible to have the ILLinker to produce a (probably huge) tree of sorts of all the used/not-trimmed methods and classes and then another build task could use that tree/file to read and scan the assemblies for [Register]
attributes and extract all the java members used and then from there another build task (or possibly the same one) that generates a progaurd file that gets included with the other progaurd files from the app head and the other included .aar
s and then fed to R8
?
As for what @jpobst mentioned, I don't know how R8
works but if you managed to get R8
to not link out the Java code used from C# directly, doesn't that automatically tell R8
that the Java code used by that code is also used and shouldn't be trimmed? I'm guessing the exception here would be reflection in the Java side of things, this should be handled by the Java library author themselves and that responsibility shouldn't be on XA.
I'm wondering how much illinker involvement is actually desirable here. The illinker is not responsible for assemblies publishing and in this case it looks like the process is quite Android specific and sounds rather complicated due to possible customizations. Can Android do something similar to what other platforms do and scan/probe for needed dependencies of trimmed assemblies and combine that with other inputs to publish only needed dependencies?
Problem
When .NET Android (including MAUI) projects reference external libraries/packages which contain Bindings to Native .aar/.jar libraries, it is currently difficult to trim the native libraries and in some cases impossible to achieve an optimal trimming result.
Native Linking with R8
It’s possible to use the R8 (formerly proguard) to perform trimming however this is an advanced concept for developers. We do not enable it by default for Release configurations because it usually does not work out of the box and requires manual additions to the proguard.config rules to tweak the java/native types from being removed by the overly aggressive trimming R8 performs.
Android Manifest prevents too many types from being trimmed
In android native .aar libraries, it is possible to define an AndroidManifest.xml file which gets included in the build of the application consuming the library. This manifest file can include entries for declaring the existence of Activities, Services, Broadcast Receivers, and other types which are registered with Android for other processes to interact with. When these declarations exist, the native linker (R8) has no way to ensure these types are unused (there is no trimming of the AndroidManifest files) and so it must keep the types referenced in this file from being trimmed out.
This means that even if the managed .NET assembly that is associated to the native library is trimmed out, but the native library is still included in the build, using R8 will still not remove as much of the native library as might be optimal.
.NET and Native Trimming have no relationship
Currently, even if a managed .NET assembly with bindings to a native library is completely trimmed out of a build, the native library assets will still be included in the build. It would be ideal to have a way to associate a native library (.aar/.jar/.so/etc) with a managed .NET assembly such that if the managed .NET assembly is trimmed out, the native library is also removed. There may be difficulties in the ordering of this process and could require an additional build step. It’s also possible that trimming out the native library in some of these cases is not desirable, so there would need to be a way to override this behaviour.