Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[One .NET] fix [Export] for Release builds (#6235)
Imagine you use the `[Export]` attribute: partial class Example : Java.Lang.Object { [Java.Interop.Export] public void newJavaMethod() { } } If you then build this type in a .NET 6+ app in Release config, the build will fail with a `NullReferenceException`: Xamarin.Android.Common.targets(1413,3): error XA4209: Failed to generate Java type for class: UnnamedProject.ContainsExportedMethods due to System.NullReferenceException: Object reference not set to an instance of an object. at Java.Interop.Tools.JavaCallableWrappers.JavaCallableWrapperGenerator.Signature..ctor(String name, String signature, String connector, String managedParameters, String outerType, String superCall) at Java.Interop.Tools.JavaCallableWrappers.JavaCallableWrapperGenerator.Signature..ctor(MethodDefinition method, ExportAttribute export, IMetadataResolver cache) at Java.Interop.Tools.JavaCallableWrappers.JavaCallableWrapperGenerator.AddMethod(MethodDefinition registeredMethod, MethodDefinition implementedMethod) at Java.Interop.Tools.JavaCallableWrappers.JavaCallableWrapperGenerator..ctor(TypeDefinition type, String outerType, Action`2 log, IMetadataResolver resolver) at Java.Interop.Tools.JavaCallableWrappers.JavaCallableWrapperGenerator..ctor(TypeDefinition type, Action`2 log, IMetadataResolver resolver) at Java.Interop.Tools.JavaCallableWrappers.JavaCallableWrapperGenerator..ctor(TypeDefinition type, Action`2 log, TypeDefinitionCache cache) at Xamarin.Android.Tasks.GenerateJavaStubs.CreateJavaSources(IEnumerable`1 javaTypes, TypeDefinitionCache cache) The `NullReferenceException` happens because the `System.Void` type in `System.Runtime.dll` is actually a type forwarder to `System.Private.CoreLib.dll`: [assembly: TypeForwardedTo(typeof(void))] and in Release config, `JavaCallableWrapperGenerator` runs on the *linked* assembly output, and once `System.Runtime.dll` is linked it no longer contains type forwarders. Consequently `JavaCallableWrapperGenerator` is unable to resolve the type `System.Void, System.Runtime`, as the type forwarder no longer exists. I found we could solve this issue by preserving the types in `System.Runtime.dll`: <linker> <assembly fullname="System.Runtime"> <type fullname="System.Void" /> </assembly> </linker> However, while this works, it meant that *none* of those types could be linked at all, which increased app sizes. "Split the difference" by instead preserving the `ToString()` method: <linker> <assembly fullname="System.Runtime"> <type fullname="System.Void"> <method name="ToString" /> </type> </assembly> </linker> Additionally, preserve all other built-in types such as `Int32` and `Boolean`. The result of this is that a linked `System.Runtime.dll` increases in size by ~150 bytes. The test now passes, and I believe most usage of `[Export]` should work now for `Release` builds.
- Loading branch information