From ebb3873c4e437b35c6b3d645aa577bdee1455088 Mon Sep 17 00:00:00 2001
From: Marek Habersack <grendel@twistedcode.net>
Date: Mon, 15 Jul 2019 17:14:25 +0200
Subject: [PATCH] Remove Mono submodule

One of the goals behind the Mono SDK/archive was to enable product builds
without having the entire Mono source present which means it should be possible
to remove Mono git submodule and build entire Xamarin.Android without any
issues. At the same time, we want to keep the ability to build Mono from source,
if necessary, for situations when a developer works on the BCL or the runtime
itself and there's no appropriate binary archive present. To that effect, this
commit implements the following:

  * Remove Mono submodule
  * Put Mono repo reference to the `.external` file
  * Make distinction between "commercial" and "regular" bits in the `.external`
    file so that we don't attempt to check out everything mentioned in there in
    situations when a developer doesn't have access to the commercial bits.
  * Use Mono linker sources from the archive
  * Remove `zlib-helper.c` from the `libmonodroid` build - the API implemented
    in there is no longer used by Mono.
  * `Xamarin.Android.Cecil.dll` and `Xamarin.Android.Cecil.Mdb.dll` are no
    longer built from source. Instead we use `Cecil` to reshape `Mono.Cecil` and
    conjure the two renamed and re-signed assemblies.
  * All the code which used `Xamarin.Android.Cecil` project reference now simply
    references the conjured asseblies (which are also added to the bundle)
  * Third Party Notices are generated from licenses found in the Mono archive.
  * Windows build downloads also the Darwin archive - in order to be able to use
    Mono Linker sources as well as licenses contained in this archive.
---
 .external                                     |   1 +
 .gitignore                                    |   1 -
 .gitmodules                                   |   4 -
 Configuration.props                           |   2 +-
 .../conjure-xamarin-android-cecil.cs          |  63 +++++++
 .../conjure-xamarin-android-cecil.csproj      |  38 ++++
 .../remap-assembly-ref.csproj                 |   8 +-
 build-tools/scripts/XAVersionInfo.targets     |   4 +-
 .../xaprepare/Application/BuildInfo.cs        |   8 +-
 .../xaprepare/Application/Context.cs          |  13 +-
 .../Application/ExternalGitDependency.cs      |  20 +-
 .../xaprepare/Application/KnownConditions.cs  |   6 +
 .../xaprepare/Application/Utilities.cs        |  78 ++++++++
 .../ConfigAndData/Configurables.Unix.cs       |   1 +
 .../ConfigAndData/Configurables.Windows.cs    |   1 +
 .../xaprepare/ConfigAndData/Configurables.cs  |  15 +-
 .../xaprepare/ConfigAndData/Runtimes.cs       |  32 ++++
 .../xaprepare/Resources/MonoGitHash.props.in  |   6 +
 ...Scenario_PrepareExternalGitDependencies.cs |   5 +-
 .../xaprepare/Scenarios/Scenario_Required.cs  |   8 +
 .../xaprepare/Scenarios/Scenario_Standard.cs  |   1 +
 .../Steps/Step_BuildMonoRuntimes.Unix.cs      | 177 +++++-------------
 .../Steps/Step_DownloadMonoArchive.cs         | 119 ++++++++++++
 .../xaprepare/Steps/Step_GenerateFiles.cs     |  47 ++++-
 .../xaprepare/Steps/Step_PrepareBundle.cs     |   7 +
 .../xaprepare/Steps/Step_PrepareLocal.cs      |  13 --
 .../xaprepare/Steps/Step_PrepareProps.cs      |   4 -
 .../xaprepare/ThirdPartyNotices/mono.cs       |  28 +--
 .../ToolRunners/SnRunner.OutputSink.cs        |  22 +++
 .../xaprepare/ToolRunners/SnRunner.cs         |  55 ++++++
 .../xaprepare/xaprepare/xaprepare.csproj      |   3 +
 external/mono                                 |   1 -
 mono.snk                                      | Bin 0 -> 596 bytes
 msfinal.pub                                   | Bin 0 -> 160 bytes
 .../Xamarin.Android.Build.Tests.csproj        |   9 +-
 .../Xamarin.Android.Build.Tasks.csproj        |  18 +-
 .../Xamarin.Android.Tools.Aidl.csproj         |   9 +-
 ...marin.Android.Tools.JavadocImporter.csproj |  11 +-
 src/mono.pub                                  | Bin 35 -> 160 bytes
 src/monodroid/CMakeLists.txt                  |   2 -
 .../Xamarin.Android.Bcl-Tests.csproj          |  12 +-
 .../Xamarin.Android.Bcl-Tests/packages.config |  18 +-
 .../MSBuildDeviceIntegration.targets          |   6 +-
 43 files changed, 636 insertions(+), 240 deletions(-)
 create mode 100644 build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.cs
 create mode 100644 build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.csproj
 create mode 100644 build-tools/xaprepare/xaprepare/Resources/MonoGitHash.props.in
 create mode 100644 build-tools/xaprepare/xaprepare/Steps/Step_DownloadMonoArchive.cs
 create mode 100644 build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.OutputSink.cs
 create mode 100644 build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.cs
 delete mode 160000 external/mono
 create mode 100644 mono.snk
 create mode 100644 msfinal.pub
 mode change 120000 => 100644 src/mono.pub

diff --git a/.external b/.external
index 94b4aefc41e..766b94d3272 100644
--- a/.external
+++ b/.external
@@ -1 +1,2 @@
 xamarin/monodroid:master@237e0bd9f105b9842778ef82161a20c6d4497a40
+mono/mono:2019-06@afcf28a3660b069721e5c441dfe5bb7548e3204f
diff --git a/.gitignore b/.gitignore
index e6b730ef72c..ea1bc48a44a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,6 @@
 bin
 Configuration.Override.props
 Configuration.OperatingSystem.props
-msfinal.pub
 obj
 packages
 .DS_Store
diff --git a/.gitmodules b/.gitmodules
index 7cfb9fab01c..4d78bec7701 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -22,10 +22,6 @@
     path = external/mman-win32
     url = https://github.com/witwall/mman-win32.git
     branch = master
-[submodule "external/mono"]
-    path = external/mono
-    url = https://github.com/mono/mono.git
-    branch = 2019-06
 [submodule "external/mxe"]
     path = external/mxe
     url = https://github.com/xamarin/mxe.git
diff --git a/Configuration.props b/Configuration.props
index 0c3cbc43967..2240fd628a2 100644
--- a/Configuration.props
+++ b/Configuration.props
@@ -88,7 +88,7 @@
     <MonoRequiredMaximumVersion Condition=" '$(MonoRequiredMaximumVersion)' == '' ">6.5.0</MonoRequiredMaximumVersion>
     <IgnoreMaxMonoVersion Condition=" '$(IgnoreMaxMonoVersion)' == '' ">True</IgnoreMaxMonoVersion>
     <MonoRequiredDarwinMinimumVersion>$(MonoRequiredMinimumVersion).98</MonoRequiredDarwinMinimumVersion>
-    <LinkerSourceDirectory>$(MSBuildThisFileDirectory)external\mono\external\linker\src</LinkerSourceDirectory>
+    <LinkerSourceDirectory>$(MSBuildThisFileDirectory)external\mono\sdks\out\android-sources\external\linker\src</LinkerSourceDirectory>
     <OpenTKSourceDirectory>$(MSBuildThisFileDirectory)external\opentk</OpenTKSourceDirectory>
     <MingwZlibRootDirectory Condition=" '$(ZlibRootDirectory)' == '' And '$(HostOS)' == 'Linux' ">\usr</MingwZlibRootDirectory>
     <MingwZlibRootDirectory Condition=" '$(ZlibRootDirectory)' == '' And '$(HostOS)' == 'Darwin' ">$(HostHomebrewPrefix)\opt\mingw-zlib\usr</MingwZlibRootDirectory>
