From 300c3a8cd6e145cbc663682a596cb803274b8754 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 6 May 2020 22:55:07 -0500 Subject: [PATCH] [.NET 5] NuGet workarounds for Xamarin.Forms projects Context: https://github.com/xamarin/net5-samples/blob/d525d8a2d60700f52f86372c47e83d646d800aa4/Directory.Android.targets Currently, .NET 5 will not restore *existing* Xamarin.Android NuGet packages. It does not know to map `netcoreapp5.0` to `MonoAndroid10.0`, `MonoAndroid9` etc. We'll need to work around this until this lands: * https://github.com/NuGet/NuGet.Client/pull/3339 To get a Xamarin.Forms project building & running *at all* in `xamarin/net5-samples`, I had to: 1. Change `$(AssetTargetFallback)` 2. Write an MSBuild target to replace any instances of `netstandard2.0\Xamarin.Forms.Platform.dll` with `MonoAndroid10.0\Xamarin.Forms.Platform.dll`. 3. Add additional platform-specific assemblies in `$(PkgXamarin_Forms)\lib\MonoAndroid10.0\` There are still some issues with this: 1. You get a lot of `NU1701` warnings due to `$(AssetTargetFallback)`. 2. Due to: https://github.com/NuGet/docs.microsoft.com-nuget/issues/1955 You have to manually list *every* transitive dependency, which totals around ~36 packages for AndroidX. These drawbacks make it completely impractical to run some subset of our existing MSBuild tests on .NET 5. We would have to list the entire tree of `` for every test. Since we might be waiting a bit of time for this, I have been able to come up with some workarounds to solve these problems for now: 1. Add a `Microsoft.Android.Sdk.NuGet.targets` with workarounds that we will completely remove down the road (I hope!). 2. Use `$(PackageTargetFallback)` instead of `$(AssetTargetFallback)`. It does not emit `NU1701` warnings, and transitive dependencies work! It is a deprecated MSBuild property, but should be fine as a workaround. 3. Write a `_FixupNuGetReferences` MSBuild target that runs after `ResolvePackageAssets`. A `` MSBuild task will remove any `netstandard2.0` assemblies where platform-specific ones exist. It also needs to add platform-specific assemblies that are missing. With this in place, a Xamarin.Forms `.csproj` with no hacks works! netcoreapp5.0 Exe I created a new `XamarinFormsXASdkProject` class for use in our existing .NET 5 MSBuild tests. Other changes: * `$(XamarinAndroidVersion)` needs to be filled out for the AndroidX MSBuild targets: https://github.com/xamarin/XamarinAndroidXMigration/blob/ea130ca0d0e9b3e20edccec02364f36da11ada6b/source/Xamarin.AndroidX.Migration/BuildTasks/Xamarin.AndroidX.Migration.targets#L107 * `$(RuntimeIdentifier)` should have a default value for application projects. * Some tweaks to make `XASdkProject` more flexible. * `Xamarin.ProjectTools.DotNetStandard` projects now support ``. * Added AndroidX-compatible `Tabbar.xml` and `Toolbar.xml` --- .../create-packs/Microsoft.Android.Sdk.proj | 1 + .../Microsoft.Android.Sdk.NuGet.targets | 46 ++++++++++ .../targets/Microsoft.Android.Sdk.targets | 2 + .../Tasks/FixupNuGetReferences.cs | 78 ++++++++++++++++ .../Xamarin.Android.Build.Tests/XASdkTests.cs | 10 +++ .../Android/KnownPackages.cs | 5 ++ .../Android/XASdkProject.cs | 43 +++++---- .../Android/XamarinFormsXASdkProject.cs | 89 +++++++++++++++++++ .../Common/DotNetStandard.cs | 5 ++ .../Resources/AndroidX/Tabbar.xml | 10 +++ .../Resources/AndroidX/Toolbar.xml | 6 ++ .../Xamarin.ProjectTools.csproj | 6 ++ .../Tests/XASdkDeployTests.cs | 15 +++- 13 files changed, 293 insertions(+), 23 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NuGet.targets create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/FixupNuGetReferences.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinFormsXASdkProject.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Tabbar.xml create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Toolbar.xml diff --git a/build-tools/create-packs/Microsoft.Android.Sdk.proj b/build-tools/create-packs/Microsoft.Android.Sdk.proj index 796ce768111..52399c6385e 100644 --- a/build-tools/create-packs/Microsoft.Android.Sdk.proj +++ b/build-tools/create-packs/Microsoft.Android.Sdk.proj @@ -102,6 +102,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and $(AndroidPackVersionLong) + $(AndroidPackVersionLong) + + + + + + + + + + + monoandroid10.0; + monoandroid90; + monoandroid81; + monoandroid80; + monoandroid70; + monoandroid60; + monoandroid50; + $(PackageTargetFallback); + + + + + + + + + + + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets index 1dcdb83e167..7c35a4a75f8 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets @@ -9,6 +9,7 @@ true false true + android.21-x86 Properties\AndroidManifest.xml Library @@ -20,6 +21,7 @@ + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/FixupNuGetReferences.cs b/src/Xamarin.Android.Build.Tasks/Tasks/FixupNuGetReferences.cs new file mode 100644 index 00000000000..7e0f423b4b0 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/FixupNuGetReferences.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Build.Framework; + +namespace Xamarin.Android.Tasks +{ + /// + /// This task contains *temporary* workarounds for NuGet in .NET 5. + /// + public class FixupNuGetReferences : AndroidTask + { + public override string TaskPrefix => "FNR"; + + [Required] + public string [] PackageTargetFallback { get; set; } + + public ITaskItem [] CopyLocalItems { get; set; } + + [Output] + public string [] AssembliesToAdd { get; set; } + + [Output] + public ITaskItem [] AssembliesToRemove { get; set; } + + public override bool RunTask () + { + if (CopyLocalItems == null || CopyLocalItems.Length == 0) + return true; + + var assembliesToAdd = new Dictionary (); + var assembliesToRemove = new List (); + var fallbackDirectories = new HashSet (); + + foreach (var item in CopyLocalItems) { + var directory = Path.GetDirectoryName (item.ItemSpec); + var directoryName = Path.GetFileName (directory); + Log.LogDebugMessage ($"{directoryName} -> {item.ItemSpec}"); + if (directoryName == "netstandard2.0") { + var parent = Directory.GetParent (directory); + foreach (var nugetDirectory in parent.EnumerateDirectories ()) { + var name = Path.GetFileName (nugetDirectory.Name); + foreach (var fallback in PackageTargetFallback) { + if (!string.Equals (name, fallback, StringComparison.OrdinalIgnoreCase)) + continue; + var fallbackDirectory = Path.Combine (parent.FullName, fallback); + fallbackDirectories.Add (fallbackDirectory); + + // Remove the netstandard assembly, if there is a platform-specific one + var path = Path.Combine (fallbackDirectory, Path.GetFileName (item.ItemSpec)); + if (File.Exists (path)) { + Log.LogDebugMessage ($"Removing: {item.ItemSpec}"); + assembliesToRemove.Add (item); + } + } + } + } + } + + // Look for any platform-specific assemblies + foreach (var directory in fallbackDirectories) { + foreach (var assembly in Directory.GetFiles (directory, "*.dll")) { + var assemblyName = Path.GetFileName (assembly); + if (!assembliesToAdd.ContainsKey (assemblyName)) { + Log.LogDebugMessage ($"Adding: {assembly}"); + assembliesToAdd.Add (assemblyName, assembly); + } + } + } + + AssembliesToAdd = assembliesToAdd.Values.ToArray (); + AssembliesToRemove = assembliesToRemove.ToArray (); + + return !Log.HasLoggedErrors; + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 36915bb9f7c..a6eb76170be 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -89,6 +89,16 @@ public void DotNetBuild (string runtimeIdentifier, bool isRelease) } } + [Test] + [Category ("SmokeTests")] + public void DotNetBuildXamarinForms () + { + var proj = new XamarinFormsXASdkProject (SdkVersion); + var dotnet = CreateDotNetBuilder (proj); + Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed"); + Assert.IsTrue (StringAssertEx.ContainsText (dotnet.LastBuildOutput, " 0 Warning(s)"), "Should have no MSBuild warnings."); + } + [Test] public void BuildWithLiteSdk () { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs index ef5a28363d6..67b2679e34e 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownPackages.cs @@ -208,6 +208,11 @@ public static class KnownPackages }, } }; + public static Package XamarinForms_4_5_0_617 = new Package { + Id = "Xamarin.Forms", + Version = "4.5.0.617", + TargetFramework = "MonoAndroid10.0", + }; public static Package XamarinFormsMaps_4_0_0_425677 = new Package { Id = "Xamarin.Forms.Maps", Version = "4.0.0.425677", diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XASdkProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XASdkProject.cs index 89689ac290b..dcd36742a08 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XASdkProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XASdkProject.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Xamarin.ProjectTools { @@ -16,10 +13,25 @@ public class XASdkProject : DotNetStandard "; - readonly string default_layout_main; - readonly string default_main_activity_cs; - readonly string default_android_manifest; - readonly byte [] icon_binary_mdpi; + static readonly string default_layout_main; + static readonly string default_main_activity_cs; + static readonly string default_android_manifest; + static readonly byte [] icon_binary_mdpi; + + static XASdkProject () + { + var assembly = typeof (XASdkProject).Assembly; + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.AndroidManifest.xml"))) + default_android_manifest = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.cs"))) + default_main_activity_cs = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.LayoutMain.axml"))) + default_layout_main = sr.ReadToEnd (); + using (var stream = assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.Icon.png")) { + icon_binary_mdpi = new byte [stream.Length]; + stream.Read (icon_binary_mdpi, 0, (int) stream.Length); + } + } public string PackageName { get; set; } public string JavaPackageName { get; set; } @@ -35,24 +47,13 @@ public XASdkProject (string sdkVersion = "", string outputType = "Exe") GlobalPackagesFolder = Path.Combine (XABuildPaths.TopDirectory, "packages"); SetProperty (KnownProperties.OutputType, outputType); - using (var sr = new StreamReader (typeof (XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.AndroidManifest.xml"))) - default_android_manifest = sr.ReadToEnd (); - using (var sr = new StreamReader (typeof (XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.cs"))) - default_main_activity_cs = sr.ReadToEnd (); - using (var sr = new StreamReader (typeof (XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.LayoutMain.axml"))) - default_layout_main = sr.ReadToEnd (); - using (var stream = typeof (XamarinAndroidCommonProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.Icon.png")) { - icon_binary_mdpi = new byte [stream.Length]; - stream.Read (icon_binary_mdpi, 0, (int) stream.Length); - } - // Add relevant Android content to our project without writing it to the .csproj file if (outputType == "Exe") { Sources.Add (new BuildItem.Source ("Properties\\AndroidManifest.xml") { TextContent = () => default_android_manifest.Replace ("${PROJECT_NAME}", ProjectName).Replace ("${PACKAGENAME}", string.Format ("{0}.{0}", ProjectName)) }); } - Sources.Add (new BuildItem.Source ($"MainActivity{Language.DefaultExtension}") { TextContent = () => ProcessSourceTemplate (default_main_activity_cs) }); + Sources.Add (new BuildItem.Source ($"MainActivity{Language.DefaultExtension}") { TextContent = () => ProcessSourceTemplate (MainActivity ?? DefaultMainActivity) }); Sources.Add (new BuildItem.Source ("Resources\\layout\\Main.axml") { TextContent = () => default_layout_main }); Sources.Add (new BuildItem.Source ("Resources\\values\\Strings.xml") { TextContent = () => default_strings_xml.Replace ("${PROJECT_NAME}", ProjectName) }); Sources.Add (new BuildItem.Source ("Resources\\drawable-mdpi\\Icon.png") { BinaryContent = () => icon_binary_mdpi }); @@ -65,6 +66,10 @@ public XASdkProject (string sdkVersion = "", string outputType = "Exe") public string IntermediateOutputPath => Path.Combine ("obj", Configuration, TargetFramework.ToLowerInvariant ()); + public string DefaultMainActivity => default_main_activity_cs; + + public string MainActivity { get; set; } + public override string ProcessSourceTemplate (string source) { return source.Replace ("${ROOT_NAMESPACE}", RootNamespace ?? ProjectName) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinFormsXASdkProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinFormsXASdkProject.cs new file mode 100644 index 00000000000..af593a26f8b --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinFormsXASdkProject.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Xamarin.ProjectTools +{ + public class XamarinFormsXASdkProject : XASdkProject + { + static readonly string default_main_activity_cs; + static readonly string colors_xml; + static readonly string styles_xml; + static readonly string Tabbar_xml; + static readonly string Toolbar_xml; + static readonly string MainPage_xaml; + static readonly string MainPage_xaml_cs; + static readonly string App_xaml; + static readonly string App_xaml_cs; + + static XamarinFormsXASdkProject () + { + var assembly = typeof (XamarinFormsXASdkProject).Assembly; + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.MainActivity.cs"))) + default_main_activity_cs = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.colors.xml"))) + colors_xml = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.styles.xml"))) + styles_xml = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.AndroidX.Tabbar.xml"))) + Tabbar_xml = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.AndroidX.Toolbar.xml"))) + Toolbar_xml = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.MainPage.xaml"))) + MainPage_xaml = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.MainPage.xaml.cs"))) + MainPage_xaml_cs = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.App.xaml"))) + App_xaml = sr.ReadToEnd (); + using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Forms.App.xaml.cs"))) + App_xaml_cs = sr.ReadToEnd (); + } + + + public XamarinFormsXASdkProject (string sdkVersion = "", string outputType = "Exe") + : base (sdkVersion, outputType) + { + PackageReferences.Add (KnownPackages.XamarinForms_4_5_0_617); + + // Workaround for AndroidX, see: https://github.com/xamarin/AndroidSupportComponents/pull/239 + Imports.Add (new Import (() => "Directory.Build.targets") { + TextContent = () => + @" + + + + " + }); + + Sources.Add (new AndroidItem.AndroidResource ("Resources\\values\\colors.xml") { + TextContent = () => colors_xml, + }); + Sources.Add (new AndroidItem.AndroidResource ("Resources\\values\\styles.xml") { + TextContent = () => styles_xml, + }); + Sources.Add (new AndroidItem.AndroidResource ("Resources\\layout\\Tabbar.xml") { + TextContent = () => Tabbar_xml, + }); + Sources.Add (new AndroidItem.AndroidResource ("Resources\\layout\\Toolbar.xml") { + TextContent = () => Toolbar_xml, + }); + Sources.Add (new BuildItem ("EmbeddedResource", "MainPage.xaml") { + TextContent = MainPageXaml, + }); + Sources.Add (new BuildItem.Source ("MainPage.xaml.cs") { + TextContent = () => ProcessSourceTemplate (MainPage_xaml_cs), + }); + Sources.Add (new BuildItem ("EmbeddedResource", "App.xaml") { + TextContent = () => ProcessSourceTemplate (App_xaml), + }); + Sources.Add (new BuildItem.Source ("App.xaml.cs") { + TextContent = () => ProcessSourceTemplate (App_xaml_cs), + }); + + MainActivity = default_main_activity_cs; + } + + protected virtual string MainPageXaml () => ProcessSourceTemplate (MainPage_xaml); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs index c9875ae493b..77d457119e5 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs @@ -82,6 +82,11 @@ public override string SaveProject () } sb.AppendLine ("\t"); } + foreach (var import in Imports) { + var project = import.Project (); + if (project != "Directory.Build.props" && project != "Directory.Build.targets") + sb.AppendLine ($"\t"); + } return $"\r\n{sb.ToString ()}\r\n"; } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Tabbar.xml b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Tabbar.xml new file mode 100644 index 00000000000..9fcf0fc2b6f --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Tabbar.xml @@ -0,0 +1,10 @@ + diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Toolbar.xml b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Toolbar.xml new file mode 100644 index 00000000000..7addb101e9b --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/AndroidX/Toolbar.xml @@ -0,0 +1,6 @@ + diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj index 966539bbf42..894ed2932ca 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj @@ -9,6 +9,12 @@ + + Xamarin.ProjectTools.Resources.AndroidX.Tabbar.xml + + + Xamarin.ProjectTools.Resources.AndroidX.Toolbar.xml + Xamarin.ProjectTools.Resources.Wear.LayoutMain.axml diff --git a/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs b/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs index 32d99271f86..e8c9b9f0fbe 100644 --- a/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs @@ -17,14 +17,21 @@ public class XASdkDeployTests : DeviceTest .FirstOrDefault () ?? "0.0.1"; [Test] - public void DotNetInstallAndRun ([Values (false, true)] bool isRelease) + public void DotNetInstallAndRun ([Values (false, true)] bool isRelease, [Values (false, true)] bool xamarinForms) { if (!HasDevices) Assert.Ignore ("Skipping Test. No devices available."); - var proj = new XASdkProject (SdkVersion) { - IsRelease = isRelease - }; + XASdkProject proj; + if (xamarinForms) { + proj = new XamarinFormsXASdkProject (SdkVersion) { + IsRelease = isRelease + }; + } else { + proj = new XASdkProject (SdkVersion) { + IsRelease = isRelease + }; + } proj.SetProperty (KnownProperties.AndroidSupportedAbis, DeviceAbi); proj.SetRuntimeIdentifier (DeviceAbi);