From 50dd4f90697c135c80266563b013490bde88b4eb Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 29 Sep 2020 16:41:47 +0200 Subject: [PATCH] [dotnet-linker] Add a CollectUnmarkedMembersStep that will keep linked away types around for the static registrar. (#9722) The static registrar may need access to types that have been linked away, so store unmarked types so that the static registrar can access them later. This also makes all the monotouch-test variations green, so enable them all. Fixes this monotouch-test when all optimizations are enabled: MonoTouchFixtures.ObjCRuntime.RegistrarTest [FAIL] TestProtocolRegistration : UIApplicationDelegate/17669 Expected: True But was: False at MonoTouchFixtures.ObjCRuntime.RegistrarTest.TestProtocolRegistration() in xamarin-macios/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs:line 1350 --- .../xharness/Jenkins/TestVariationsFactory.cs | 2 - tools/dotnet-linker/SetupStep.cs | 3 ++ .../Steps/CollectUnmarkedMembers.cs | 37 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tools/dotnet-linker/Steps/CollectUnmarkedMembers.cs diff --git a/tests/xharness/Jenkins/TestVariationsFactory.cs b/tests/xharness/Jenkins/TestVariationsFactory.cs index e29c711ba722..0a22dd6ce0f8 100644 --- a/tests/xharness/Jenkins/TestVariationsFactory.cs +++ b/tests/xharness/Jenkins/TestVariationsFactory.cs @@ -93,8 +93,6 @@ IEnumerable GetTestData (RunTestTask test) case "iPhoneSimulator": switch (test.TestName) { case "monotouch-test": - if (test.TestProject.IsDotNetProject) - ignore = true; // The default is to run monotouch-test with the dynamic registrar (in the simulator), so that's already covered yield return new TestData { Variation = "Debug (LinkSdk)", Debug = true, Profiling = false, LinkMode = "LinkSdk", Ignored = ignore }; yield return new TestData { Variation = "Debug (static registrar)", MTouchExtraArgs = "--registrar:static", Debug = true, Profiling = false, Undefines = "DYNAMIC_REGISTRAR", Ignored = ignore }; diff --git a/tools/dotnet-linker/SetupStep.cs b/tools/dotnet-linker/SetupStep.cs index 82c7acc30e66..654047180298 100644 --- a/tools/dotnet-linker/SetupStep.cs +++ b/tools/dotnet-linker/SetupStep.cs @@ -46,6 +46,9 @@ protected override void Process () prelink_substeps.Add (new OptimizeGeneratedCodeSubStep ()); prelink_substeps.Add (new MarkNSObjects ()); prelink_substeps.Add (new PreserveSmartEnumConversionsSubStep ()); + prelink_substeps.Add (new CollectUnmarkedMembersSubStep ()); + + post_sweep_substeps.Add (new RemoveAttributesStep ()); } Steps.Add (new LoadNonSkippedAssembliesStep ()); diff --git a/tools/dotnet-linker/Steps/CollectUnmarkedMembers.cs b/tools/dotnet-linker/Steps/CollectUnmarkedMembers.cs new file mode 100644 index 000000000000..73ab545d9b6e --- /dev/null +++ b/tools/dotnet-linker/Steps/CollectUnmarkedMembers.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +using Mono.Cecil; +using Mono.Linker.Steps; + +namespace Xamarin.Linker { + // The static registrar may need access to information that has been linked away, + // in particular types and interfaces, so we need to store those somewhere + // so that the static registrar can access them. + public class CollectUnmarkedMembersSubStep : ConfigurationAwareSubStep { + Dictionary> ProtocolImplementations => Configuration.DerivedLinkContext.ProtocolImplementations; + + public override SubStepTargets Targets { + get { + return SubStepTargets.Type; + } + } + + public override void ProcessType (TypeDefinition type) + { + if (!Annotations.IsMarked (type)) + LinkContext.AddLinkedAwayType (type); + + if (type.HasInterfaces) { + foreach (var iface in type.Interfaces) { + if (Annotations.IsMarked (iface)) + continue; + + // This interface might be removed, so save it + if (!ProtocolImplementations.TryGetValue (type, out var list)) + ProtocolImplementations [type] = list = new List (); + list.Add (iface.InterfaceType.Resolve ()); + } + } + } + } +}