diff --git a/build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.cs b/build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.cs
new file mode 100644
index 00000000000..d6a9a66923b
--- /dev/null
+++ b/build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+using Mono.Cecil;
+
+public class ConjureXamarinAndroidCecil
+{
+	const string BaseNameReplacement = "Xamarin.Android.Cecil";
+	const string CecilAssemblyName = BaseNameReplacement;
+	const string CecilMdbAssemblyName = BaseNameReplacement + ".Mdb";
+
+	static readonly List<string> internalsVisibleTo = new List<string> {
+		"Xamarin.Android.Cecil.Pdb, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db",
+		"Xamarin.Android.Cecil.Mdb, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db"
+	};
+
+	public static int Main (string[] args)
+	{
+		if (args.Length < 2) {
+			Console.WriteLine ("Usage: <input directory> <output directory>");
+			Console.WriteLine ("  <input directory> must have Mono.Cecil.dll and Mono.Cecil.Mdb.dll assemblies");
+			return 1;
+		}
+
+		string inputDir = args [0];
+		string inputFilePath = Path.Combine (inputDir, "Mono.Cecil.dll");
+		string outputDirPath = args [1];
+
+		var resolver = new DefaultAssemblyResolver ();
+		resolver.AddSearchDirectory (Path.GetDirectoryName (inputFilePath));
+		var rp = new ReaderParameters () {
+			AssemblyResolver = resolver,
+			ReadSymbols = true
+		};
+		var monoCecil = AssemblyDefinition.ReadAssembly (inputFilePath, rp);
+		monoCecil.Name.Name = CecilAssemblyName;
+
+		var ivtCtor = monoCecil.MainModule.ImportReference (typeof (System.Runtime.CompilerServices.InternalsVisibleToAttribute).GetConstructor (new []{typeof(string)}));
+		foreach (string ivtParam in internalsVisibleTo) {
+			var ca = new CustomAttribute (ivtCtor);
+			ca.ConstructorArguments.Add (new CustomAttributeArgument (monoCecil.MainModule.TypeSystem.String, ivtParam));
+			monoCecil.CustomAttributes.Add (ca);
+		}
+
+		var wp = new WriterParameters {
+			WriteSymbols = true
+		};
+
+		monoCecil.Write (Path.Combine (outputDirPath, $"{CecilAssemblyName}.dll"), wp);
+
+		inputFilePath = Path.Combine (inputDir, "Mono.Cecil.Mdb.dll");
+		var monoCecilMdb = AssemblyDefinition.ReadAssembly (inputFilePath, rp);
+		monoCecilMdb.Name.Name = CecilMdbAssemblyName;
+
+		AssemblyNameReference monoCecilRef = monoCecilMdb.MainModule.AssemblyReferences.Single (r => String.Compare ("Mono.Cecil", r.Name, StringComparison.Ordinal) == 0);
+		monoCecilRef.Name = CecilAssemblyName;
+		monoCecilMdb.Write (Path.Combine (outputDirPath, $"{CecilMdbAssemblyName}.dll"), wp);
+
+		return 0;
+	}
+}
diff --git a/build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.csproj b/build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.csproj
new file mode 100644
index 00000000000..c8da4feea73
--- /dev/null
+++ b/build-tools/conjure-xamarin-android-cecil/conjure-xamarin-android-cecil.csproj
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{C876DA71-8573-4CEF-9149-716D72455ED4}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Xamarin.Android.Prepare</RootNamespace>
+    <AssemblyName>conjure-xamarin-android-cecil</AssemblyName>
+  </PropertyGroup>
+  <Import Project="..\..\Configuration.props" />
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\bin\BuildDebug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ExternalConsole>true</ExternalConsole>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\bin\BuildRelease</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ExternalConsole>true</ExternalConsole>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="Mono.Cecil">
+      <HintPath>$(XamarinAndroidSourcePath)external\mono\sdks\out\android-bcl\monodroid_tools\Mono.Cecil.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="conjure-xamarin-android-cecil.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
diff --git a/build-tools/remap-assembly-ref/remap-assembly-ref.csproj b/build-tools/remap-assembly-ref/remap-assembly-ref.csproj
index 8850e18b198..9dcf2627041 100644
--- a/build-tools/remap-assembly-ref/remap-assembly-ref.csproj
+++ b/build-tools/remap-assembly-ref/remap-assembly-ref.csproj
@@ -27,10 +27,10 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
-    <ProjectReference Include="..\..\external\Java.Interop\src\Xamarin.Android.Cecil\Xamarin.Android.Cecil.csproj">
-      <Project>{15945D4B-FF56-4BCC-B598-2718D199DD08}</Project>
-      <Name>Xamarin.Android.Cecil</Name>
-    </ProjectReference>  </ItemGroup>
+    <Reference Include="Mono.Cecil">
+      <HintPath>$(XamarinAndroidSourcePath)external\mono\sdks\out\android-bcl\monodroid_tools\Mono.Cecil.dll</HintPath>
+    </Reference>
+  </ItemGroup>
   <ItemGroup>
     <Compile Include="remap-assembly-ref.cs" />
   </ItemGroup>
diff --git a/build-tools/scripts/XAVersionInfo.targets b/build-tools/scripts/XAVersionInfo.targets
index 16cfcb459d5..f1982f03281 100644
--- a/build-tools/scripts/XAVersionInfo.targets
+++ b/build-tools/scripts/XAVersionInfo.targets
@@ -6,15 +6,13 @@
   <UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\xa-prep-tasks.dll"  TaskName="Xamarin.Android.BuildTools.PrepTasks.GitCommitsInRange" />
   <UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\xa-prep-tasks.dll"  TaskName="Xamarin.Android.BuildTools.PrepTasks.GitCommitTime" />
   <UsingTask AssemblyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\xa-prep-tasks.dll"  TaskName="Xamarin.Android.BuildTools.PrepTasks.GitCommitInfo" />
+  <Import Project="..\..\bin\Build$(Configuration)\MonoGitHash.props" />
   <Target Name="_GetSubmodulesVersionInfo">
     <ItemGroup>
       <!-- If anything changes in this list, make sure to update:
            src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets (the _GenerateXACommonProps target)
            build-tools/create-vsix/create-vsix.targets (the _CreateDependencies target)
       -->
-      <_SubmoduleBranchInfo Include="external/mono">
-        <OutputPropertyName>_BuildInfo_MonoCommit</OutputPropertyName>
-      </_SubmoduleBranchInfo>
       <_SubmoduleBranchInfo Include="external/Java.Interop">
         <OutputPropertyName>_BuildInfo_JavaInteropCommit</OutputPropertyName>
       </_SubmoduleBranchInfo>
diff --git a/build-tools/xaprepare/xaprepare/Application/BuildInfo.cs b/build-tools/xaprepare/xaprepare/Application/BuildInfo.cs
index f4e8b9f9f97..cbf4b9aab9b 100644
--- a/build-tools/xaprepare/xaprepare/Application/BuildInfo.cs
+++ b/build-tools/xaprepare/xaprepare/Application/BuildInfo.cs
@@ -105,7 +105,13 @@ void DetermineBundleHashes (Context context)
 			LibZipHash = EnsureHash ("LibZip", Utilities.ShortenGitHash (FullLibZipHash));
 
 			Log.StatusLine ($"  {context.Characters.Bullet} Mono commit hash", ConsoleColor.Gray);
