From 3415f679cb29ec2f2e7d7ba1604244e3045eddb5 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Thu, 20 Oct 2022 20:16:49 +0100 Subject: [PATCH 1/5] [Xamarin.Android.Build.Tasks] Don't report duplicate type if the mvid is the same. Fixes #7473 With the new build system under `dotnet` we can end up with duplicate assemblies for different `RuntimeIdentifiers`. This can cause the `GenerateJavaStubs` task to mistakenly report duplicate types. ``` warning XA4214: The managed type `Microsoft.UI.Xaml.Controls.AnimatedIcon` exists in multiple assemblies: Uno.UI, Uno.UI, Uno.UI, Uno.UI. Please refactor the managed type names in these assemblies so that they are not identical. [C:\a\1\s\UnoAppAll\UnoAppAll.Mobile\UnoAppAll.Mobile.csproj::TargetFramework=net6.0-android] error XA4215: The Java type `crc64a5a37c43dff01024.GridViewHeaderItem` is generated by more than one managed type. Please change the [Register] attribute so that the same Java type is not emitted. [C:\a\1\s\UnoAppAll\UnoAppAll.Mobile\UnoAppAll.Mobile.csproj::TargetFramework=net6.0-android] ``` We should ignore these duplicates is the `mvid` of the the type module is the same. If it is then they will be from the same assembly. --- .../Tasks/GenerateJavaStubs.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs index 4053a0f9b1e..548634595d4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs @@ -217,7 +217,6 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) if ((!useMarshalMethods && !userAssemblies.ContainsKey (td.Module.Assembly.Name.Name)) || JavaTypeScanner.ShouldSkipJavaCallableWrapperGeneration (td, cache)) { continue; } - javaTypes.Add (td); } @@ -272,6 +271,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) using (var acw_map = MemoryStreamPool.Shared.CreateStreamWriter ()) { foreach (TypeDefinition type in javaTypes) { + string mvid = type.Module.Mvid.ToString (); string managedKey = type.FullName.Replace ('/', '.'); string javaKey = JavaNativeTypeManager.ToJniName (type, cache).Replace ('/', '.'); @@ -283,16 +283,20 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) TypeDefinition conflict; bool hasConflict = false; if (managed.TryGetValue (managedKey, out conflict)) { - if (!managedConflicts.TryGetValue (managedKey, out var list)) - managedConflicts.Add (managedKey, list = new List { conflict.GetPartialAssemblyName (cache) }); - list.Add (type.GetPartialAssemblyName (cache)); + if (!conflict.Module.Mvid.Equals(mvid)) { + if (!managedConflicts.TryGetValue (managedKey, out var list)) + managedConflicts.Add (managedKey, list = new List { conflict.GetPartialAssemblyName (cache) }); + list.Add (type.GetPartialAssemblyName (cache)); + } hasConflict = true; } if (java.TryGetValue (javaKey, out conflict)) { - if (!javaConflicts.TryGetValue (javaKey, out var list)) - javaConflicts.Add (javaKey, list = new List { conflict.GetAssemblyQualifiedName (cache) }); - list.Add (type.GetAssemblyQualifiedName (cache)); - success = false; + if (!conflict.Module.Mvid.Equals(mvid)) { + if (!javaConflicts.TryGetValue (javaKey, out var list)) + javaConflicts.Add (javaKey, list = new List { conflict.GetAssemblyQualifiedName (cache) }); + list.Add (type.GetAssemblyQualifiedName (cache)); + success = false; + } hasConflict = true; } if (!hasConflict) { From 0303c0e80f265b4be8876b547bc087ae768a0e4c Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 1 Nov 2022 16:27:58 +0000 Subject: [PATCH 2/5] Updatee based on feedback --- src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs index 548634595d4..854ab8aacbc 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs @@ -271,7 +271,6 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) using (var acw_map = MemoryStreamPool.Shared.CreateStreamWriter ()) { foreach (TypeDefinition type in javaTypes) { - string mvid = type.Module.Mvid.ToString (); string managedKey = type.FullName.Replace ('/', '.'); string javaKey = JavaNativeTypeManager.ToJniName (type, cache).Replace ('/', '.'); @@ -283,7 +282,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) TypeDefinition conflict; bool hasConflict = false; if (managed.TryGetValue (managedKey, out conflict)) { - if (!conflict.Module.Mvid.Equals(mvid)) { + if (!conflict.Module.Mvid.Equals(type.Module.Mvid)) { if (!managedConflicts.TryGetValue (managedKey, out var list)) managedConflicts.Add (managedKey, list = new List { conflict.GetPartialAssemblyName (cache) }); list.Add (type.GetPartialAssemblyName (cache)); @@ -291,7 +290,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) hasConflict = true; } if (java.TryGetValue (javaKey, out conflict)) { - if (!conflict.Module.Mvid.Equals(mvid)) { + if (!conflict.Module.Mvid.Equals(type.Module.Mvid)) { if (!javaConflicts.TryGetValue (javaKey, out var list)) javaConflicts.Add (javaKey, list = new List { conflict.GetAssemblyQualifiedName (cache) }); list.Add (type.GetAssemblyQualifiedName (cache)); From 2923ca152678db30069e06e7aac4dbf436fbe880 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Wed, 9 Nov 2022 18:09:11 +0000 Subject: [PATCH 3/5] Add Unit test --- .../Tasks/GenerateJavaStubs.cs | 4 +-- .../Tasks/LinkerTests.cs | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs index 854ab8aacbc..0c8545cfe0e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs @@ -282,7 +282,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) TypeDefinition conflict; bool hasConflict = false; if (managed.TryGetValue (managedKey, out conflict)) { - if (!conflict.Module.Mvid.Equals(type.Module.Mvid)) { + if (!conflict.Module.Name.Equals(type.Module.Name)) { if (!managedConflicts.TryGetValue (managedKey, out var list)) managedConflicts.Add (managedKey, list = new List { conflict.GetPartialAssemblyName (cache) }); list.Add (type.GetPartialAssemblyName (cache)); @@ -290,7 +290,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) hasConflict = true; } if (java.TryGetValue (javaKey, out conflict)) { - if (!conflict.Module.Mvid.Equals(type.Module.Mvid)) { + if (!conflict.Module.Name.Equals(type.Module.Name)) { if (!javaConflicts.TryGetValue (javaKey, out var list)) javaConflicts.Add (javaKey, list = new List { conflict.GetAssemblyQualifiedName (cache) }); list.Add (type.GetAssemblyQualifiedName (cache)); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs index 530a3de0f07..62e9c1d157d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs @@ -509,5 +509,41 @@ public void AndroidUseNegotiateAuthentication ([Values (true, false, null)] bool } } } + + [Test] + public void DoNotErrorOnPerArchJavaTypeDuplicates () + { + if (!Builder.UseDotNet) + Assert.Ignore ("Test only valid on .NET"); + + var path = Path.Combine (Root, "temp", TestName); + var lib = new XamarinAndroidLibraryProject { IsRelease = true, ProjectName = "Lib1" }; + lib.SetProperty ("IsTrimmable", "true"); + lib.Sources.Add (new BuildItem.Source ("Library1.cs") { + TextContent = () => @" +namespace Lib1; +public class Library1 : Java.Lang.Object { + private static bool Is64Bits = IntPtr.Size >= 8; + + public static bool Is64 () { + return Is64Bits; + } +}", + }); + var proj = new XamarinAndroidApplicationProject { IsRelease = true, ProjectName = "App1" }; + proj.References.Add(new BuildItem.ProjectReference (Path.Combine ("..", "Lib1", "Lib1.csproj"), "Lib1")); + proj.MainActivity = proj.DefaultMainActivity.Replace ( + "base.OnCreate (bundle);", + "base.OnCreate (bundle);\n" + + "if (Lib1.Library1.Is64 ()) Console.WriteLine (\"Hello World!\");"); + + + using (var lb = CreateDllBuilder (Path.Combine (path, "Lib1"))) { + using (var b = CreateApkBuilder (Path.Combine (path, "App1"))) { + Assert.IsTrue (lb.Build (lib), "build should have succeeded."); + Assert.IsTrue (b.Build (proj), "build should have succeeded."); + } + } + } } } From 10e837967ec7dd03f91668b7cfa8fa03e76b3384 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Thu, 17 Nov 2022 13:59:21 +0000 Subject: [PATCH 4/5] remove nested using's --- .../Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs index 62e9c1d157d..0a630a47619 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs @@ -538,12 +538,10 @@ public static bool Is64 () { "if (Lib1.Library1.Is64 ()) Console.WriteLine (\"Hello World!\");"); - using (var lb = CreateDllBuilder (Path.Combine (path, "Lib1"))) { - using (var b = CreateApkBuilder (Path.Combine (path, "App1"))) { - Assert.IsTrue (lb.Build (lib), "build should have succeeded."); - Assert.IsTrue (b.Build (proj), "build should have succeeded."); - } - } + using var lb = CreateDllBuilder (Path.Combine (path, "Lib1")); + using var b = CreateApkBuilder (Path.Combine (path, "App1")); + Assert.IsTrue (lb.Build (lib), "build should have succeeded."); + Assert.IsTrue (b.Build (proj), "build should have succeeded."); } } } From d685f0bc76eb83618a93ab8212fd1cb810d46cad Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 29 Nov 2022 11:31:07 -0500 Subject: [PATCH 5/5] Fix code formatting --- src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs index 0c8545cfe0e..d82c2f10b00 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs @@ -282,7 +282,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) TypeDefinition conflict; bool hasConflict = false; if (managed.TryGetValue (managedKey, out conflict)) { - if (!conflict.Module.Name.Equals(type.Module.Name)) { + if (!conflict.Module.Name.Equals (type.Module.Name)) { if (!managedConflicts.TryGetValue (managedKey, out var list)) managedConflicts.Add (managedKey, list = new List { conflict.GetPartialAssemblyName (cache) }); list.Add (type.GetPartialAssemblyName (cache)); @@ -290,7 +290,7 @@ void Run (DirectoryAssemblyResolver res, bool useMarshalMethods) hasConflict = true; } if (java.TryGetValue (javaKey, out conflict)) { - if (!conflict.Module.Name.Equals(type.Module.Name)) { + if (!conflict.Module.Name.Equals (type.Module.Name)) { if (!javaConflicts.TryGetValue (javaKey, out var list)) javaConflicts.Add (javaKey, list = new List { conflict.GetAssemblyQualifiedName (cache) }); list.Add (type.GetAssemblyQualifiedName (cache));