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..b52dadb5f2bb
--- /dev/null
+++ b/tests/mmptest/src/LinkerTests.cs
@@ -0,0 +1,41 @@
+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
+ {
+ 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 => {
+ 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);
+ }
+ });
+ }
+ }
+}
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
+}