-			FullMonoHash = git.GetTopCommitHash (context.Properties.GetRequiredValue (KnownProperties.MonoSourceFullPath), shortHash: false);
+			List<ExternalGitDependency> externalDependencies = ExternalGitDependency.GetDependencies (context, Configurables.Paths.ExternalGitDepsFilePath, quiet: true);
+			ExternalGitDependency mono = externalDependencies?.Where (
+				eg => eg != null &&
+				      String.Compare ("mono", eg.Owner, StringComparison.Ordinal) == 0 &&
+				      String.Compare ("mono", eg.Name, StringComparison.Ordinal) == 0).FirstOrDefault ();
+
+			FullMonoHash = mono?.Commit?.Trim ();
 			MonoHash = EnsureHash ("Mono", Utilities.ShortenGitHash (FullMonoHash));
 
 			if (Configurables.Paths.BundleVersionHashFiles == null || Configurables.Paths.BundleVersionHashFiles.Count == 0) {
diff --git a/build-tools/xaprepare/xaprepare/Application/Context.cs b/build-tools/xaprepare/xaprepare/Application/Context.cs
index 73b8de7d27e..6cb6ecd1762 100644
--- a/build-tools/xaprepare/xaprepare/Application/Context.cs
+++ b/build-tools/xaprepare/xaprepare/Application/Context.cs
@@ -329,6 +329,13 @@ public string DebugFileExtension {
 		/// </summary>
 		public RefreshableComponent ComponentsToRefresh { get; set; }
 
+		/// <summary>
+		///   Set by <see cref="Step_DownloadMonoArchive"/> if the archive has been downloaded and validated, so
+		///   that the <see cref="Step_BuildMonoRuntimes"/> step doesn't have to re-download the archive, should
+		///   bundle be absent and <see cref="Step_PrepareBundle"/> fails.
+		/// </summary>
+		public bool MonoAlreadyBuilt { get; set; }
+
 		static Context ()
 		{
 			Instance = new Context ();
@@ -742,8 +749,10 @@ public async Task<bool> Init (string scenarioName = null)
 			Banner ("Updating Git submodules");
 
 			var git = new GitRunner (this);
-			if (!await git.SubmoduleUpdate ())
-				Log.WarningLine ("Failed to update Git submodules");
+			if (!await git.SubmoduleUpdate ()) {
+				Log.ErrorLine ("Failed to update Git submodules");
+				return false;
+			}
 
 			BuildInfo = new BuildInfo ();
 			await BuildInfo.GatherGitInfo (this);
diff --git a/build-tools/xaprepare/xaprepare/Application/ExternalGitDependency.cs b/build-tools/xaprepare/xaprepare/Application/ExternalGitDependency.cs
index a129a90bd4d..34c5008f13a 100644
--- a/build-tools/xaprepare/xaprepare/Application/ExternalGitDependency.cs
+++ b/build-tools/xaprepare/xaprepare/Application/ExternalGitDependency.cs
@@ -33,11 +33,13 @@ sealed class ExternalGitDependency : AppObject
 		public string Name   { get; private set; }
 		public string Owner  { get; private set; }
 
-		public static List<ExternalGitDependency> GetDependencies (Context context, string externalFilePath)
+		public static List<ExternalGitDependency> GetDependencies (Context context, string externalFilePath, bool quiet = false)
 		{
-			Log.Instance.StatusLine ($"  {context.Characters.Bullet} Reading external dependencies from {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, externalFilePath)}");
+			if (!quiet)
+				Log.Instance.StatusLine ($"  {context.Characters.Bullet} Reading external dependencies from {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, externalFilePath)}");
 			string[] unparsedExternals = File.ReadAllLines (externalFilePath);
 			var externals = new List<ExternalGitDependency> (unparsedExternals.Length);
+			bool includeCommercial = context.CheckCondition (KnownConditions.IncludeCommercial);
 
 			foreach (string external in unparsedExternals) {
 				Match match = externalRegex.Match (external);
@@ -47,14 +49,22 @@ public static List<ExternalGitDependency> GetDependencies (Context context, stri
 						continue;
 					}
 
+					string owner = match.Groups["owner"].Value;
+					string repo = match.Groups["repo"].Value;
+					if (!includeCommercial && Configurables.Defaults.CommercialExternalDependencies.Contains ($"{owner}/{repo}")) {
+						Log.Instance.DebugLine ($"Ignoring external commercial dependency '{owner}/{repo}'");
+						continue;
+					}
+
 					var e = new ExternalGitDependency {
 						Branch = match.Groups["branch"].Value,
 						Commit = match.Groups["commit"].Value,
-						Name   = match.Groups["repo"].Value,
-						Owner  = match.Groups["owner"].Value,
+						Name   = repo,
+						Owner  = owner,
 					};
 					externals.Add (e);
-					Log.Instance.StatusLine ($"    {context.Characters.Bullet} {e.Owner}/{e.Name} ({e.Commit})");
+					if (!quiet)
+						Log.Instance.StatusLine ($"    {context.Characters.Bullet} {e.Owner}/{e.Name} ({e.Commit})");
 				}
 			}
 
diff --git a/build-tools/xaprepare/xaprepare/Application/KnownConditions.cs b/build-tools/xaprepare/xaprepare/Application/KnownConditions.cs
index 2240d487a65..c78f877cb7d 100644
--- a/build-tools/xaprepare/xaprepare/Application/KnownConditions.cs
+++ b/build-tools/xaprepare/xaprepare/Application/KnownConditions.cs
@@ -18,5 +18,11 @@ public enum KnownConditions
 		///   only a single program (e.g. the UpdateMono scenario) but not the rest. Default: unset. <see cref="Scenario_UpdateMono" />
 		/// </summary>
 		IgnoreMissingPrograms,
+
+		/// <summary>
+		///   If set, will cause checkout of the commercial dependencies mentioned in the `.external` file at
+		///   the top of the repository. Default: unset
+		/// </summary>
+		IncludeCommercial,
 	}
 }
diff --git a/build-tools/xaprepare/xaprepare/Application/Utilities.cs b/build-tools/xaprepare/xaprepare/Application/Utilities.cs
index 007cfd5fca4..155c6693def 100644
--- a/build-tools/xaprepare/xaprepare/Application/Utilities.cs
+++ b/build-tools/xaprepare/xaprepare/Application/Utilities.cs
@@ -28,6 +28,84 @@ static partial class Utilities
 
 		public static readonly Encoding UTF8NoBOM = new UTF8Encoding (false);
 
+		public static bool AbiChoiceChanged (Context context)
+		{
+			string cacheFile = Configurables.Paths.MonoRuntimesEnabledAbisCachePath;
+			if (!File.Exists (cacheFile)) {
+				Log.DebugLine ($"Enabled ABI cache file not found at {cacheFile}");
+				return true;
+			}
+
+			var oldAbis = new HashSet<string> (StringComparer.Ordinal);
+			foreach (string l in File.ReadAllLines (cacheFile)) {
+				string line = l?.Trim ();
+				if (String.IsNullOrEmpty (line) || oldAbis.Contains (line))
+					continue;
+				oldAbis.Add (line);
+			}
+
+			HashSet<string> currentAbis = null;
+			FillCurrentAbis (context, ref currentAbis);
+
+			if (oldAbis.Count != currentAbis.Count)
+				return true;
+
+			foreach (string abi in oldAbis) {
+				if (!currentAbis.Contains (abi))
+					return true;
+			}
+
+			return false;
+		}
+
+		public static void SaveAbiChoice (Context context)
+		{
+			HashSet<string> currentAbis = null;
+			FillCurrentAbis (context, ref currentAbis);
+
+			string cacheFile = Configurables.Paths.MonoRuntimesEnabledAbisCachePath;
+			Log.DebugLine ($"Writing ABI cache file {cacheFile}");
+			File.WriteAllLines (cacheFile, currentAbis);
+		}
+
+		static void FillCurrentAbis (Context context, ref HashSet<string> currentAbis)
+		{
+			Utilities.AddAbis (context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedTargetJitAbis).Trim (), ref currentAbis);
+			Utilities.AddAbis (context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedTargetAotAbis).Trim (), ref currentAbis);
+			Utilities.AddAbis (context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedHostJitAbis).Trim (), ref currentAbis);
+		}
+
+		public static void PropagateXamarinAndroidCecil (Context context)
+		{
+			const string CecilAssembly = "Xamarin.Android.Cecil.dll";
+
+			CopyFile (
+				Path.Combine (Configurables.Paths.InstallMSBuildDir, CecilAssembly),
+				Path.Combine (Configurables.Paths.ExternalJavaInteropDir, "bin", context.Configuration, CecilAssembly)
+			);
+		}
+
+		public static async Task<bool> BuildRemapRef (Context context, bool haveManagedRuntime, string managedRuntime, bool quiet = false)
+		{
+			if (!quiet)
+				Log.StatusLine ("Building remap-assembly-ref");
+
+			var msbuild = new MSBuildRunner (context);
+			string projectPath = Path.Combine (Configurables.Paths.BuildToolsDir, "remap-assembly-ref", "remap-assembly-ref.csproj");
+			bool result = await msbuild.Run (
+				projectPath: projectPath,
+				logTag: "remap-assembly-ref",
+				binlogName: "build-remap-assembly-ref"
+			);
+
+			if (!result) {
+				Log.ErrorLine ("Failed to build remap-assembly-ref");
+				return false;
+			}
+
+			return true;
+		}
+
 		public static string ToXamarinAndroidPropertyValue (ICollection<string> coll)
 		{
 			if (coll == null)
diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Unix.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Unix.cs
index 8a031b753b2..52aaae44f57 100644
--- a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Unix.cs
+++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Unix.cs
@@ -12,6 +12,7 @@ partial class Defaults
 		partial class Paths
 		{
 			static string BundleOSType                  => Context.Instance.OS.Type;
+			static string ArchiveOSType                 => Context.Instance.OS.Type;
 
 			public static string BCLTestsSourceDir      => GetCachedPath (ref bclTestsSourceDir, () => Path.Combine (MonoProfileDir, "tests"));
 			public static string BCLAssembliesSourceDir => MonoProfileDir;
diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Windows.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Windows.cs
index 078a88a52ca..e5a9865bd15 100644
--- a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Windows.cs
+++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.Windows.cs
@@ -34,6 +34,7 @@ partial class Defaults
 		partial class Paths
 		{
 			static string BundleOSType                                            => "Darwin"; // Windows doesn't build the bundle
+			static string ArchiveOSType                                           => "Darwin"; // Windows need sources from there
 
 			// Windows doesn't build the bundle so we need to look in the XA framework dir as installed
 			public static string BCLAssembliesSourceDir                           => InstallBCLFrameworkDir;
diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs
index 833a099bf41..5f3cc33b6e0 100644
--- a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs
+++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs
@@ -71,6 +71,14 @@ public static partial class Defaults
 
 			public static CompressionFormat DefaultCompressionFormat => CompressionFormats [SevenZipCompressionFormatName];
 
+			/// <summary>
+			///   Set of .external "submodules" to check out when the <see
+			///   cref="KnownConditions.IncludeCommercial" /> condition is set.
+			/// </summary>
+			public static HashSet<string> CommercialExternalDependencies = new HashSet<string> (StringComparer.OrdinalIgnoreCase) {
+				"xamarin/monodroid"
+			};
+
 			/// <summary>
 			///   Default execution mode. One of:
 			///
@@ -326,7 +334,7 @@ public static partial class Paths
 
 			// Mono Archive
 			public static string MonoArchiveMonoHash                 => ctx.BuildInfo.FullMonoHash;
-			public static string MonoArchiveBaseFileName             => $"android-{Defaults.MonoSdksConfiguration}-{ctx.OS.Type}-{MonoArchiveMonoHash}";
+			public static string MonoArchiveBaseFileName             => $"android-{Defaults.MonoSdksConfiguration}-{ArchiveOSType}-{MonoArchiveMonoHash}";
 			public static string MonoArchiveWindowsBaseFileName      => $"android-release-Windows-{MonoArchiveMonoHash}";
 			public static string MonoArchiveFileName                 => $"{MonoArchiveBaseFileName}.7z";
 			public static string MonoArchiveWindowsFileName          => $"{MonoArchiveWindowsBaseFileName}.7z";
@@ -351,7 +359,8 @@ public static partial class Paths
 			// not really configurables, merely convenience aliases for more frequently used paths that come from properties
 			public static string XAInstallPrefix                => ctx.Properties.GetRequiredValue (KnownProperties.XAInstallPrefix);
 			public static string MonoSourceFullPath             => ctx.Properties.GetRequiredValue (KnownProperties.MonoSourceFullPath);
-			public static string MonoExternalFullPath           => Path.Combine (MonoSourceFullPath, "external");
+			public static string MonoSdksTpnPath                => GetCachedPath (ref monoSdksTpnPath, ()         => Path.Combine (MonoSDKSOutputDir, "android-tpn"));
+			public static string MonoSdksTpnExternalPath        => GetCachedPath (ref monoSdksTpnExternalPath, () => Path.Combine (MonoSdksTpnPath, "external"));
 
 			static string EnsureAndroidToolchainBinDirectories ()
 			{
@@ -409,6 +418,8 @@ static string GetCachedPath (ref string variable, Func<string> creator)
 			static string installBCLDesignerDir;
 			static string monoAndroidFrameworksRootDir;
 			static string externalJavaInteropDir;
+			static string monoSdksTpnPath;
+			static string monoSdksTpnExternalPath;
 		}
 	}
 }
diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Runtimes.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Runtimes.cs
index 45f28678691..b88cef9ebfe 100644
--- a/build-tools/xaprepare/xaprepare/ConfigAndData/Runtimes.cs
+++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Runtimes.cs
@@ -408,6 +408,38 @@ partial class Runtimes
 				shared: true
 			),
 
+			// Xamarin.Android.Cecil.dll
+			new RuntimeFile (
+				sourceCreator: (Runtime runtime) => Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.dll"),
+				destinationCreator: (Runtime runtime) => "Xamarin.Android.Cecil.dll",
+				strip: false,
+				shared: true
+			),
+
+			// Xamarin.Android.Cecil.pdb
+			new RuntimeFile (
+				sourceCreator: (Runtime runtime) => Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.pdb"),
+				destinationCreator: (Runtime runtime) => "Xamarin.Android.Cecil.pdb",
+				strip: false,
+				shared: true
+			),
+
+			// Xamarin.Android.Cecil.Mdb.dll
+			new RuntimeFile (
+				sourceCreator: (Runtime runtime) => Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.Mdb.dll"),
+				destinationCreator: (Runtime runtime) => "Xamarin.Android.Cecil.Mdb.dll",
+				strip: false,
+				shared: true
+			),
+
+			// Xamarin.Android.Cecil.Mdb.pdb
+			new RuntimeFile (
+				sourceCreator: (Runtime runtime) => Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.Mdb.pdb"),
+				destinationCreator: (Runtime runtime) => "Xamarin.Android.Cecil.Mdb.pdb",
+				strip: false,
+				shared: true
+			),
+
 			 // Stripped runtime
 			new RuntimeFile (
 				sourceCreator: (Runtime runtime) => GetRuntimeOutputSourcePath (runtime),
diff --git a/build-tools/xaprepare/xaprepare/Resources/MonoGitHash.props.in b/build-tools/xaprepare/xaprepare/Resources/MonoGitHash.props.in
new file mode 100644
index 00000000000..d5aebc5fcc1
--- /dev/null
+++ b/build-tools/xaprepare/xaprepare/Resources/MonoGitHash.props.in
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_BuildInfo_MonoCommit>@MONO_COMMIT_HASH@</_BuildInfo_MonoCommit>
+  </PropertyGroup>
+</Project>
diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternalGitDependencies.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternalGitDependencies.cs
index bc0237bb7bb..4af05758141 100644
--- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternalGitDependencies.cs
+++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternalGitDependencies.cs
@@ -19,8 +19,11 @@ protected override void AddSteps (Context context)
 			// disable installation of missing programs...
 			context.SetCondition (KnownConditions.AllowProgramInstallation, false);
 
-			// ...but do not signal an error when any are missing
+			// ...but do not signal an error when any are missing...
 			context.SetCondition (KnownConditions.IgnoreMissingPrograms, true);
+
+			// ...and include external commercial dependencies
+			context.SetCondition (KnownConditions.IncludeCommercial, true);
 		}
 	}
 }
diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs
index 9931fe898af..3bce5d807b4 100644
--- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs
+++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs
@@ -8,5 +8,13 @@ class Scenario_Required : Scenario
 	{
 		public Scenario_Required () : base ("Required", "Just the basic steps to quickly install required tools and generate build files.", Context.Instance)
 		{}
+
+		protected override void AddSteps (Context context)
+		{
+			if (context == null)
+				throw new ArgumentNullException (nameof (context));
+
+			Steps.Add (new Step_GenerateFiles (atBuildStart: true, onlyRequired: true));
+		}
 	}
 }
diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs
index db56cb15f4a..3aa1c22d71d 100644
--- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs
+++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs
@@ -21,6 +21,7 @@ protected override void AddSteps (Context context)
 			Steps.Add (new Step_PrepareProps ());
 			Steps.Add (new Step_PrepareExternal ());
 			Steps.Add (new Step_PrepareLocal ());
+			Steps.Add (new Step_DownloadMonoArchive ());
 			AddRequiredOSSpecificSteps (true);
 			Steps.Add (new Step_PrepareBundle ());
 			AddRequiredOSSpecificSteps (false);
diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_BuildMonoRuntimes.Unix.cs b/build-tools/xaprepare/xaprepare/Steps/Step_BuildMonoRuntimes.Unix.cs
index 12789751793..89bbbd0af5c 100644
--- a/build-tools/xaprepare/xaprepare/Steps/Step_BuildMonoRuntimes.Unix.cs
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_BuildMonoRuntimes.Unix.cs
@@ -32,28 +32,33 @@ protected override async Task<bool> Execute (Context context)
 				return true;
 			}
 
-			bool built = await DownloadMonoArchive (context);
-
-			if (!built) {
+			if (!context.MonoAlreadyBuilt) {
 				List<string> makeArguments = GetMakeArguments (context, enabledRuntimes);
 				if (!await BuildRuntimes (context, makeArguments)) {
 					Log.ErrorLine ("Mono runtime build failed");
 					return false;
 				}
-			} else
-				SaveAbiChoice (context);
+			}
 
 			CleanupBeforeInstall ();
 			Log.StatusLine ();
+
+			string managedRuntime = context.Properties.GetRequiredValue (KnownProperties.ManagedRuntime);
+			bool haveManagedRuntime = !String.IsNullOrEmpty (managedRuntime);
+			if (!await ConjureXamarinCecilAndRemapRef (context, haveManagedRuntime, managedRuntime))
+				return false;
+
 			if (!await InstallRuntimes (context, enabledRuntimes))
 				return false;
 
 			if (!InstallBCL (context))
 				return false;
 
-			if (!InstallUtilities (context))
+			if (!InstallUtilities (context, haveManagedRuntime, managedRuntime))
 				return false;
 
+			Utilities.PropagateXamarinAndroidCecil (context);
+
 			return true;
 		}
 
@@ -64,148 +69,70 @@ void CleanupBeforeInstall ()
 			}
 		}
 
-		bool AbiChoiceChanged (Context context)
+		async Task<bool> ConjureXamarinCecilAndRemapRef (Context context, bool haveManagedRuntime, string managedRuntime)
 		{
-			string cacheFile = Configurables.Paths.MonoRuntimesEnabledAbisCachePath;
-			if (!File.Exists (cacheFile)) {
-				Log.DebugLine ($"Enabled ABI cache file not found at {cacheFile}");
-				return true;
-			}
-
-			var oldAbis = new HashSet<string> (StringComparer.Ordinal);
-			foreach (string l in File.ReadAllLines (cacheFile)) {
-				string line = l?.Trim ();
-				if (String.IsNullOrEmpty (line) || oldAbis.Contains (line))
-					continue;
-				oldAbis.Add (line);
-			}
-
-			HashSet<string> currentAbis = null;
-			FillCurrentAbis (context, ref currentAbis);
-
-			if (oldAbis.Count != currentAbis.Count)
-				return true;
-
-			foreach (string abi in oldAbis) {
-				if (!currentAbis.Contains (abi))
-					return true;
-			}
-
-			return false;
-		}
-
-		void SaveAbiChoice (Context context)
-		{
-			HashSet<string> currentAbis = null;
-			FillCurrentAbis (context, ref currentAbis);
-
-			string cacheFile = Configurables.Paths.MonoRuntimesEnabledAbisCachePath;
-			Log.DebugLine ($"Writing ABI cache file {cacheFile}");
-			File.WriteAllLines (cacheFile, currentAbis);
-		}
+			StatusStep (context, "Building remap-assembly-ref");
+			bool result = await Utilities.BuildRemapRef (context, haveManagedRuntime, managedRuntime, quiet: true);
+			if (!result)
+				return false;
 
-		void FillCurrentAbis (Context context, ref HashSet<string> currentAbis)
-		{
-			Utilities.AddAbis (context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedTargetJitAbis).Trim (), ref currentAbis);
-			Utilities.AddAbis (context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedTargetAotAbis).Trim (), ref currentAbis);
-			Utilities.AddAbis (context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedHostJitAbis).Trim (), ref currentAbis);
-		}
+			var msbuild = new MSBuildRunner (context);
+			StatusStep (context, "Building conjure-xamarin-android-cecil");
+			string projectPath = Path.Combine (Configurables.Paths.BuildToolsDir, "conjure-xamarin-android-cecil", "conjure-xamarin-android-cecil.csproj");
+			result = await msbuild.Run (
+				projectPath: projectPath,
+				logTag: "conjure-xamarin-android-cecil",
+				binlogName: "build-conjure-xamarin-android-cecil"
+			);
 
