From a82d24ef955e9b06a258ed31daf102817868b8b5 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 11 Oct 2023 13:30:20 -0500 Subject: [PATCH 01/15] [WIP] attempt to fix dotnet/maui#17265 Context: https://github.com/dotnet/maui/issues/17265 Reproduced the issue in a new `FixLegacyResourceDesignerStep` test. It crashes at runtime, but if you change the class libraries in the test to `net8.0`, it works fine. I first attempted to fix the problem for `Release` mode, as it seemed easier to do a "second pass" on *all assemblies* at the end of a linker step. This change starts to work: ILLink: Library2 has an assembly reference to Library1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ILLink: Library2 has an assembly reference with a designer. ILLink: Adding reference _Microsoft.Android.Resource.Designer. ILLink: FixupAssemblyTypes Library2. ILLink: Looking for String::hello. ILLink: Fixing up System.Int32 Foo::get_Hello() ILLink: Replacing IL_0000: ldsfld System.Int32 Library1.Resource/String::hello ILLink: With IL_0000: call System.Int32 _Microsoft.Android.Resource.Designer.Resource/String::get_hello() But then fails with: System.ArgumentException: Member 'System.Int32 _Microsoft.Android.Resource.Designer.Resource/String::get_hello()' is declared in another module and needs to be imported --- .../FixLegacyResourceDesignerStep.cs | 22 ++++---- .../MonoDroid.Tuner/LinkDesignerBase.cs | 38 ++++++++++++- .../RemoveResourceDesignerStep.cs | 2 +- .../Tests/InstallAndRunTests.cs | 53 +++++++++++++++++++ 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs index ae4473d6cd1..23e7f30b7e4 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs @@ -34,6 +34,8 @@ public class FixLegacyResourceDesignerStep : LinkDesignerBase protected override void EndProcess () { + base.EndProcess (); + if (designerAssembly != null) { LogMessage ($" Setting Action on {designerAssembly.Name} to Link."); Annotations.SetAction (designerAssembly, AssemblyAction.Link); @@ -68,18 +70,20 @@ protected override void LoadDesigner () } } - internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly) + internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly, TypeDefinition designer = null) { - if (!FindResourceDesigner (assembly, mainApplication: false, out TypeDefinition designer, out CustomAttribute designerAttribute)) { + if (designer is not null) { + LogMessage ($" {assembly.Name.Name} has an assembly reference with a designer."); + } else if (!FindResourceDesigner (assembly, mainApplication: false, out designer, out _)) { LogMessage ($" {assembly.Name.Name} has no designer. "); return false; - } - - LogMessage ($" {assembly.Name.Name} has a designer. "); - LogMessage ($" BaseType: {designer.BaseType.FullName}. "); - if (designer.BaseType.FullName == $"{DesignerAssemblyNamespace}.Resource") { - LogMessage ($" {assembly.Name.Name} has already been processed. "); - return false; + } else { + LogMessage ($" {assembly.Name.Name} has a designer. "); + LogMessage ($" BaseType: {designer.BaseType.FullName}. "); + if (designer.BaseType.FullName == $"{DesignerAssemblyNamespace}.Resource") { + LogMessage ($" {assembly.Name.Name} has already been processed. "); + return false; + } } // This is expected for the first call, in diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index d8c65f1b573..5d6d5e78448 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -16,6 +16,9 @@ namespace MonoDroid.Tuner { public abstract class LinkDesignerBase : BaseStep { + HashSet allAssemblies = new (); + HashSet processedAssemblies = new (); + public virtual void LogMessage (string message) { Context.LogMessage (message); @@ -198,6 +201,7 @@ protected void FixupAssemblyTypes (AssemblyDefinition assembly, TypeDefinition d protected override void ProcessAssembly (AssemblyDefinition assembly) { + allAssemblies.Add (assembly); LoadDesigner (); var action = Annotations.HasAction (assembly) ? Annotations.GetAction (assembly) : AssemblyAction.Skip; @@ -205,12 +209,42 @@ protected override void ProcessAssembly (AssemblyDefinition assembly) return; if (ProcessAssemblyDesigner (assembly)) { - if (action == AssemblyAction.Skip || action == AssemblyAction.Copy) + if (action == AssemblyAction.Skip || action == AssemblyAction.Copy) { Annotations.SetAction (assembly, AssemblyAction.Save); + processedAssemblies.Add (assembly); + } + } + } + + protected override void EndProcess () + { + if (processedAssemblies.Count > 0) { + foreach (var assembly in allAssemblies) { + if (processedAssemblies.Contains (assembly)) + continue; + + var action = Annotations.HasAction (assembly) ? Annotations.GetAction (assembly) : AssemblyAction.Skip; + if (action == AssemblyAction.Delete) + continue; + + foreach (var processedAssembly in processedAssemblies) { + if (assembly.MainModule.AssemblyReferences.Any (r => r.FullName == processedAssembly.Name.FullName)) { + LogMessage ($" {assembly.Name.Name} has an assembly reference to {processedAssembly.Name}"); + if (FindResourceDesigner (processedAssembly, mainApplication: false, out TypeDefinition designer, out _)) { + if (ProcessAssemblyDesigner (assembly, designer) && + (action == AssemblyAction.Skip || action == AssemblyAction.Copy)) { + Annotations.SetAction (assembly, AssemblyAction.Save); + } + } else { + LogMessage ($" {processedAssembly.Name} did not have a designer"); + } + } + } + } } } - internal abstract bool ProcessAssemblyDesigner (AssemblyDefinition assemblyDefinition); + internal abstract bool ProcessAssemblyDesigner (AssemblyDefinition assemblyDefinition, TypeDefinition designer = null); protected abstract void LoadDesigner (); protected abstract void FixBody (MethodBody body, TypeDefinition designer); } diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs index 2ef7e074cdc..28eed903fd8 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs @@ -84,7 +84,7 @@ protected override void FixBody (MethodBody body, TypeDefinition designer) } } - internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly) + internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly, TypeDefinition designer = null) { if (mainDesigner == null) return false; diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index a6e903cc6dd..0b2b84909c3 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1115,5 +1115,58 @@ public void EnableAndroidStripILAfterAOT ([Values (false, true)] bool profiledAO Assert.IsTrue(didLaunch, "Activity should have started."); } + [Test] + public void FixLegacyResourceDesignerStep ([Values (false, true)] bool isRelease) + { + string previousTargetFramework = "net7.0-android"; + + var library1 = new XamarinAndroidLibraryProject { + IsRelease = isRelease, + TargetFramework = previousTargetFramework, + ProjectName = "Library1", + AndroidResources = { + new AndroidItem.AndroidResource (() => "Resources\\values\\strings2.xml") { + TextContent = () => @" + + Hi! +", + }, + }, + }; + var library2 = new XamarinAndroidLibraryProject { + IsRelease = isRelease, + TargetFramework = previousTargetFramework, + ProjectName = "Library2", + OtherBuildItems = { + new BuildItem.Source("Foo.cs") { + TextContent = () => "public class Foo { public static int Hello => Library1.Resource.String.hello; } ", + } + } + }; + library2.AndroidResources.Clear (); + library2.SetProperty ("AndroidGenerateResourceDesigner", "false"); // Disable Android Resource Designer generation + library2.AddReference (library1); + proj = new XamarinAndroidApplicationProject { + IsRelease = isRelease, + ProjectName = "MyApp", + }; + proj.AddReference (library2); + proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}", "Console.WriteLine(Foo.Hello);"); + + using (var library1Builder = CreateDllBuilder (Path.Combine ("temp", TestName, library1.ProjectName))) + using (var library2Builder = CreateDllBuilder (Path.Combine ("temp", TestName, library2.ProjectName))) { + builder = CreateApkBuilder (Path.Combine ("temp", TestName, proj.ProjectName)); + Assert.IsTrue (library1Builder.Build (library1, doNotCleanupOnUpdate: true), $"Build of {library1.ProjectName} should have succeeded."); + Assert.IsTrue (library2Builder.Build (library2, doNotCleanupOnUpdate: true), $"Build of {library2.ProjectName} should have succeeded."); + Assert.IsTrue (builder.Build (proj), $"Build of {proj.ProjectName} should have succeeded."); + + RunProjectAndAssert (proj, builder); + + WaitForPermissionActivity (Path.Combine (Root, builder.ProjectDirectory, "permission-logcat.log")); + bool didLaunch = WaitForActivityToStart (proj.PackageName, "MainActivity", + Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30); + Assert.IsTrue (didLaunch, "Activity should have started."); + } + } } } From 69849f5f2fae36ec755451877a986a7ce3ee7cbd Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Thu, 12 Oct 2023 10:12:31 +0100 Subject: [PATCH 02/15] Fix up ImportReference --- .../Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs index 23e7f30b7e4..793320858ee 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs @@ -167,7 +167,7 @@ protected override void FixBody (MethodBody body, TypeDefinition designer) found = lookupCaseInsensitive.TryGetValue (key, out method); } if (found) { - var importedMethod = designer.Module.ImportReference (method); + var importedMethod = body.Method.Module.ImportReference (method); var newIn = Instruction.Create (OpCodes.Call, importedMethod); instructions.Add (i, newIn); } else { From e84d2fb6dc0c941c0965953c7a39e919f9b1664e Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Thu, 12 Oct 2023 10:57:51 +0100 Subject: [PATCH 03/15] Fix Debug Build --- .../MonoDroid.Tuner/LinkDesignerBase.cs | 7 ++++- .../Tasks/LinkAssembliesNoShrink.cs | 31 ++++++++++++++++++- .../Tests/InstallAndRunTests.cs | 2 +- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index 5d6d5e78448..fdf0bfb8dbe 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -38,7 +38,7 @@ public virtual AssemblyDefinition Resolve (AssemblyNameReference name) return Context.Resolve (name); } - protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute) + internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute) { string designerFullName = null; designer = null; @@ -216,6 +216,11 @@ protected override void ProcessAssembly (AssemblyDefinition assembly) } } + internal void ProcessNonDesignerAssemblies () + { + + } + protected override void EndProcess () { if (processedAssemblies.Count > 0) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs index 2d42039fce2..bc20b815e5d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs @@ -5,6 +5,8 @@ using Mono.Cecil; using System; using System.IO; +using System.Linq; +using System.Collections.Generic; using Microsoft.Android.Build.Tasks; namespace Xamarin.Android.Tasks @@ -67,6 +69,8 @@ public override bool RunTask () var fixAbstractMethodsStep = new FixAbstractMethodsStep (resolver, cache, Log); var addKeepAliveStep = new AddKeepAlivesStep (resolver, cache, Log, UsingAndroidNETSdk); var fixLegacyResourceDesignerStep = new FixLegacyResourceDesignerStep (resolver, Log); + Dictionary allAssemblies = new (); + HashSet processedAssemblies = new (); for (int i = 0; i < SourceFiles.Length; i++) { var source = SourceFiles [i]; var destination = DestinationFiles [i]; @@ -94,9 +98,14 @@ public override bool RunTask () if (assemblyDefinition == null) assemblyDefinition = resolver.GetAssembly (source.ItemSpec); + allAssemblies.Add (assemblyDefinition, destination); + bool save = fixAbstractMethodsStep.FixAbstractMethods (assemblyDefinition); - if (UseDesignerAssembly) + if (UseDesignerAssembly) { save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesigner (assemblyDefinition); + if (save) + processedAssemblies.Add (assemblyDefinition); + } if (AddKeepAlives) save |= addKeepAliveStep.AddKeepAlives (assemblyDefinition); if (save) { @@ -109,6 +118,26 @@ public override bool RunTask () CopyIfChanged (source, destination); } + if (UseDesignerAssembly && processedAssemblies.Count > 0) { + foreach (var kvp in allAssemblies) { + var assembly = kvp.Key; + var destination = kvp.Value; + if (processedAssemblies.Contains (assembly)) + continue; + bool save = false; + foreach (var processedAssembly in processedAssemblies) { + if (!assembly.MainModule.AssemblyReferences.Any (r => r.FullName == processedAssembly.Name.FullName)) + continue; + if (fixLegacyResourceDesignerStep.FindResourceDesigner (processedAssembly, mainApplication: false, out TypeDefinition designer, out _)) { + save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesigner (assembly, designer); + } + } + if (save) { + writerParameters.WriteSymbols = assembly.MainModule.HasSymbols; + assembly.Write (destination.ItemSpec, writerParameters); + } + } + } } return !Log.HasLoggedErrors; diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 0b2b84909c3..b6553ecdef6 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -1116,7 +1116,7 @@ public void EnableAndroidStripILAfterAOT ([Values (false, true)] bool profiledAO } [Test] - public void FixLegacyResourceDesignerStep ([Values (false, true)] bool isRelease) + public void FixLegacyResourceDesignerStep ([Values (true, false)] bool isRelease) { string previousTargetFramework = "net7.0-android"; From 9939315093ee7da1b39fd8463bbb5afd2ecdfb69 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 12 Oct 2023 09:20:50 -0500 Subject: [PATCH 04/15] Refactor to share more code Debug vs Release --- .../MonoDroid.Tuner/LinkDesignerBase.cs | 28 ++++++++++++------- .../Tasks/LinkAssembliesNoShrink.cs | 9 ++---- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index fdf0bfb8dbe..937630a5ad8 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -223,6 +223,7 @@ internal void ProcessNonDesignerAssemblies () protected override void EndProcess () { + // This is a "second pass" to fix assemblies with references to assemblies with a designer if (processedAssemblies.Count > 0) { foreach (var assembly in allAssemblies) { if (processedAssemblies.Contains (assembly)) @@ -233,22 +234,29 @@ protected override void EndProcess () continue; foreach (var processedAssembly in processedAssemblies) { - if (assembly.MainModule.AssemblyReferences.Any (r => r.FullName == processedAssembly.Name.FullName)) { - LogMessage ($" {assembly.Name.Name} has an assembly reference to {processedAssembly.Name}"); - if (FindResourceDesigner (processedAssembly, mainApplication: false, out TypeDefinition designer, out _)) { - if (ProcessAssemblyDesigner (assembly, designer) && - (action == AssemblyAction.Skip || action == AssemblyAction.Copy)) { - Annotations.SetAction (assembly, AssemblyAction.Save); - } - } else { - LogMessage ($" {processedAssembly.Name} did not have a designer"); - } + if (ProcessAssemblyDesignerSecondPass (assembly, processedAssembly) && + (action == AssemblyAction.Skip || action == AssemblyAction.Copy)) { + Annotations.SetAction (assembly, AssemblyAction.Save); } } } } } + public bool ProcessAssemblyDesignerSecondPass (AssemblyDefinition assembly, AssemblyDefinition processedAssembly) + { + if (assembly.MainModule.AssemblyReferences.Any (r => r.FullName == processedAssembly.Name.FullName)) { + LogMessage ($" {assembly.Name.Name} has an assembly reference to {processedAssembly.Name}"); + if (FindResourceDesigner (processedAssembly, mainApplication: false, out TypeDefinition designer, out _) && + ProcessAssemblyDesigner (assembly, designer)) { + return true; + } else { + LogMessage ($" {processedAssembly.Name} did not have a designer"); + } + } + return false; + } + internal abstract bool ProcessAssemblyDesigner (AssemblyDefinition assemblyDefinition, TypeDefinition designer = null); protected abstract void LoadDesigner (); protected abstract void FixBody (MethodBody body, TypeDefinition designer); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs index bc20b815e5d..261bca0f3d7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs @@ -5,7 +5,6 @@ using Mono.Cecil; using System; using System.IO; -using System.Linq; using System.Collections.Generic; using Microsoft.Android.Build.Tasks; @@ -118,6 +117,8 @@ public override bool RunTask () CopyIfChanged (source, destination); } + + // Run a "second pass" for the FixLegacyResourceDesignerStep if (UseDesignerAssembly && processedAssemblies.Count > 0) { foreach (var kvp in allAssemblies) { var assembly = kvp.Key; @@ -126,11 +127,7 @@ public override bool RunTask () continue; bool save = false; foreach (var processedAssembly in processedAssemblies) { - if (!assembly.MainModule.AssemblyReferences.Any (r => r.FullName == processedAssembly.Name.FullName)) - continue; - if (fixLegacyResourceDesignerStep.FindResourceDesigner (processedAssembly, mainApplication: false, out TypeDefinition designer, out _)) { - save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesigner (assembly, designer); - } + save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesignerSecondPass (assembly, processedAssembly); } if (save) { writerParameters.WriteSymbols = assembly.MainModule.HasSymbols; From 9435fbb9d655dff668ad66d8f4f06f1c01d4dfdd Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Thu, 12 Oct 2023 23:08:02 +0100 Subject: [PATCH 05/15] Try a backup --- .../MonoDroid.Tuner/LinkDesignerBase.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index 937630a5ad8..b7677e0e96d 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -19,6 +19,12 @@ public abstract class LinkDesignerBase : BaseStep { HashSet allAssemblies = new (); HashSet processedAssemblies = new (); + string[] knownDesigners = new string [] { + "Microsoft.Maui", + "Microsoft.Maui.Core", + "Microsoft.Maui.Controls", + }; + public virtual void LogMessage (string message) { Context.LogMessage (message); @@ -63,8 +69,19 @@ internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplic } } - if (string.IsNullOrEmpty(designerFullName)) + if (string.IsNullOrEmpty(designerFullName)) { + // Check for known designers which have been removed. + LogMessage ($" c"); + foreach (var d in knownDesigners) { + LogMessage ($" Checking {d} against {assembly.Name.Name}"); + if (d.Contains (assembly.Name.Name)) { + designer = new TypeDefinition (d, "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); + designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass); + return true; + } + } return false; + } foreach (ModuleDefinition module in assembly.Modules) { @@ -77,6 +94,7 @@ internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplic } } } + return false; } From ff404dfcdd4f9080b68be5170f69169b0f5be3a6 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 13 Oct 2023 11:55:02 +0100 Subject: [PATCH 06/15] Make this work with a ItemGroup 'AndroidKnownDesignerAssemblies' --- .../MonoDroid.Tuner/LinkDesignerBase.cs | 20 +++++++++---------- .../Microsoft.Android.Sdk.ILLink.targets | 1 + .../Tasks/LinkAssembliesNoShrink.cs | 7 +++++-- .../Xamarin.Android.Common.targets | 2 ++ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index b7677e0e96d..040939171b0 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -19,11 +19,7 @@ public abstract class LinkDesignerBase : BaseStep { HashSet allAssemblies = new (); HashSet processedAssemblies = new (); - string[] knownDesigners = new string [] { - "Microsoft.Maui", - "Microsoft.Maui.Core", - "Microsoft.Maui.Controls", - }; + public string[] KnownDesignerAssemblies { get; set; } = Array.Empty (); public virtual void LogMessage (string message) { @@ -71,10 +67,8 @@ internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplic } if (string.IsNullOrEmpty(designerFullName)) { // Check for known designers which have been removed. - LogMessage ($" c"); - foreach (var d in knownDesigners) { - LogMessage ($" Checking {d} against {assembly.Name.Name}"); - if (d.Contains (assembly.Name.Name)) { + foreach (var d in KnownDesignerAssemblies) { + if (string.Compare (d, assembly.Name.Name, StringComparison.Ordinal) == 0) { designer = new TypeDefinition (d, "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass); return true; @@ -234,9 +228,13 @@ protected override void ProcessAssembly (AssemblyDefinition assembly) } } - internal void ProcessNonDesignerAssemblies () + protected override void Process () { - +#if ILLINK + if (Context.TryGetCustomData ("AndroidKnownDesignerAssemblies", out string knownDesignerAssemblies)) { + KnownDesignerAssemblies = knownDesignerAssemblies.Split (';'); + } +#endif } protected override void EndProcess () diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets index 7400de192ff..880c3abc4c1 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets @@ -45,6 +45,7 @@ This file contains the .NET 5-specific targets to customize ILLink Include="ProguardConfiguration" Value="$(_ProguardProjectConfiguration)" /> + <_TrimmerCustomData Include="AndroidKnownDesignerAssemblies" Value="@(AndroidKnownDesignerAssemblies)" /> @@ -1464,6 +1465,7 @@ because xbuild doesn't support framework reference assemblies. UseDesignerAssembly="$(AndroidUseDesignerAssembly)" Deterministic="$(Deterministic)" UsingAndroidNETSdk="$(UsingAndroidNETSdk)" + KnownDesignerAssemblies="@(AndroidKnownDesignerAssemblies)" /> From a398c96e4ed686f9ba4c0b41d901f16149660d42 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 13 Oct 2023 13:37:21 +0100 Subject: [PATCH 07/15] Add docs --- .../guides/building-apps/build-items.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 6da648100fe..e1f9335f899 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -174,6 +174,29 @@ installing app bundles. This build action was introduced in Xamarin.Android 11.3. +## AndroidKnownDesignerAssemblies + +This is an ItemGroup that is used to work around issues when upgrading the old `Resource.designer.cs` +system to the new Resource Assembly system. This can happen if an assembly is referencing a +`Resource.designer.cs` class from anther assembly which was built on an older framework. +If you see runtime errors such as + +``` +System.TypeLoadException: 'Could not resolve type with token 010001d8 from typeref (expected class 'Style' in assembly '')' +``` + +If you see this you can figure out which assembly is missing the designer and add its name to this +ItemGroup + +``` + +``` + +This will enable some additional processing to ensure the IL is fixed. + +This build item was introduced in .NET 8. + + ## AndroidNativeLibrary [Native libraries](~/android/platform/native-libraries.md) From 7c6bf0d229702660a4e33618676c65cd6a93068e Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 13 Oct 2023 14:21:21 +0100 Subject: [PATCH 08/15] Update docs --- .../guides/building-apps/build-items.md | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index e1f9335f899..1a3cda0eb2e 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -185,7 +185,40 @@ If you see runtime errors such as System.TypeLoadException: 'Could not resolve type with token 010001d8 from typeref (expected class 'Style' in assembly '')' ``` -If you see this you can figure out which assembly is missing the designer and add its name to this +or build errors such as + +``` +error NETSDK1144: Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false +``` + +or + +``` +Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1013: Error processing '…/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'. + ---> System.ArgumentNullException: Value cannot be null. (Parameter 'key') + at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) + at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) + at Mono.Linker.AssemblyResolver.GetAssembly(String file) + at Mono.Linker.AssemblyResolver.ResolveFromReferences(AssemblyNameReference name) + at Mono.Linker.AssemblyResolver.Resolve(AssemblyNameReference name, Boolean probing) + at Mono.Linker.LinkContext.TryResolve(AssemblyNameReference name) + at Mono.Linker.Steps.ProcessLinkerXmlBase.ProcessAssemblies(XPathNavigator nav) + at Mono.Linker.Steps.ProcessLinkerXmlBase.ProcessXml(Boolean stripResource, Boolean ignoreResource) + --- End of inner exception stack trace --- + at Mono.Linker.Steps.ProcessLinkerXmlBase.ProcessXml(Boolean stripResource, Boolean ignoreResource) + at Mono.Linker.Steps.DescriptorMarker.Mark() + at Mono.Linker.Steps.ResolveFromXmlStep.Process() + at Mono.Linker.Steps.BaseStep.Process(LinkContext context) + at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step) + at Mono.Linker.Pipeline.Process(LinkContext context) + at Mono.Linker.Driver.Run(ILogger customLogger) + at Mono.Linker.Driver.Main(String[] args) +The command exited with code 134. +``` + +You can make use of this ItemGroup to work around these issues. + +You need to figure out which assembly is missing the designer and add its name to this ItemGroup ``` From 9aae2b76a334a775ccdd51348cb7512ab6529169 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 13 Oct 2023 14:38:42 +0100 Subject: [PATCH 09/15] Fix up variable nanme --- .../Linker/MonoDroid.Tuner/LinkDesignerBase.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index 040939171b0..292ac240180 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -67,9 +67,9 @@ internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplic } if (string.IsNullOrEmpty(designerFullName)) { // Check for known designers which have been removed. - foreach (var d in KnownDesignerAssemblies) { - if (string.Compare (d, assembly.Name.Name, StringComparison.Ordinal) == 0) { - designer = new TypeDefinition (d, "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); + foreach (var knownDesigner in KnownDesignerAssemblies) { + if (string.Compare (knownDesigner, assembly.Name.Name, StringComparison.Ordinal) == 0) { + designer = new TypeDefinition (knownDesigner, "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass); return true; } From 9dfadda44e0336c0e51d3355a1dc6fb9c1d99ab7 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 13 Oct 2023 18:19:01 +0100 Subject: [PATCH 10/15] Remove errors which are not needed --- .../guides/building-apps/build-items.md | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 1a3cda0eb2e..47bb0f6c25f 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -185,37 +185,6 @@ If you see runtime errors such as System.TypeLoadException: 'Could not resolve type with token 010001d8 from typeref (expected class 'Style' in assembly '')' ``` -or build errors such as - -``` -error NETSDK1144: Optimizing assemblies for size failed. Optimization can be disabled by setting the PublishTrimmed property to false -``` - -or - -``` -Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1013: Error processing '…/dotnet-sdk-8.0.100-rc.1.23455.8-osx-x64/packs/Microsoft.Android.Sdk.Darwin/34.0.0-rc.1.432/targets/../PreserveLists/Mono.Android.xml'. - ---> System.ArgumentNullException: Value cannot be null. (Parameter 'key') - at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) - at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) - at Mono.Linker.AssemblyResolver.GetAssembly(String file) - at Mono.Linker.AssemblyResolver.ResolveFromReferences(AssemblyNameReference name) - at Mono.Linker.AssemblyResolver.Resolve(AssemblyNameReference name, Boolean probing) - at Mono.Linker.LinkContext.TryResolve(AssemblyNameReference name) - at Mono.Linker.Steps.ProcessLinkerXmlBase.ProcessAssemblies(XPathNavigator nav) - at Mono.Linker.Steps.ProcessLinkerXmlBase.ProcessXml(Boolean stripResource, Boolean ignoreResource) - --- End of inner exception stack trace --- - at Mono.Linker.Steps.ProcessLinkerXmlBase.ProcessXml(Boolean stripResource, Boolean ignoreResource) - at Mono.Linker.Steps.DescriptorMarker.Mark() - at Mono.Linker.Steps.ResolveFromXmlStep.Process() - at Mono.Linker.Steps.BaseStep.Process(LinkContext context) - at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step) - at Mono.Linker.Pipeline.Process(LinkContext context) - at Mono.Linker.Driver.Run(ILogger customLogger) - at Mono.Linker.Driver.Main(String[] args) -The command exited with code 134. -``` - You can make use of this ItemGroup to work around these issues. You need to figure out which assembly is missing the designer and add its name to this From 639188b6339f97ed7ec67c8ea48be5a929053f23 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Mon, 16 Oct 2023 13:16:02 +0100 Subject: [PATCH 11/15] Try this --- .../guides/building-apps/build-items.md | 25 -------- .../FixLegacyResourceDesignerStep.cs | 32 ++++++++-- .../MonoDroid.Tuner/LinkDesignerBase.cs | 58 ++++++++++++------- .../Microsoft.Android.Sdk.ILLink.targets | 1 - .../Tasks/LinkAssembliesNoShrink.cs | 7 +-- .../Xamarin.Android.Common.targets | 2 - 6 files changed, 66 insertions(+), 59 deletions(-) diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 47bb0f6c25f..6da648100fe 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -174,31 +174,6 @@ installing app bundles. This build action was introduced in Xamarin.Android 11.3. -## AndroidKnownDesignerAssemblies - -This is an ItemGroup that is used to work around issues when upgrading the old `Resource.designer.cs` -system to the new Resource Assembly system. This can happen if an assembly is referencing a -`Resource.designer.cs` class from anther assembly which was built on an older framework. -If you see runtime errors such as - -``` -System.TypeLoadException: 'Could not resolve type with token 010001d8 from typeref (expected class 'Style' in assembly '')' -``` - -You can make use of this ItemGroup to work around these issues. - -You need to figure out which assembly is missing the designer and add its name to this -ItemGroup - -``` - -``` - -This will enable some additional processing to ensure the IL is fixed. - -This build item was introduced in .NET 8. - - ## AndroidNativeLibrary [Native libraries](~/android/platform/native-libraries.md) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs index 793320858ee..411888f2be8 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs @@ -143,6 +143,32 @@ string GetNativeTypeNameFromManagedTypeName (string name) } } + string GetFixupKey (Instruction instruction, string designerFullName) + { + string line = instruction.ToString (); + int idx = line.IndexOf (designerFullName, StringComparison.Ordinal); + if (idx >= 0) { + return line.Substring (idx + designerFullName.Length); + } + if (instruction.Operand is FieldReference fieldRef && + (fieldRef.DeclaringType?.ToString()?.Contains (".Resource/") ?? false)) { + var canResolve = false; + try { + var resolved = fieldRef.Resolve (); + canResolve = resolved != null; + } catch (Exception) { + } + if (canResolve) + return null; + var type = fieldRef.DeclaringType.FullName; + var s = type.LastIndexOf ('/'); + type = type.Substring (s + 1); + var key = type + "::" + fieldRef.Name; + return key; + } + return null; + } + protected override void FixBody (MethodBody body, TypeDefinition designer) { // replace @@ -156,10 +182,8 @@ protected override void FixBody (MethodBody body, TypeDefinition designer) { if (i.OpCode != OpCodes.Ldsfld) continue; - string line = i.ToString (); - int idx = line.IndexOf (designerFullName, StringComparison.Ordinal); - if (idx >= 0) { - string key = line.Substring (idx + designerFullName.Length); + var key = GetFixupKey (i, designerFullName); + if (key != null) { LogMessage ($"Looking for {key}."); var found = lookup.TryGetValue (key, out MethodDefinition method); if (!found) { diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index 292ac240180..bfa6398d90e 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -19,8 +19,6 @@ public abstract class LinkDesignerBase : BaseStep { HashSet allAssemblies = new (); HashSet processedAssemblies = new (); - public string[] KnownDesignerAssemblies { get; set; } = Array.Empty (); - public virtual void LogMessage (string message) { Context.LogMessage (message); @@ -65,18 +63,43 @@ internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplic } } + if (string.IsNullOrEmpty(designerFullName)) { - // Check for known designers which have been removed. - foreach (var knownDesigner in KnownDesignerAssemblies) { - if (string.Compare (knownDesigner, assembly.Name.Name, StringComparison.Ordinal) == 0) { - designer = new TypeDefinition (knownDesigner, "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); + var memberRefs = assembly.MainModule.GetMemberReferences (); + var memberIdx = 0; + LogMessage ($"# jonp: LinkDesignerBase.FindResourceDesigner: looking at assembly: {assembly.FullName};"); + foreach (var memberRef in memberRefs) { + memberIdx++; + string declaringType = memberRef.DeclaringType?.ToString () ?? string.Empty; + if (!declaringType.Contains (".Resource/")) { + continue; + } + if (declaringType.Contains ("_Microsoft.Android.Resource.Designer")) { + continue; + } + LogMessage ($"# jonp: memberRefs[{memberIdx}].Name={memberRef?.Name}; .FullName={memberRef.FullName}; .DeclaringType={memberRef.DeclaringType}"); + var resolved = false; + try { + var def = memberRef.Resolve (); + resolved = def != null; + LogMessage ($"# jonp: memberRef '{memberRef?.Name}' resolved to: {def?.FullName} [{def != null} {def?.GetType().FullName}]"); + } + catch (Exception _ex) { + LogMessage ($"# jonp: exception resolving memberRef {memberRef?.Name}! {_ex}"); + resolved = false; + } + if (!resolved) { + LogMessage ($"# jonp: Adding _Linker.Generated.Resource to {assembly.Name.Name}"); + designer = new TypeDefinition ("_Linker.Generated", "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass); return true; } } - return false; } + if (string.IsNullOrEmpty(designerFullName)) + return false; + foreach (ModuleDefinition module in assembly.Modules) { foreach (TypeDefinition type in module.Types) @@ -228,15 +251,6 @@ protected override void ProcessAssembly (AssemblyDefinition assembly) } } - protected override void Process () - { -#if ILLINK - if (Context.TryGetCustomData ("AndroidKnownDesignerAssemblies", out string knownDesignerAssemblies)) { - KnownDesignerAssemblies = knownDesignerAssemblies.Split (';'); - } -#endif - } - protected override void EndProcess () { // This is a "second pass" to fix assemblies with references to assemblies with a designer @@ -249,12 +263,12 @@ protected override void EndProcess () if (action == AssemblyAction.Delete) continue; - foreach (var processedAssembly in processedAssemblies) { - if (ProcessAssemblyDesignerSecondPass (assembly, processedAssembly) && - (action == AssemblyAction.Skip || action == AssemblyAction.Copy)) { - Annotations.SetAction (assembly, AssemblyAction.Save); - } - } + // foreach (var processedAssembly in processedAssemblies) { + // if (ProcessAssemblyDesignerSecondPass (assembly, processedAssembly) && + // (action == AssemblyAction.Skip || action == AssemblyAction.Copy)) { + // Annotations.SetAction (assembly, AssemblyAction.Save); + // } + // } } } } diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets index 880c3abc4c1..7400de192ff 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets @@ -45,7 +45,6 @@ This file contains the .NET 5-specific targets to customize ILLink Include="ProguardConfiguration" Value="$(_ProguardProjectConfiguration)" /> - <_TrimmerCustomData Include="AndroidKnownDesignerAssemblies" Value="@(AndroidKnownDesignerAssemblies)" /> @@ -1465,7 +1464,6 @@ because xbuild doesn't support framework reference assemblies. UseDesignerAssembly="$(AndroidUseDesignerAssembly)" Deterministic="$(Deterministic)" UsingAndroidNETSdk="$(UsingAndroidNETSdk)" - KnownDesignerAssemblies="@(AndroidKnownDesignerAssemblies)" /> From 1f41e9e08c7a490abbc88563197da2e48a957f45 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 16 Oct 2023 15:58:18 -0500 Subject: [PATCH 12/15] Refactor and remove unused code The "new fix" doesn't require us to touch as much code. I could restore much of the original code to make the diff smaller. --- .../FixLegacyResourceDesignerStep.cs | 22 ++++---- .../MonoDroid.Tuner/LinkDesignerBase.cs | 50 ++----------------- .../RemoveResourceDesignerStep.cs | 2 +- .../Tasks/LinkAssembliesNoShrink.cs | 28 +---------- 4 files changed, 15 insertions(+), 87 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs index 411888f2be8..e07ec5e9751 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs @@ -34,8 +34,6 @@ public class FixLegacyResourceDesignerStep : LinkDesignerBase protected override void EndProcess () { - base.EndProcess (); - if (designerAssembly != null) { LogMessage ($" Setting Action on {designerAssembly.Name} to Link."); Annotations.SetAction (designerAssembly, AssemblyAction.Link); @@ -70,20 +68,18 @@ protected override void LoadDesigner () } } - internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly, TypeDefinition designer = null) + internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly) { - if (designer is not null) { - LogMessage ($" {assembly.Name.Name} has an assembly reference with a designer."); - } else if (!FindResourceDesigner (assembly, mainApplication: false, out designer, out _)) { + if (!FindResourceDesigner (assembly, mainApplication: false, out TypeDefinition designer, out CustomAttribute designerAttribute)) { LogMessage ($" {assembly.Name.Name} has no designer. "); return false; - } else { - LogMessage ($" {assembly.Name.Name} has a designer. "); - LogMessage ($" BaseType: {designer.BaseType.FullName}. "); - if (designer.BaseType.FullName == $"{DesignerAssemblyNamespace}.Resource") { - LogMessage ($" {assembly.Name.Name} has already been processed. "); - return false; - } + } + + LogMessage ($" {assembly.Name.Name} has a designer. "); + LogMessage ($" BaseType: {designer.BaseType.FullName}. "); + if (designer.BaseType.FullName == $"{DesignerAssemblyNamespace}.Resource") { + LogMessage ($" {assembly.Name.Name} has already been processed. "); + return false; } // This is expected for the first call, in diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index bfa6398d90e..7745b6b3b77 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -16,9 +16,6 @@ namespace MonoDroid.Tuner { public abstract class LinkDesignerBase : BaseStep { - HashSet allAssemblies = new (); - HashSet processedAssemblies = new (); - public virtual void LogMessage (string message) { Context.LogMessage (message); @@ -38,7 +35,7 @@ public virtual AssemblyDefinition Resolve (AssemblyNameReference name) return Context.Resolve (name); } - internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute) + protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplication, out TypeDefinition designer, out CustomAttribute designerAttribute) { string designerFullName = null; designer = null; @@ -111,7 +108,7 @@ internal bool FindResourceDesigner (AssemblyDefinition assembly, bool mainApplic } } } - + return false; } @@ -236,7 +233,6 @@ protected void FixupAssemblyTypes (AssemblyDefinition assembly, TypeDefinition d protected override void ProcessAssembly (AssemblyDefinition assembly) { - allAssemblies.Add (assembly); LoadDesigner (); var action = Annotations.HasAction (assembly) ? Annotations.GetAction (assembly) : AssemblyAction.Skip; @@ -244,50 +240,12 @@ protected override void ProcessAssembly (AssemblyDefinition assembly) return; if (ProcessAssemblyDesigner (assembly)) { - if (action == AssemblyAction.Skip || action == AssemblyAction.Copy) { + if (action == AssemblyAction.Skip || action == AssemblyAction.Copy) Annotations.SetAction (assembly, AssemblyAction.Save); - processedAssemblies.Add (assembly); - } } } - protected override void EndProcess () - { - // This is a "second pass" to fix assemblies with references to assemblies with a designer - if (processedAssemblies.Count > 0) { - foreach (var assembly in allAssemblies) { - if (processedAssemblies.Contains (assembly)) - continue; - - var action = Annotations.HasAction (assembly) ? Annotations.GetAction (assembly) : AssemblyAction.Skip; - if (action == AssemblyAction.Delete) - continue; - - // foreach (var processedAssembly in processedAssemblies) { - // if (ProcessAssemblyDesignerSecondPass (assembly, processedAssembly) && - // (action == AssemblyAction.Skip || action == AssemblyAction.Copy)) { - // Annotations.SetAction (assembly, AssemblyAction.Save); - // } - // } - } - } - } - - public bool ProcessAssemblyDesignerSecondPass (AssemblyDefinition assembly, AssemblyDefinition processedAssembly) - { - if (assembly.MainModule.AssemblyReferences.Any (r => r.FullName == processedAssembly.Name.FullName)) { - LogMessage ($" {assembly.Name.Name} has an assembly reference to {processedAssembly.Name}"); - if (FindResourceDesigner (processedAssembly, mainApplication: false, out TypeDefinition designer, out _) && - ProcessAssemblyDesigner (assembly, designer)) { - return true; - } else { - LogMessage ($" {processedAssembly.Name} did not have a designer"); - } - } - return false; - } - - internal abstract bool ProcessAssemblyDesigner (AssemblyDefinition assemblyDefinition, TypeDefinition designer = null); + internal abstract bool ProcessAssemblyDesigner (AssemblyDefinition assemblyDefinition); protected abstract void LoadDesigner (); protected abstract void FixBody (MethodBody body, TypeDefinition designer); } diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs index 28eed903fd8..2ef7e074cdc 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/RemoveResourceDesignerStep.cs @@ -84,7 +84,7 @@ protected override void FixBody (MethodBody body, TypeDefinition designer) } } - internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly, TypeDefinition designer = null) + internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly) { if (mainDesigner == null) return false; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs index 261bca0f3d7..2d42039fce2 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/LinkAssembliesNoShrink.cs @@ -5,7 +5,6 @@ using Mono.Cecil; using System; using System.IO; -using System.Collections.Generic; using Microsoft.Android.Build.Tasks; namespace Xamarin.Android.Tasks @@ -68,8 +67,6 @@ public override bool RunTask () var fixAbstractMethodsStep = new FixAbstractMethodsStep (resolver, cache, Log); var addKeepAliveStep = new AddKeepAlivesStep (resolver, cache, Log, UsingAndroidNETSdk); var fixLegacyResourceDesignerStep = new FixLegacyResourceDesignerStep (resolver, Log); - Dictionary allAssemblies = new (); - HashSet processedAssemblies = new (); for (int i = 0; i < SourceFiles.Length; i++) { var source = SourceFiles [i]; var destination = DestinationFiles [i]; @@ -97,14 +94,9 @@ public override bool RunTask () if (assemblyDefinition == null) assemblyDefinition = resolver.GetAssembly (source.ItemSpec); - allAssemblies.Add (assemblyDefinition, destination); - bool save = fixAbstractMethodsStep.FixAbstractMethods (assemblyDefinition); - if (UseDesignerAssembly) { + if (UseDesignerAssembly) save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesigner (assemblyDefinition); - if (save) - processedAssemblies.Add (assemblyDefinition); - } if (AddKeepAlives) save |= addKeepAliveStep.AddKeepAlives (assemblyDefinition); if (save) { @@ -117,24 +109,6 @@ public override bool RunTask () CopyIfChanged (source, destination); } - - // Run a "second pass" for the FixLegacyResourceDesignerStep - if (UseDesignerAssembly && processedAssemblies.Count > 0) { - foreach (var kvp in allAssemblies) { - var assembly = kvp.Key; - var destination = kvp.Value; - if (processedAssemblies.Contains (assembly)) - continue; - bool save = false; - foreach (var processedAssembly in processedAssemblies) { - save |= fixLegacyResourceDesignerStep.ProcessAssemblyDesignerSecondPass (assembly, processedAssembly); - } - if (save) { - writerParameters.WriteSymbols = assembly.MainModule.HasSymbols; - assembly.Write (destination.ItemSpec, writerParameters); - } - } - } } return !Log.HasLoggedErrors; From 0a194e6eef50c2ea9c1a52c2dc680e29dfe96374 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 16 Oct 2023 16:06:06 -0500 Subject: [PATCH 13/15] Remove `#jonp` log messages --- .../Linker/MonoDroid.Tuner/LinkDesignerBase.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index 7745b6b3b77..db82bdf45c0 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -62,9 +62,9 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli } if (string.IsNullOrEmpty(designerFullName)) { + LogMessage ($"Inspecting member references for assembly: {assembly.FullName};"); var memberRefs = assembly.MainModule.GetMemberReferences (); var memberIdx = 0; - LogMessage ($"# jonp: LinkDesignerBase.FindResourceDesigner: looking at assembly: {assembly.FullName};"); foreach (var memberRef in memberRefs) { memberIdx++; string declaringType = memberRef.DeclaringType?.ToString () ?? string.Empty; @@ -74,19 +74,18 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli if (declaringType.Contains ("_Microsoft.Android.Resource.Designer")) { continue; } - LogMessage ($"# jonp: memberRefs[{memberIdx}].Name={memberRef?.Name}; .FullName={memberRef.FullName}; .DeclaringType={memberRef.DeclaringType}"); var resolved = false; try { var def = memberRef.Resolve (); - resolved = def != null; - LogMessage ($"# jonp: memberRef '{memberRef?.Name}' resolved to: {def?.FullName} [{def != null} {def?.GetType().FullName}]"); - } - catch (Exception _ex) { - LogMessage ($"# jonp: exception resolving memberRef {memberRef?.Name}! {_ex}"); + if (resolved = def != null) { + LogMessage ($"Resolved member `{memberRef?.Name}`"); + } + } catch (Exception ex) { + LogMessage ($"Exception resolving member `{memberRef?.Name}`: {ex}"); resolved = false; } if (!resolved) { - LogMessage ($"# jonp: Adding _Linker.Generated.Resource to {assembly.Name.Name}"); + LogMessage ($"Adding _Linker.Generated.Resource to {assembly.Name.Name}"); designer = new TypeDefinition ("_Linker.Generated", "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass); return true; From 9f6ce51ba8a0caf0b9651c02baec9feed6937eb5 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 16 Oct 2023 16:33:45 -0500 Subject: [PATCH 14/15] Remove newline --- .../Linker/MonoDroid.Tuner/LinkDesignerBase.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index db82bdf45c0..a51e04c0f86 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -107,7 +107,6 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli } } } - return false; } From 8e75f834d3b5a6f6074d6b017df930fdb2aeaca1 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 17 Oct 2023 09:44:06 +0100 Subject: [PATCH 15/15] Add more logging --- .../Linker/MonoDroid.Tuner/LinkDesignerBase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs index a51e04c0f86..d999506b286 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs @@ -64,9 +64,7 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli if (string.IsNullOrEmpty(designerFullName)) { LogMessage ($"Inspecting member references for assembly: {assembly.FullName};"); var memberRefs = assembly.MainModule.GetMemberReferences (); - var memberIdx = 0; foreach (var memberRef in memberRefs) { - memberIdx++; string declaringType = memberRef.DeclaringType?.ToString () ?? string.Empty; if (!declaringType.Contains (".Resource/")) { continue; @@ -85,7 +83,7 @@ protected bool FindResourceDesigner (AssemblyDefinition assembly, bool mainAppli resolved = false; } if (!resolved) { - LogMessage ($"Adding _Linker.Generated.Resource to {assembly.Name.Name}"); + LogMessage ($"Adding _Linker.Generated.Resource to {assembly.Name.Name}. Could not resolve {memberRef?.Name} : {declaringType}"); designer = new TypeDefinition ("_Linker.Generated", "Resource", TypeAttributes.Public | TypeAttributes.AnsiClass); designer.BaseType = new TypeDefinition ("System", "Object", TypeAttributes.Public | TypeAttributes.AnsiClass); return true;