From c29466b5dd1aa20b73038feebe9b6edb2e93e747 Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Thu, 6 Apr 2017 14:18:50 -0500 Subject: [PATCH 1/3] Add XM SDK + LinkSkip test --- tests/mmptest/mmptest.csproj | 1 + tests/mmptest/src/LinkerTests.cs | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/mmptest/src/LinkerTests.cs diff --git a/tests/mmptest/mmptest.csproj b/tests/mmptest/mmptest.csproj index c67064af9527..19c1da454521 100644 --- a/tests/mmptest/mmptest.csproj +++ b/tests/mmptest/mmptest.csproj @@ -96,6 +96,7 @@ unit\aot.cs + diff --git a/tests/mmptest/src/LinkerTests.cs b/tests/mmptest/src/LinkerTests.cs new file mode 100644 index 000000000000..3aaae47afe11 --- /dev/null +++ b/tests/mmptest/src/LinkerTests.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using System.Reflection; + +namespace Xamarin.MMP.Tests +{ + public partial class MMPTests + { + [Test] + public void UnifiedLinkingSDK_WithAllNonProductSkipped_Builds () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "SdkOnly--linkskip=mscorlib.dll --linkskip=System.Core.dll --linkskip=System.dll" }; + TI.TestUnifiedExecutable (test); + }); + } + } +} From 9d8c754eb80d031448f1514c39337e700a1b5ff4 Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Fri, 7 Apr 2017 13:26:24 -0500 Subject: [PATCH 2/3] Current work --- tools/linker/MobileSweepStep.cs | 1 + tools/mmp/Makefile | 2 +- tools/mmp/Tuning.cs | 40 ++++++++++++------- tools/mmp/driver.cs | 5 ++- .../linker/MonoMac.Tuner/MonoMacMarkStep.cs | 12 +++++- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/tools/linker/MobileSweepStep.cs b/tools/linker/MobileSweepStep.cs index 1583a93d41ee..345bc1118bd7 100644 --- a/tools/linker/MobileSweepStep.cs +++ b/tools/linker/MobileSweepStep.cs @@ -27,6 +27,7 @@ protected override void Process () var assemblies = Context.GetAssemblies (); foreach (var assembly in assemblies) { CurrentAction = Annotations.GetAction (assembly); + Console.WriteLine ($"{CurrentAction} on {assembly.Name.Name}"); switch (CurrentAction) { case AssemblyAction.Link: case AssemblyAction.Save: diff --git a/tools/mmp/Makefile b/tools/mmp/Makefile index 9eb4821898ed..4ff0f0b799b2 100644 --- a/tools/mmp/Makefile +++ b/tools/mmp/Makefile @@ -132,7 +132,7 @@ LOCAL_MMP = \ Mono.Cecil.Mdb.dll \ mmp.exe: Makefile $(MONO_CECIL_DLL) $(MONO_CECIL_MDB_DLL) $(mmp_sources) config config_mobile Info.plist.tmpl $(tuner_sources) $(linker_resources) - $(Q_MCS) $(SYSTEM_MCS) -unsafe -out:mmp.exe $(DEFINES) -r:$(MONO_CECIL_DLL) -r:$(MONO_CECIL_MDB_DLL) -r:Mono.Security.dll -resource:config -resource:config_mobile -resource:machine.4_5.config -resource:Info.plist.tmpl $(linker_resources:%=-resource:%) $(tuner_sources) $(mmp_sources) + $(Q_MCS) $(SYSTEM_MCS) -unsafe -out:mmp.exe -debug $(DEFINES) -r:$(MONO_CECIL_DLL) -r:$(MONO_CECIL_MDB_DLL) -r:Mono.Security.dll -resource:config -resource:config_mobile -resource:machine.4_5.config -resource:Info.plist.tmpl $(linker_resources:%=-resource:%) $(tuner_sources) $(mmp_sources) $(Q) cp $(MONO_CECIL_DLL) $(MONO_CECIL_MDB_DLL) . Mono.Cecil.dll: $(MONO_CECIL_DLL) diff --git a/tools/mmp/Tuning.cs b/tools/mmp/Tuning.cs index be3412d8850d..3cca36fb7143 100644 --- a/tools/mmp/Tuning.cs +++ b/tools/mmp/Tuning.cs @@ -34,6 +34,7 @@ public class LinkerOptions { internal PInvokeWrapperGenerator MarshalNativeExceptionsState { get; set; } internal RuntimeOptions RuntimeOptions { get; set; } public bool SkipExportedSymbolsInSdkAssemblies { get; set; } + public bool FullLimitedLinking { get; set; } public static I18nAssemblies ParseI18nAssemblies (string i18n) { @@ -113,7 +114,10 @@ public static void Process (LinkerOptions options, out LinkContext context, out static LinkContext CreateLinkContext (LinkerOptions options, Pipeline pipeline) { var context = new MonoMacLinkContext (pipeline, options.Resolver); - context.CoreAction = AssemblyAction.Link; + + context.CoreAction = options.FullLimitedLinking ? AssemblyAction.Copy : AssemblyAction.Link; + context.DefaultAction = options.FullLimitedLinking ? AssemblyAction.Copy : AssemblyAction.Link; + context.LinkSymbols = options.LinkSymbols; if (options.LinkSymbols) { context.SymbolReaderProvider = new MdbReaderProvider (); @@ -140,7 +144,7 @@ static Pipeline CreatePipeline (LinkerOptions options) if (options.LinkMode != LinkMode.None) pipeline.AppendStep (new BlacklistStep ()); - pipeline.AppendStep (new CustomizeMacActions (options.LinkMode, options.SkippedAssemblies)); + pipeline.AppendStep (new CustomizeMacActions (options.LinkMode, options.FullLimitedLinking, options.SkippedAssemblies)); // We need to store the Field attribute in annotations, since it may end up removed. pipeline.AppendStep (new ProcessExportedFields ()); @@ -150,7 +154,7 @@ static Pipeline CreatePipeline (LinkerOptions options) pipeline.AppendStep (new SubStepDispatcher { new ApplyPreserveAttribute (), - new CoreRemoveSecurity (), +// new CoreRemoveSecurity (), new OptimizeGeneratedCodeSubStep (options.EnsureUIThread), new RemoveUserResourcesSubStep (), new CoreRemoveAttributes (), @@ -161,7 +165,7 @@ static Pipeline CreatePipeline (LinkerOptions options) pipeline.AppendStep (new MonoMacPreserveCode (options)); pipeline.AppendStep (new PreserveCrypto ()); - pipeline.AppendStep (new MonoMacMarkStep ()); + pipeline.AppendStep (new MonoMacMarkStep (options.FullLimitedLinking)); pipeline.AppendStep (new MacRemoveResources (options)); pipeline.AppendStep (new MobileSweepStep (options.LinkSymbols)); pipeline.AppendStep (new CleanStep ()); @@ -224,28 +228,34 @@ static ResolveFromXmlStep GetResolveStep (string filename) public class CustomizeMacActions : CustomizeActions { LinkMode link_mode; + bool limitedLinking; - public CustomizeMacActions (LinkMode mode, IEnumerable skipped_assemblies) + bool NoLinking => link_mode == LinkMode.None; + bool XMOnlyLinking => link_mode == LinkMode.SDKOnly && limitedLinking; + + public CustomizeMacActions (LinkMode mode, bool fullLimitedLinking, IEnumerable skipped_assemblies) : base (mode == LinkMode.SDKOnly, skipped_assemblies) { link_mode = mode; + limitedLinking = fullLimitedLinking; } - - protected override bool IsLinked (AssemblyDefinition assembly) - { - if (link_mode == LinkMode.None) - return false; - - return base.IsLinked (assembly); - } - + protected override void ProcessAssembly (AssemblyDefinition assembly) { - if (link_mode == LinkMode.None) { + if (NoLinking) { Annotations.SetAction (assembly, AssemblyAction.Copy); return; } + if (XMOnlyLinking) { + if (assembly.Name.Name == "Xamarin.Mac") + Annotations.SetAction (assembly, AssemblyAction.Link); + else + Annotations.SetAction (assembly, AssemblyAction.Copy); + return; + + } + base.ProcessAssembly (assembly); } } diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index a657e9eb86a3..1069e93d9d27 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -468,9 +468,9 @@ static void Main2 (string [] args) if (IsUnified == IsClassic || (IsUnified && IsUnifiedCount != 1)) throw new Exception ("IsClassic/IsUnified/IsUnifiedMobile/IsUnifiedFullSystemFramework/IsUnifiedFullXamMacFramework logic regression"); - if ((IsUnifiedFullSystemFramework || IsUnifiedFullXamMacFramework) && (App.LinkMode != LinkMode.None)) + if ((IsUnifiedFullSystemFramework || IsUnifiedFullXamMacFramework) && (App.LinkMode == LinkMode.All)) throw new MonoMacException (2007, true, - "Xamarin.Mac Unified API against a full .NET framework does not support linking. Pass the -nolink flag."); + "Xamarin.Mac Unified Full API against a full .NET framework does not support linking except against the SDK (Xamarin.Mac) only. Pass the -nolink flag."); if (App.LinkMode != LinkMode.None && is_extension) { App.LinkMode = LinkMode.None; @@ -1406,6 +1406,7 @@ static IDictionary> Link () Registrar = (StaticRegistrar) BuildTarget.StaticRegistrar, }, SkipExportedSymbolsInSdkAssemblies = !embed_mono, + FullLimitedLinking = IsUnifiedFullSystemFramework || IsUnifiedFullXamMacFramework }; linker_options = options; diff --git a/tools/mmp/linker/MonoMac.Tuner/MonoMacMarkStep.cs b/tools/mmp/linker/MonoMac.Tuner/MonoMacMarkStep.cs index b4887ddd5d24..d6fd9e6f5cb9 100644 --- a/tools/mmp/linker/MonoMac.Tuner/MonoMacMarkStep.cs +++ b/tools/mmp/linker/MonoMac.Tuner/MonoMacMarkStep.cs @@ -23,6 +23,13 @@ public class MonoMacMarkStep : CoreMarkStep { List Exceptions = new List (); + bool FullLimitedLinking; + + public MonoMacMarkStep (bool fullLimitedLinking) + { + FullLimitedLinking = fullLimitedLinking; + } + public override void Process (LinkContext context) { PInvokeModules = (context as MonoMacLinkContext).PInvokeModules; @@ -37,6 +44,9 @@ public override void Process (LinkContext context) protected override TypeDefinition MarkType (TypeReference reference) { + if (FullLimitedLinking && reference.Name != "Xamarin.Mac") + return null; + TypeDefinition type = base.MarkType (GetOriginalType (reference)); if (type == null) return null; @@ -199,4 +209,4 @@ void ProcessXamarinMac (TypeDefinition type) } } } -} \ No newline at end of file +} From 18209f056d192021d8d4fb43d6db7db24875d40f Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Fri, 7 Apr 2017 15:28:03 -0500 Subject: [PATCH 3/3] Fix UnifiedLinkingSDK_WithAllNonProductSkipped_Builds --- tests/mmptest/src/LinkerTests.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/mmptest/src/LinkerTests.cs b/tests/mmptest/src/LinkerTests.cs index 3aaae47afe11..b52dadb5f2bb 100644 --- a/tests/mmptest/src/LinkerTests.cs +++ b/tests/mmptest/src/LinkerTests.cs @@ -11,12 +11,30 @@ namespace Xamarin.MMP.Tests { public partial class MMPTests { + int GetNumberOfTypesInLibrary (string path) + { + string output = TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Versions/Current/Commands/monop", new StringBuilder ("-r:" + path), "GetNumberOfTypesInLibrary"); + string[] splitBuildOutput = output.Split (new string[] { Environment.NewLine }, StringSplitOptions.None); + string outputLine = splitBuildOutput.First (x => x.StartsWith ("Total:")); + string numberSize = outputLine.Split (':')[1]; + string number = numberSize.Split (' ')[1]; + return int.Parse (number); + } + [Test] public void UnifiedLinkingSDK_WithAllNonProductSkipped_Builds () { RunMMPTest (tmpDir => { - TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = "SdkOnly--linkskip=mscorlib.dll --linkskip=System.Core.dll --linkskip=System.dll" }; + string[] dependencies = { "mscorlib", "System.Core", "System" }; + string config = "SdkOnly--linkskip=" + dependencies.Aggregate ((arg1, arg2) => arg1 + " --linkskip=" + arg2) + ""; + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { CSProjConfig = config }; TI.TestUnifiedExecutable (test); + foreach (string dep in dependencies) { + string outputDep = Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MonoBundle", dep + ".dll"); + string baseDep = Path.Combine (TI.FindRootDirectory (), "Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/Xamarin.Mac/", dep + ".dll"); + + Assert.AreEqual (GetNumberOfTypesInLibrary (baseDep), GetNumberOfTypesInLibrary (outputDep), "We linked a linkskip - " + dep + " with config:\n" + config); + } }); } }