-		async Task<bool> DownloadMonoArchive (Context context)
-		{
-			if (context.ForceRuntimesBuild) {
-				Log.StatusLine ("Mono runtime rebuild forced, Mono Archive download skipped");
+			if (!result) {
+				Log.ErrorLine ("Failed to build conjure-xamarin-android-cecil");
 				return false;
 			}
 
-			Log.StatusLine ("Checking if all runtime files are present");
-			allRuntimes = new Runtimes ();
-			if (MonoRuntimesHelpers.AllBundleItemsPresent (allRuntimes)) {
-				// User might have changed the set of ABIs to build, we need to check and rebuild if necessary
-				if (!AbiChoiceChanged (context)) {
-					Log.StatusLine ("Mono runtimes already present and complete. No need to download or build.");
-					return true;
-				}
+			StatusStep (context, "Conjuring Xamarin.Android.Cecil and Xamari.Android.Cecil.Mdb");
+			string conjurer = Path.Combine (Configurables.Paths.BuildBinDir, "conjure-xamarin-android-cecil.exe");
+			string conjurerSourceDir = Configurables.Paths.MonoProfileToolsDir;
+			string conjurerDestDir = Configurables.Paths.BuildBinDir;
 
-				Log.StatusLine ("Mono already present, but the choice of ABIs changed since previous build, runtime refresh is necessary");
-			}
-			Log.Instance.StatusLine ($"  {Context.Instance.Characters.Bullet} some files are missing, download/rebuild/reinstall forced");
+			result = Utilities.RunCommand (
+				haveManagedRuntime ? managedRuntime : conjurer, // command
+				BuildPaths.XamarinAndroidSourceRoot, // workingDirectory
+				true, // ignoreEmptyArguments
 
-			bool result = await DownloadAndUpackIfNeeded (
-				context,
-				"Mono",
-				Configurables.Paths.MonoArchiveLocalPath,
-				Configurables.Paths.MonoArchiveFileName,
-				Configurables.Paths.MonoSDKSOutputDir
+				// arguments
+				haveManagedRuntime ? conjurer : String.Empty,
+				Configurables.Paths.MonoProfileToolsDir, // source dir
+				Configurables.Paths.BuildBinDir // destination dir
 			);
 
-			if (!result)
+			StatusStep (context, "Re-signing Xamarin.Android.Cecil.dll");
+			var sn = new SnRunner (context);
+			string snkPath = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "mono.snk");
+			string assemblyPath = Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.dll");
+			result = await sn.ReSign (snkPath, assemblyPath, $"sign-xamarin-android-cecil");
+			if (!result) {
+				Log.ErrorLine ("Failed to re-sign Xamarin.Android.Cecil.dll");
 				return false;
-
-			return await DownloadAndUpackIfNeeded (
-				context,
-				"Windows Mono",
-				Configurables.Paths.MonoArchiveWindowsLocalPath,
-				Configurables.Paths.MonoArchiveWindowsFileName,
-				Configurables.Paths.BCLWindowsOutputDir
-			);
-		}
-
-		async Task<bool> DownloadAndUpackIfNeeded (Context context, string name, string localPath, string archiveFileName, string destinationDirectory)
-		{
-			if (await Utilities.VerifyArchive (localPath)) {
-				Log.StatusLine ($"{name} archive already downloaded and valid");
-			} else {
-				Utilities.DeleteFileSilent (localPath);
-
-				var url = new Uri (Configurables.Urls.MonoArchive_BaseUri, archiveFileName);
-				Log.StatusLine ($"Downloading {name} archive from {url}");
-
-				(bool success, ulong size, HttpStatusCode status) = await Utilities.GetDownloadSizeWithStatus (url);
-				if (!success) {
-					if (status == HttpStatusCode.NotFound)
-						Log.Info ($"{name} archive URL not found");
-					else
-						Log.Info ($"Failed to obtain {name} archive size. HTTP status code: {status} ({(int)status})");
-					Log.InfoLine (". Mono runtimes will be rebuilt");
-					return false;
-				}
-
-				DownloadStatus downloadStatus = Utilities.SetupDownloadStatus (context, size, context.InteractiveSession);
-				Log.StatusLine ($"  {context.Characters.Link} {url}", ConsoleColor.White);
-				await Download (context, url, localPath, $"{name} Archive", archiveFileName, downloadStatus);
-
-				if (!File.Exists (localPath)) {
-					Log.InfoLine ($"Download of {name} archive from {url} failed, Mono will be rebuilt");
-					return false;
-				}
 			}
 
-			string tempDir = $"{destinationDirectory}.tmp";
-			if (!await Utilities.Unpack (localPath, tempDir, cleanDestinatioBeforeUnpacking: true)) {
-				Utilities.DeleteDirectorySilent (destinationDirectory);
-				Log.WarningLine ($"Failed to unpack {name} archive {localPath}, Mono will be rebuilt");
+			StatusStep (context, "Re-signing Xamarin.Android.Cecil.Mdb.dll");
+			assemblyPath = Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.Mdb.dll");
+			result = await sn.ReSign (snkPath, assemblyPath, $"sign-xamarin-android-cecil-mdb");
+			if (!result) {
+				Log.ErrorLine ("Failed to re-sign Xamarin.Android.Cecil.Mdb.dll");
 				return false;
 			}
 
-			Log.DebugLine ($"Moving unpacked Mono archive from {tempDir} to {destinationDirectory}");
-			try {
-				Utilities.MoveDirectoryContentsRecursively (tempDir, destinationDirectory, resetFileTimestamp: true);
-			} finally {
-				Utilities.DeleteDirectorySilent (tempDir);
-			}
-
 			return true;
 		}
 
-		bool InstallUtilities (Context context)
+		bool InstallUtilities (Context context, bool haveManagedRuntime, string managedRuntime)
 		{
 			string destDir = MonoRuntimesHelpers.UtilitiesDestinationDir;
 
 			Utilities.CreateDirectory (destDir);
 
-			string managedRuntime = context.Properties.GetRequiredValue (KnownProperties.ManagedRuntime);
-			bool haveManagedRuntime = !String.IsNullOrEmpty (managedRuntime);
 			string remapper = Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, context.Properties.GetRequiredValue (KnownProperties.RemapAssemblyRefToolExecutable));
 			string targetCecil = Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, Path.Combine (Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.dll"));
 
@@ -465,7 +392,7 @@ async Task<bool> BuildRuntimes (Context context, List<string> makeArguments)
 			if (!result)
 				return false;
 
-			SaveAbiChoice (context);
+			Utilities.SaveAbiChoice (context);
 
 			return true;
 		}
diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_DownloadMonoArchive.cs b/build-tools/xaprepare/xaprepare/Steps/Step_DownloadMonoArchive.cs
new file mode 100644
index 00000000000..22785aa0854
--- /dev/null
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_DownloadMonoArchive.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace Xamarin.Android.Prepare
+{
+	class Step_DownloadMonoArchive : StepWithDownloadProgress
+	{
+		public Step_DownloadMonoArchive ()
+			: base ("Downloading Mono archive")
+		{}
+
+		protected override async Task<bool> Execute (Context context)
+		{
+			bool built = await DownloadMonoArchive (context);
+
+			if (!built) {
+				Log.InfoLine ("Mono archive not present");
+				return true;
+			} else
+				Utilities.SaveAbiChoice (context);
+
+			context.MonoAlreadyBuilt = built;
+			return true;
+		}
+
+		async Task<bool> DownloadMonoArchive (Context context)
+		{
+			if (context.ForceRuntimesBuild) {
+				Log.StatusLine ("Mono runtime rebuild forced, Mono Archive download skipped");
+				return false;
+			}
+
+			Log.StatusLine ("Checking if all runtime files are present");
+			var allRuntimes = new Runtimes ();
+			if (MonoRuntimesHelpers.AllBundleItemsPresent (allRuntimes)) {
+				// User might have changed the set of ABIs to build, we need to check and rebuild if necessary
+				if (!Utilities.AbiChoiceChanged (context)) {
+					Log.StatusLine ("Mono runtimes already present and complete. No need to download or build.");
+					return true;
+				}
+
+				Log.StatusLine ("Mono already present, but the choice of ABIs changed since previous build, runtime refresh is necessary");
+			}
+			Log.Instance.StatusLine ($"  {Context.Instance.Characters.Bullet} some files are missing, download/rebuild/reinstall forced");
+
+			bool result = await DownloadAndUpackIfNeeded (
+				context,
+				"Mono",
+				Configurables.Paths.MonoArchiveLocalPath,
+				Configurables.Paths.MonoArchiveFileName,
+				Configurables.Paths.MonoSDKSOutputDir
+			);
+
+			if (!result)
+				return false;
+
+			return await DownloadAndUpackIfNeeded (
+				context,
+				"Windows Mono",
+				Configurables.Paths.MonoArchiveWindowsLocalPath,
+				Configurables.Paths.MonoArchiveWindowsFileName,
+				Configurables.Paths.BCLWindowsOutputDir
+			);
+		}
+
+		async Task<bool> DownloadAndUpackIfNeeded (Context context, string name, string localPath, string archiveFileName, string destinationDirectory)
+		{
+			if (await Utilities.VerifyArchive (localPath)) {
+				Log.StatusLine ($"{name} archive already downloaded and valid");
+			} else {
+				Utilities.DeleteFileSilent (localPath);
+
+				var url = new Uri (Configurables.Urls.MonoArchive_BaseUri, archiveFileName);
+				Log.StatusLine ($"Downloading {name} archive from {url}");
+
+				(bool success, ulong size, HttpStatusCode status) = await Utilities.GetDownloadSizeWithStatus (url);
+				if (!success) {
+					if (status == HttpStatusCode.NotFound)
+						Log.Info ($"{name} archive URL not found");
+					else
+						Log.Info ($"Failed to obtain {name} archive size. HTTP status code: {status} ({(int)status})");
+					Log.InfoLine (". Mono runtimes will be rebuilt");
+					return false;
+				}
+
+				DownloadStatus downloadStatus = Utilities.SetupDownloadStatus (context, size, context.InteractiveSession);
+				Log.StatusLine ($"  {context.Characters.Link} {url}", ConsoleColor.White);
+				await Download (context, url, localPath, $"{name} Archive", archiveFileName, downloadStatus);
+
+				if (!File.Exists (localPath)) {
+					Log.InfoLine ($"Download of {name} archive from {url} failed, Mono will be rebuilt");
+					return false;
+				}
+			}
+
+			string tempDir = $"{destinationDirectory}.tmp";
+			if (!await Utilities.Unpack (localPath, tempDir, cleanDestinatioBeforeUnpacking: true)) {
+				Utilities.DeleteDirectorySilent (destinationDirectory);
+				Log.WarningLine ($"Failed to unpack {name} archive {localPath}, Mono will be rebuilt");
+				return false;
+			}
+
+			Log.DebugLine ($"Moving unpacked Mono archive from {tempDir} to {destinationDirectory}");
+			try {
+				Utilities.MoveDirectoryContentsRecursively (tempDir, destinationDirectory, resetFileTimestamp: true);
+			} finally {
+				Utilities.DeleteDirectorySilent (tempDir);
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs
index b844fb8b992..496a05cf6be 100644
--- a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs
@@ -8,11 +8,13 @@ namespace Xamarin.Android.Prepare
 	partial class Step_GenerateFiles : Step
 	{
 		bool atBuildStart;
+		bool onlyRequired;
 
-		public Step_GenerateFiles (bool atBuildStart)
+		public Step_GenerateFiles (bool atBuildStart, bool onlyRequired = false)
 			: base ("Generating files required by the build")
 		{
 			this.atBuildStart = atBuildStart;
+			this.onlyRequired = onlyRequired;
 		}
 
 #pragma warning disable CS1998
@@ -42,17 +44,27 @@ protected override async Task<bool> Execute (Context context)
 		List<GeneratedFile> GetFilesToGenerate (Context context)
 		{
 			if (atBuildStart) {
-				return new List <GeneratedFile> {
-					Get_Configuration_OperatingSystem_props (context),
-					Get_Ndk_projitems (context),
-					Get_XABuildPaths_cs (context),
-					Get_XABuildConfig_cs (context),
-					Get_mingw_32_cmake (context),
-					Get_mingw_64_cmake (context),
-					Get_bundle_path_targets (context),
-				};
+				if (onlyRequired) {
+					return new List<GeneratedFile> {
+						Get_MonoGitHash_props (context),
+					};
+				} else {
+					return new List <GeneratedFile> {
+						Get_Configuration_OperatingSystem_props (context),
+						Get_Ndk_projitems (context),
+						Get_XABuildPaths_cs (context),
+						Get_XABuildConfig_cs (context),
+						Get_mingw_32_cmake (context),
+						Get_mingw_64_cmake (context),
+						Get_bundle_path_targets (context),
+						Get_MonoGitHash_props (context),
+					};
+				}
 			}
 
+			if (onlyRequired)
+				return null;
+
 			var steps = new List <GeneratedFile> {
 				new GeneratedProfileAssembliesProjitemsFile (Configurables.Paths.ProfileAssembliesProjitemsPath),
 			};
@@ -192,5 +204,20 @@ GeneratedFile Get_bundle_path_targets (Context context)
 
 			return new GeneratedPlaceholdersFile (replacements, Configurables.Paths.BundlePathTemplate, Configurables.Paths.BundlePathOutput);
 		}
+
+		GeneratedFile Get_MonoGitHash_props (Context context)
+		{
+			const string OutputFileName = "MonoGitHash.props";
+
+			var replacements = new Dictionary<string, string> (StringComparer.Ordinal) {
+				{ "@MONO_COMMIT_HASH@", context.BuildInfo.MonoHash }
+			};
+
+			return new GeneratedPlaceholdersFile (
+				replacements,
+				Path.Combine (Configurables.Paths.BootstrapResourcesDir, $"{OutputFileName}.in"),
+				Path.Combine (Configurables.Paths.BuildBinDir, OutputFileName)
+			);
+		}
 	}
 }
diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareBundle.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareBundle.cs
index 64c286deb9a..98d84600e5c 100644
--- a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareBundle.cs
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareBundle.cs
@@ -90,6 +90,13 @@ protected override async Task<bool> Execute (Context context)
 				Utilities.DeleteDirectorySilent (tempDir);
 			}
 
+			string managedRuntime = context.Properties.GetRequiredValue (KnownProperties.ManagedRuntime);
+			bool haveManagedRuntime = !String.IsNullOrEmpty (managedRuntime);
+			if (!await Utilities.BuildRemapRef (context, haveManagedRuntime, managedRuntime))
+				return false;
+
+			Utilities.PropagateXamarinAndroidCecil (context);
+
 			if (String.IsNullOrEmpty (context.XABundleCopyDir))
 				return HaveEverything ();
 
diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareLocal.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareLocal.cs
index 4adba773d32..9f5052c3a9a 100644
--- a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareLocal.cs
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareLocal.cs
@@ -14,19 +14,6 @@ protected override async Task<bool> Execute(Context context)
 		{
 			var msbuild = new MSBuildRunner (context);
 
-			// This needs to be built *after* we copy Java.Interop props or we'll get the wrong Mono.Cecil assembly.
-			string remapAsmRefPath = Path.Combine (Configurables.Paths.BuildToolsDir, "remap-assembly-ref", "remap-assembly-ref.csproj");
-			bool result = await msbuild.Run (
-				projectPath: remapAsmRefPath,
-				logTag: "remap-assembly-ref",
-				binlogName: "build-remap-assembly-ref"
-			);
-
-			if (!result) {
-				Log.ErrorLine ("Failed to build remap-assembly-ref");
-				return false;
-			}
-
 			string xfTestPath = Path.Combine (BuildPaths.XamarinAndroidSourceRoot, "tests", "Xamarin.Forms-Performance-Integration", "Xamarin.Forms.Performance.Integration.csproj");
 			return await msbuild.Run (
 				projectPath: xfTestPath,
diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareProps.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareProps.cs
index 0ac0ad2dc9f..a916313eaa3 100644
--- a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareProps.cs
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareProps.cs
@@ -26,10 +26,6 @@ protected override async Task<bool> Execute (Context context)
 
 			LogStep (context, "Copying code signing keys");
 			Utilities.CopyFileToDir (Path.Combine (javaInteropDir, "product.snk"), monoSourceDir);
-			Utilities.CopyFileToDir (
-				Path.Combine (monoSourceDir, "mcs", "class", "msfinal.pub"),
-				BuildPaths.XamarinAndroidSourceRoot
-			);
 
 			LogStep (context, "Configuring Java.Interop property overrides");
 			Utilities.CopyFileToDir (
diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/mono.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/mono.cs
index 52c82fe78d5..8369d5edfc5 100644
--- a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/mono.cs
+++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/mono.cs
@@ -26,7 +26,7 @@ class mono_External_Dependencies_Group : ThirdPartyNoticeGroup
 	class mono_mono_mono_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSourceFullPath, "LICENSE");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnPath, "LICENSE");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/mono";
@@ -37,7 +37,7 @@ class mono_mono_mono_TPN : ThirdPartyNotice
 	class mono_mono_aspnetwebstack_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/aspnetwebstack/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSourceFullPath, "aspnetwebstack", "License.txt");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnPath, "aspnetwebstack", "License.txt");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/aspnetwebstack";
@@ -50,7 +50,7 @@ class mono_mono_aspnetwebstack_TPN : ThirdPartyNotice
 	class mono_mono_boringssl_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/boringssl");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "boringssl", "LICENSE");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "boringssl", "LICENSE");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/boringssl";
@@ -96,7 +96,7 @@ Jeroen Frijters
 	class mono_mono_ikvm_fork_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/ikvm-fork/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "ikvm", "LICENSE");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "ikvm", "LICENSE");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/ikvm-fork";
@@ -109,7 +109,7 @@ class mono_mono_ikvm_fork_TPN : ThirdPartyNotice
 	class mono_mono_linker_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/linker/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "linker", "LICENSE");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "linker", "LICENSE");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/linker";
@@ -120,7 +120,7 @@ class mono_mono_linker_TPN : ThirdPartyNotice
 	class mono_mono_NuGet_BuildTasks_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/NuGet.BuildTasks/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "nuget-buildtasks", "LICENSE.txt");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "nuget-buildtasks", "LICENSE.txt");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/NuGet.BuildTasks";
@@ -133,7 +133,7 @@ class mono_mono_NuGet_BuildTasks_TPN : ThirdPartyNotice
 	class mono_mono_NUnitLite_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/NUnitLite/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "nunit-lite", "NUnitLite-1.0.0", "LICENSE.txt");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "nunit-lite", "NUnitLite-1.0.0", "LICENSE.txt");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/NUnitLite";
@@ -146,7 +146,7 @@ class mono_mono_NUnitLite_TPN : ThirdPartyNotice
 	class mono_mono_rx_net_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/rx/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "rx", "Rx", "NET", "Source", "license.txt");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "rx", "Rx", "NET", "Source", "license.txt");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/rx.net";
@@ -159,7 +159,7 @@ class mono_mono_rx_net_TPN : ThirdPartyNotice
 	class mono_mono_Ix_net_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/rx/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "rx", "Ix", "NET", "license.txt");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "rx", "Ix", "NET", "license.txt");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/Ix.net";
@@ -186,7 +186,7 @@ class mono_llvm_Group : ThirdPartyNoticeGroup
 	class mono_llvm_llvm_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/llvm/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "llvm", "LICENSE.TXT");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "llvm", "LICENSE.TXT");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/llvm";
@@ -197,7 +197,7 @@ class mono_llvm_llvm_TPN : ThirdPartyNotice
 	class mono_llvm_google_test_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/llvm/tree/master/utils/unittest/googletest/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "llvm", "utils", "unittest", "googletest", "LICENSE.TXT");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "llvm", "utils", "unittest", "googletest", "LICENSE.TXT");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/llvm Google Test";
@@ -208,7 +208,7 @@ class mono_llvm_google_test_TPN : ThirdPartyNotice
 	class mono_llvm_openbsd_regex_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/llvm/tree/master/lib/Support/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "llvm", "lib", "Support", "COPYRIGHT.regex");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "llvm", "lib", "Support", "COPYRIGHT.regex");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/llvm OpenBSD Regex";
@@ -219,7 +219,7 @@ class mono_llvm_openbsd_regex_TPN : ThirdPartyNotice
 	class mono_llvm_pyyaml_tests_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/llvm/tree/master/test/YAMLParser/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "llvm", "test", "YAMLParser", "LICENSE.txt");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "llvm", "test", "YAMLParser", "LICENSE.txt");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/llvm pyyaml tests";
@@ -230,7 +230,7 @@ class mono_llvm_pyyaml_tests_TPN : ThirdPartyNotice
 	class mono_llvm_arm_contributions_TPN : ThirdPartyNotice
 	{
 		static readonly Uri    url         = new Uri ("https://github.com/mono/llvm/tree/master/lib/Target/ARM/");
-		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoExternalFullPath, "llvm", "lib", "Target", "ARM", "LICENSE.TXT");
+		static readonly string licenseFile = Path.Combine (Configurables.Paths.MonoSdksTpnExternalPath, "llvm", "lib", "Target", "ARM", "LICENSE.TXT");
 
 		public override string LicenseFile => licenseFile;
 		public override string Name        => "mono/llvm ARM contributions";
diff --git a/build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.OutputSink.cs b/build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.OutputSink.cs
new file mode 100644
index 00000000000..f2d33dd33cf
--- /dev/null
+++ b/build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.OutputSink.cs
@@ -0,0 +1,22 @@
+using System.Text;
+
+namespace Xamarin.Android.Prepare
+{
+	partial class SnRunner
+	{
+		class OutputSink : ToolRunner.ToolOutputSink
+		{
+			public override Encoding Encoding => Encoding.Default;
+
+			public OutputSink (Log log, string logFilePath)
+				: base (log, logFilePath)
+			{
+			}
+
+			public override void WriteLine (string value)
+			{
+				base.WriteLine (value);
+			}
+		}
+	}
+}
diff --git a/build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.cs b/build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.cs
new file mode 100644
index 00000000000..0fb0094ce64
--- /dev/null
+++ b/build-tools/xaprepare/xaprepare/ToolRunners/SnRunner.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace Xamarin.Android.Prepare
+{
+	partial class SnRunner : ToolRunner
+	{
+		protected override string DefaultToolExecutableName => "sn";
+		protected override string ToolName                  => "sn";
+
+		public SnRunner (Context context, Log log = null, string snPath = null)
+			: base (context, log, snPath)
+		{}
+
+		public async Task<bool> ReSign (string snkPath, string assemblyPath, string logTag, string workingDirectory = null)
+		{
+			if (String.IsNullOrEmpty (snkPath))
+				throw new ArgumentException ("must not be null or empty", nameof (snkPath));
+
+			if (String.IsNullOrEmpty (assemblyPath))
+				throw new ArgumentException ("must not be null or empty", nameof (assemblyPath));
+
+			if (String.IsNullOrEmpty (logTag))
+				throw new ArgumentException ("must not be null or empty", nameof (logTag));
+
+			if (String.IsNullOrEmpty (workingDirectory))
+				workingDirectory = BuildPaths.XamarinAndroidSourceRoot;
+
+			ProcessRunner runner = CreateProcessRunner ();
+			runner.AddQuotedArgument ( "-R");
+			runner.AddQuotedArgument (Utilities.GetRelativePath (workingDirectory, assemblyPath));
+			runner.AddQuotedArgument (Utilities.GetRelativePath (workingDirectory, snkPath));
+
+			string message = GetLogMessage (runner);
+			Log.Info (message, CommandMessageColor);
+			Log.StatusLine ();
+
+			return await RunTool (
+				() => {
+					using (var outputSink = (OutputSink)SetupOutputSink (runner, $"sn.{logTag}")) {
+						runner.WorkingDirectory = workingDirectory;
+						return runner.Run ();
+					}
+				}
+			);
+		}
+
+		protected override TextWriter CreateLogSink (string logFilePath)
+		{
+			return new OutputSink (Log, logFilePath);
+		}
+	}
+}
diff --git a/build-tools/xaprepare/xaprepare/xaprepare.csproj b/build-tools/xaprepare/xaprepare/xaprepare.csproj
index 6cccc21ce7f..de16e1e6e31 100644
--- a/build-tools/xaprepare/xaprepare/xaprepare.csproj
+++ b/build-tools/xaprepare/xaprepare/xaprepare.csproj
@@ -134,6 +134,7 @@
     <Compile Include="Steps\Step_Android_SDK_NDK.cs" />
     <Compile Include="Steps\Step_BuildMingwDependencies.cs" />
     <Compile Include="Steps\Step_CopyLibZip.cs" />
+    <Compile Include="Steps\Step_DownloadMonoArchive.cs" />
     <Compile Include="Steps\Step_DownloadNuGet.cs" />
     <Compile Include="Steps\Step_GenerateFiles.cs" />
     <Compile Include="Steps\Step_InstallCorrettoOpenJDK.cs" />
@@ -174,6 +175,8 @@
     <Compile Include="ToolRunners\NuGetRunner.OutputSink.cs" />
     <Compile Include="ToolRunners\SevenZipRunner.cs" />
     <Compile Include="ToolRunners\SevenZipRunner.OutputSink.cs" />
+    <Compile Include="ToolRunners\SnRunner.cs" />
+    <Compile Include="ToolRunners\SnRunner.OutputSink.cs" />
     <Compile Include="ToolRunners\TarRunner.cs" />
     <Compile Include="ToolRunners\TarRunner.OutputSink.cs" />
     <Compile Include="ToolRunners\ToolRunner.cs" />
diff --git a/external/mono b/external/mono
deleted file mode 160000
index edc9e70e04a..00000000000
--- a/external/mono
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit edc9e70e04a2e5a7c760044db980c99496ad0003
diff --git a/mono.snk b/mono.snk
new file mode 100644
index 0000000000000000000000000000000000000000..380116c18fc37e37caee38d5c7f00553381fbf9e
GIT binary patch
literal 596
zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50097b6`6O^&^nH5>Uu78=+UptljwyRbd@W#
zfT1jrG)GMY1|&zrehz5BfKzYJJU_lK`N?_CnS^!a2I$U$-CGYe4Z#kRzb@|2hf5@P
z3{ZjF>U2l_+WIGZBHl;V|LR1Rbfo$G&xFxXX$X^mC{4Z7Uq;RU5~00#<nI7w&=%iK
z#@oEjKVXTH8;PH^SDFl|Y9eD)IR(n4R%kzyhJz#a0fcZDOvqLWa$u+fGr^>T8$V?4
zm0(Z@pa!7K?(Fv6`Sy%zIG6>&?npz0UV%?bgx!7tH#C%jM34vHZxVr2-GyqR){Wb_
z{XsWBT$ZExT8-J6M|x?bD~-_)p-JamyVJi9497FdEQ65@I<~MMyg{tluUqokqOaxj
zlhqj9JtQiyyKdy8TBK}e2S{tm<$7FGKad_^`^?rYM0;cj^<r(}<_k*`ti}$qJaNhR
z0U7GYLsxVkUftkC>51yOyC%wV#(=?x_-cVmn-um!xGBCj903_NLpqj#fY94K!%&o7
zw|E3wgmzMa{N+PDQQ4BhoE7KBA!Hxyi2D5IJ4civ7g7A4#<j*^F!BY52{@vHe_Ez0
z4QJgno?O2X3FjUM-b|M|ALpX@s)prV&D_XcJI@p;?+YrzK2Ann`hVHgmoE06pKUg9
zs+TXb2@kP}O^oqKiyYRmFSkZtN%x@pwJv1K#4lcCB}Oawii)KYvG|NVQK8VHS>@Va
i>Ut2fuAI+%0QCxKtaJZ4tp|R<30%KGIZqYwf2q$<xgwAN

literal 0
HcmV?d00001

diff --git a/msfinal.pub b/msfinal.pub
new file mode 100644
index 0000000000000000000000000000000000000000..110b59c7b0d27388353dcf4116f721595f473e58
GIT binary patch
literal 160
zcmV;R0AK$ABme*efB*oL000060ssI2Bme+XQ$aBR1ONa500968(fU`!uG#RTE`+KN
zuKf+^=>2N!kB9pMc5H)8nUWr|JLj6&)!f0|n$k8CAp(#Kay<Efm4C$HcMy-p2X{{?
z=rRtH>ILlN=pn$R@96PlTucm;!K;}lU1BV%Wh@=~);)AxZ!P8VeqOH+#FjlK9EuV{
OWf&lBz>_phTGEsG5JRQ_

literal 0
HcmV?d00001

diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
index 9c265e0db69..35ff6f133f7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj
@@ -1,4 +1,4 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="..\..\..\..\packages\Xamarin.Build.AsyncTask.0.3.4\build\Xamarin.Build.AsyncTask.props" Condition="Exists('..\..\..\..\packages\Xamarin.Build.AsyncTask.0.3.4\build\Xamarin.Build.AsyncTask.props')" />
   <Import Project="..\..\..\..\packages\NUnit3TestAdapter.3.12.0\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\..\..\..\packages\NUnit3TestAdapter.3.12.0\build\net35\NUnit3TestAdapter.props')" />
@@ -60,6 +60,9 @@
     </Reference>
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Numerics" />
+    <Reference Include="Xamarin.Android.Cecil">
+      <HintPath>..\..\..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
@@ -75,10 +78,6 @@
       <Project>{3F1F2F50-AF1A-4A5A-BEDB-193372F068D7}</Project>
       <Name>Xamarin.Android.Build.Tasks</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\..\..\external\Java.Interop\src\Xamarin.Android.Cecil\Xamarin.Android.Cecil.csproj">
-      <Project>{15945D4B-FF56-4BCC-B598-2718D199DD08}</Project>
-      <Name>Xamarin.Android.Cecil</Name>
-    </ProjectReference>
     <ProjectReference Include="..\..\..\..\external\xamarin-android-tools\src\Xamarin.Android.Tools.AndroidSdk\Xamarin.Android.Tools.AndroidSdk.csproj">
       <Project>{e34bcfa0-caa4-412c-aa1c-75db8d67d157}</Project>
       <Name>Xamarin.Android.Tools.AndroidSdk</Name>
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
index 36feeb3347d..94c7567b9e5 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
@@ -1,4 +1,4 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="..\..\packages\Xamarin.Build.AsyncTask.0.3.4\build\Xamarin.Build.AsyncTask.props" Condition="Exists('..\..\packages\Xamarin.Build.AsyncTask.0.3.4\build\Xamarin.Build.AsyncTask.props')" />
   <PropertyGroup>
@@ -112,6 +112,12 @@
     <Reference Include="Mono.CompilerServices.SymbolWriter.dll">
       <HintPath>..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Mono.CompilerServices.SymbolWriter.dll</HintPath>
     </Reference>
+    <Reference Include="Xamarin.Android.Cecil">
+      <HintPath>..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.dll</HintPath>
+    </Reference>
+    <Reference Include="Xamarin.Android.Cecil.Mdb">
+      <HintPath>..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.Mdb.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="$(IntermediateOutputPath)Profile.g.cs" />
@@ -609,7 +615,7 @@
   -->
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <Import Project="Xamarin.Android.Build.Tasks.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
   </Target>
@@ -725,14 +731,6 @@
       <Project>{E248B2CA-303B-4645-ADDC-9D4459D550FD}</Project>
       <Name>libZipSharp</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\external\Java.Interop\src\Xamarin.Android.Cecil\Xamarin.Android.Cecil.csproj">
-      <Project>{15945D4B-FF56-4BCC-B598-2718D199DD08}</Project>
-      <Name>Xamarin.Android.Cecil</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\external\Java.Interop\src\Xamarin.Android.Cecil\Xamarin.Android.Cecil.Mdb.csproj">
-      <Project>{C0487169-8F81-497F-919E-EB42B1D0243F}</Project>
-      <Name>Xamarin.Android.Cecil.Mdb</Name>
-    </ProjectReference>
     <ProjectReference Include="..\..\external\xamarin-android-tools\src\Xamarin.Android.Tools.AndroidSdk\Xamarin.Android.Tools.AndroidSdk.csproj">
       <Project>{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}</Project>
       <Name>Xamarin.Android.Tools.AndroidSdk</Name>
diff --git a/src/Xamarin.Android.Tools.Aidl/Xamarin.Android.Tools.Aidl.csproj b/src/Xamarin.Android.Tools.Aidl/Xamarin.Android.Tools.Aidl.csproj
index 05cbbfaf723..b43b3cc79c8 100644
--- a/src/Xamarin.Android.Tools.Aidl/Xamarin.Android.Tools.Aidl.csproj
+++ b/src/Xamarin.Android.Tools.Aidl/Xamarin.Android.Tools.Aidl.csproj
@@ -33,6 +33,9 @@
       <HintPath>..\..\packages\Irony.0.9.1\lib\net40\Irony.dll</HintPath>
       <Private>False</Private>
     </Reference>
+    <Reference Include="Xamarin.Android.Cecil">
+      <HintPath>..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
@@ -46,10 +49,4 @@
   <ItemGroup>
     <None Include="packages.config" />
   </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\external\Java.Interop\src\Xamarin.Android.Cecil\Xamarin.Android.Cecil.csproj">
-      <Project>{15945D4B-FF56-4BCC-B598-2718D199DD08}</Project>
-      <Name>Xamarin.Android.Cecil</Name>
-    </ProjectReference>
-  </ItemGroup>
 </Project>
diff --git a/src/Xamarin.Android.Tools.JavadocImporter/Xamarin.Android.Tools.JavadocImporter.csproj b/src/Xamarin.Android.Tools.JavadocImporter/Xamarin.Android.Tools.JavadocImporter.csproj
index 71be60d73ca..7d99fa7b1f2 100644
--- a/src/Xamarin.Android.Tools.JavadocImporter/Xamarin.Android.Tools.JavadocImporter.csproj
+++ b/src/Xamarin.Android.Tools.JavadocImporter/Xamarin.Android.Tools.JavadocImporter.csproj
@@ -34,6 +34,9 @@
       <HintPath>..\..\packages\Microsoft.Xml.SgmlReader.1.8.14\lib\net45\SgmlReaderDll.dll</HintPath>
     </Reference>
     <Reference Include="System.Xml" />
+    <Reference Include="Xamarin.Android.Cecil">
+      <HintPath>..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -46,7 +49,7 @@
     <Compile Include="MdocHelper.cs" />
     <Compile Include="samples.cs" />
     <Compile Include="TypeUtilities.cs" />
-    <Compile Include="..\..\external\mono\mcs\class\Mono.Options\Mono.Options\Options.cs">
+    <Compile Include="$(LinkerSourceFullPath)\analyzer\common\Mono.Options\Options.cs">
       <Link>Options.cs</Link>
     </Compile>
     <Compile Include="..\..\external\Java.Interop\src\utils\StringRocks.cs">
@@ -54,10 +57,6 @@
     </Compile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\external\Java.Interop\src\Xamarin.Android.Cecil\Xamarin.Android.Cecil.csproj">
-      <Project>{15945D4B-FF56-4BCC-B598-2718D199DD08}</Project>
-      <Name>Xamarin.Android.Cecil</Name>
-    </ProjectReference>
     <ProjectReference Include="..\..\external\LibZipSharp\libZipSharp.csproj">
       <Project>{E248B2CA-303B-4645-ADDC-9D4459D550FD}</Project>
       <Name>libZipSharp</Name>
@@ -83,4 +82,4 @@
   <Import Project="..\..\external\Java.Interop\src\Java.Interop.Tools.TypeNameMappings\Java.Interop.Tools.TypeNameMappings.projitems" Label="Shared" Condition="Exists('..\..\external\Java.Interop\src\Java.Interop.Tools.TypeNameMappings\Java.Interop.Tools.TypeNameMappings.projitems')" />
   <Import Project="..\..\external\Java.Interop\src\Java.Interop.NamingCustomAttributes\Java.Interop.NamingCustomAttributes.projitems" Label="Shared" Condition="Exists('..\..\external\Java.Interop\src\Java.Interop.NamingCustomAttributes\Java.Interop.NamingCustomAttributes.projitems')" />
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-</Project>
\ No newline at end of file
+</Project>
diff --git a/src/mono.pub b/src/mono.pub
deleted file mode 120000
index 963b3c2481b..00000000000
--- a/src/mono.pub
+++ /dev/null
@@ -1 +0,0 @@
-../external/mono/mcs/class/mono.pub
\ No newline at end of file
diff --git a/src/mono.pub b/src/mono.pub
new file mode 100644
index 0000000000000000000000000000000000000000..52c20a107e3d36d7416352440377baa019b7677f
GIT binary patch
literal 160
zcmV;R0AK$ABme*efB*oL000060ssI2Bme+XQ$aBR1ONa50097b6`6O^&^nH5>Uu78
z=+UptljwyRbd@W#fT1jrG)GMY1|&zrehz5BfKzYJJU_lK`N?_CnS^!a2I$U$-CGYe
z4Z#kRzb@|2hf5@P3{ZjF>U2l_+WIGZBHl;V|LR1Rbfo$G&xFxXX$X^mC{4Z7Uq;RU
O5~00#<nI7w&=%jX0!0r1

literal 0
HcmV?d00001

diff --git a/src/monodroid/CMakeLists.txt b/src/monodroid/CMakeLists.txt
index ffc96946d24..44151c8c413 100644
--- a/src/monodroid/CMakeLists.txt
+++ b/src/monodroid/CMakeLists.txt
@@ -191,7 +191,6 @@ check_include_files("linux/rtnetlink.h" HAVE_LINUX_RTNETLINK_H)
 set(SOURCES_DIR ${TOP_DIR}/jni)
 set(MONODROID_SOURCES
   ${MONODROID_SOURCES}
-  ${MONO_PATH}/support/zlib-helper.c
   ${SOURCES_DIR}/new_delete.cc
   ${SOURCES_DIR}/android-system.cc
   ${SOURCES_DIR}/cpu-arch-detect.cc
@@ -260,4 +259,3 @@ elseif(NOT ANDROID)
 endif()
 
 target_link_libraries(${MONO_ANDROID_LIB} ${LINK_LIBS} xamarin-app)
-
diff --git a/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/Xamarin.Android.Bcl-Tests.csproj b/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/Xamarin.Android.Bcl-Tests.csproj
index 104c4f19b63..49a94288e68 100644
--- a/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/Xamarin.Android.Bcl-Tests.csproj
+++ b/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/Xamarin.Android.Bcl-Tests.csproj
@@ -51,22 +51,22 @@
     <Reference Include="System.IO.Compression.FileSystem" />
     <Reference Include="System.Net.Http" />
     <Reference Include="xunit.abstractions">
-      <HintPath>..\..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll</HintPath>
+      <HintPath>..\..\..\packages\xunit.abstractions.2.0.3\lib\netstandard1.0\xunit.abstractions.dll</HintPath>
     </Reference>
     <Reference Include="xunit.assert">
-      <HintPath>..\..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll</HintPath>
+      <HintPath>..\..\..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll</HintPath>
     </Reference>
     <Reference Include="xunit.core">
-      <HintPath>..\..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll</HintPath>
+      <HintPath>..\..\..\packages\xunit.extensibility.core.2.4.1\lib\netstandard1.1\xunit.core.dll</HintPath>
     </Reference>
     <Reference Include="xunit.execution.dotnet">
-      <HintPath>..\..\..\packages\xunit.extensibility.execution.2.3.1\lib\netstandard1.1\xunit.execution.dotnet.dll</HintPath>
+      <HintPath>..\..\..\packages\xunit.extensibility.execution.2.4.1\lib\netstandard1.1\xunit.execution.dotnet.dll</HintPath>
     </Reference>
     <Reference Include="Xunit.NetCore.Extensions">
-      <HintPath>$(MonoSourceDirectory)\external\xunit-binaries\Xunit.NetCore.Extensions.dll</HintPath>
+      <HintPath>$(MonoSourceDirectory)\sdks\out\android-bcl\monodroid\tests\Xunit.NetCore.Extensions.dll</HintPath>
     </Reference>
     <Reference Include="xunit.execution.desktop">
-      <HintPath>$(MonoSourceDirectory)\external\xunit-binaries\xunit.execution.desktop.dll</HintPath>
+      <HintPath>..\..\..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.execution.desktop.dll</HintPath>
     </Reference>
     <Reference Include="System.Data" />
     <Reference Include="Mono.Data.Sqlite" />
diff --git a/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/packages.config b/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/packages.config
index 3dad8f33c31..4e710bca0f5 100644
--- a/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/packages.config
+++ b/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/packages.config
@@ -1,4 +1,4 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Microsoft.NETCore.Platforms" version="2.0.1" targetFramework="monoandroid81" />
   <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="monoandroid80" />
@@ -45,11 +45,11 @@
   <package id="System.Threading.Timer" version="4.3.0" targetFramework="monoandroid80" />
   <package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="monoandroid80" />
   <package id="System.Xml.XDocument" version="4.3.0" targetFramework="monoandroid80" />
-  <package id="xunit" version="2.3.1" targetFramework="monoandroid80" />
-  <package id="xunit.abstractions" version="2.0.1" targetFramework="monoandroid80" />
-  <package id="xunit.analyzers" version="0.8.0" targetFramework="monoandroid81" />
-  <package id="xunit.assert" version="2.3.1" targetFramework="monoandroid80" />
-  <package id="xunit.core" version="2.3.1" targetFramework="monoandroid80" />
-  <package id="xunit.extensibility.core" version="2.3.1" targetFramework="monoandroid80" />
-  <package id="xunit.extensibility.execution" version="2.3.1" targetFramework="monoandroid80" />
-</packages>
\ No newline at end of file
+  <package id="xunit" version="2.4.1" targetFramework="monoandroid80" />
+  <package id="xunit.abstractions" version="2.0.3" targetFramework="monoandroid80" />
+  <package id="xunit.analyzers" version="0.10.0" targetFramework="monoandroid81" />
+  <package id="xunit.assert" version="2.4.1" targetFramework="monoandroid80" />
+  <package id="xunit.core" version="2.4.1" targetFramework="monoandroid80" />
+  <package id="xunit.extensibility.core" version="2.4.1" targetFramework="monoandroid80" />
+  <package id="xunit.extensibility.execution" version="2.4.1" targetFramework="monoandroid80" />
+</packages>
diff --git a/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.targets b/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.targets
index e113750d66f..c396a39d4de 100644
--- a/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.targets
+++ b/tests/MSBuildDeviceIntegration/MSBuildDeviceIntegration.targets
@@ -2,10 +2,6 @@
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="_RemapAssemblies" AfterTargets="Build">
     <ItemGroup>
-      <_Source Include="..\..\bin\Test$(Configuration)\MSBuildDeviceIntegration\Mono.Debugging.Soft.dll">
-        <From>Mono.Cecil.Mdb</From>
-        <To>..\..\bin\Test$(Configuration)\MSBuildDeviceIntegration\Xamarin.Android.Cecil.Mdb.dll</To>
-      </_Source>
       <_Source Include="..\..\bin\Test$(Configuration)\MSBuildDeviceIntegration\Mono.Debugging.Soft.dll">
         <From>Mono.Cecil</From>
         <To>..\..\bin\Test$(Configuration)\MSBuildDeviceIntegration\Xamarin.Android.Cecil.dll</To>
@@ -15,7 +11,7 @@
         <To>..\..\bin\Test$(Configuration)\MSBuildDeviceIntegration\Xamarin.Android.Cecil.dll</To>
       </_Source>
     </ItemGroup>
-    <Copy SourceFiles="..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.dll;..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.Mdb.dll"
+    <Copy SourceFiles="..\..\bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Cecil.dll"
         DestinationFolder="..\..\bin\Test$(Configuration)\MSBuildDeviceIntegration" />
     <Exec
         Command="$(RemapAssemblyRefTool) &quot;%(_Source.Identity)&quot; &quot;$(IntermediateOutputPath)%(_Source.Filename)%(_Source.Extension)&quot; %(_Source.From) &quot;%(_Source.To)&quot;"
