diff --git a/.gitmodules b/.gitmodules index 0c3ab256194..7dd76d7ea06 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,6 @@ path = external/llvm url = https://github.com/mono/llvm.git branch = master +[submodule "external/xamarin-android-tools"] + path = external/xamarin-android-tools + url = git@github.com:xamarin/xamarin-android-tools.git diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index 03bb4f780aa..f65014728cc 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -91,12 +91,16 @@ Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "bundle", "build-tools\bundl EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xa-prep-tasks", "build-tools\xa-prep-tasks\xa-prep-tasks.csproj", "{7CE69551-BD73-4726-ACAA-AAF89C84BAF8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools", "external\xamarin-android-tools\src\Xamarin.Android.Tools\Xamarin.Android.Tools.csproj", "{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|AnyCPU = Debug|AnyCPU Release|AnyCPU = Release|AnyCPU XAIntegrationDebug|AnyCPU = XAIntegrationDebug|AnyCPU XAIntegrationRelease|AnyCPU = XAIntegrationRelease|AnyCPU + XAIntegrationDebug|Any CPU = XAIntegrationDebug|Any CPU + XAIntegrationRelease|Any CPU = XAIntegrationRelease|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3F1F2F50-AF1A-4A5A-BEDB-193372F068D7}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU @@ -417,6 +421,18 @@ Global {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationDebug|AnyCPU.Build.0 = Debug|Any CPU {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationRelease|AnyCPU.ActiveCfg = Debug|Any CPU {7CE69551-BD73-4726-ACAA-AAF89C84BAF8}.XAIntegrationRelease|AnyCPU.Build.0 = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Release|AnyCPU.Build.0 = Release|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationDebug|AnyCPU.ActiveCfg = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationDebug|AnyCPU.Build.0 = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationRelease|AnyCPU.ActiveCfg = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationRelease|AnyCPU.Build.0 = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationDebug|Any CPU.ActiveCfg = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationDebug|Any CPU.Build.0 = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationRelease|Any CPU.ActiveCfg = Debug|Any CPU + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.XAIntegrationRelease|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} @@ -460,6 +476,7 @@ Global {0DE278D6-000F-4001-BB98-187C0AF58A61} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} {1640725C-4DB8-4D8D-BC96-74E688A06EEF} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} {7CE69551-BD73-4726-ACAA-AAF89C84BAF8} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} + {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157} = {04E3E11E-B47D-4599-8AFC-50515A95E715} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 diff --git a/external/xamarin-android-tools b/external/xamarin-android-tools new file mode 160000 index 00000000000..641945a90af --- /dev/null +++ b/external/xamarin-android-tools @@ -0,0 +1 @@ +Subproject commit 641945a90af8a4a64b83d6b689c1f3a4fb089ce2 diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs index 1e229aea339..8009d3f0283 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs @@ -10,6 +10,7 @@ using Java.Interop.Tools.Diagnostics; using Xamarin.Android.Build.Utilities; +using Xamarin.Android.Tools; namespace Xamarin.Android.Tasks { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/NdkUtils.cs b/src/Xamarin.Android.Build.Tasks/Tasks/NdkUtils.cs index 4928b6dfbca..8d0756c8ec9 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/NdkUtils.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/NdkUtils.cs @@ -11,6 +11,7 @@ using Java.Interop.Tools.Diagnostics; using Xamarin.Android.Build.Utilities; +using Xamarin.Android.Tools; namespace Xamarin.Android.Tasks { 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 97caaae9c18..06b9bfd8355 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -643,6 +643,10 @@ <Project>{E248B2CA-303B-4645-ADDC-9D4459D550FD}</Project> <Name>libZipSharp</Name> </ProjectReference> + <ProjectReference Include="..\..\external\xamarin-android-tools\src\Xamarin.Android.Tools\Xamarin.Android.Tools.csproj"> + <Project>{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}</Project> + <Name>Xamarin.Android.Tools</Name> + </ProjectReference> </ItemGroup> <ItemGroup> <Folder Include="pdb2mdb\" /> diff --git a/src/Xamarin.Android.Build.Utilities/AndroidAppManifest.cs b/src/Xamarin.Android.Build.Utilities/AndroidAppManifest.cs deleted file mode 100644 index d7afc4cabe6..00000000000 --- a/src/Xamarin.Android.Build.Utilities/AndroidAppManifest.cs +++ /dev/null @@ -1,314 +0,0 @@ -using System; -using System.Linq; -using System.Xml; -using System.Collections.Generic; -using System.Xml.Linq; -using System.Text.RegularExpressions; -using System.Text; -using System.IO; - -namespace Xamarin.Android.Build.Utilities -{ - public class AndroidAppManifest - { - XDocument doc; - XElement manifest, application, usesSdk; - - static readonly XNamespace aNS = "http://schemas.android.com/apk/res/android"; - static readonly XName aName = aNS + "name"; - - AndroidAppManifest (XDocument doc) - { - this.doc = doc; - manifest = doc.Root; - if (manifest.Name != "manifest") - throw new Exception ("App manifest does not have 'manifest' root element"); - - application = manifest.Element ("application"); - if (application == null) - manifest.Add (application = new XElement ("application")); - - usesSdk = manifest.Element ("uses-sdk"); - if (usesSdk == null) - manifest.Add (usesSdk = new XElement ("uses-sdk")); - } - - public static string CanonicalizePackageName (string packageNameOrAssemblyName) - { - if (packageNameOrAssemblyName == null) - throw new ArgumentNullException ("packageNameOrAssemblyName"); - if (string.IsNullOrEmpty (packageNameOrAssemblyName = packageNameOrAssemblyName.Trim ())) - throw new ArgumentException ("Must specify a package name or assembly name", "packageNameOrAssemblyName"); - - string[] packageParts = packageNameOrAssemblyName.Split (new[]{'.'}, StringSplitOptions.RemoveEmptyEntries); - for (int i = 0; i < packageParts.Length; ++i) { - packageParts [i] = Regex.Replace (packageParts [i], "[^A-Za-z0-9_]", "_"); - if (char.IsDigit (packageParts [i], 0) || packageParts [i][0] == '_') - packageParts [i] = "x" + packageParts [i]; - } - return packageParts.Length == 1 - ? packageParts [0] + "." + packageParts [0] - : string.Join (".", packageParts); - } - - public static AndroidAppManifest Create (string packageName, string appLabel) - { - return new AndroidAppManifest (XDocument.Parse ( - @"<?xml version=""1.0"" encoding=""utf-8""?> -<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0""> - <uses-sdk /> - <application android:label=""""> - </application> -</manifest>")) { - PackageName = packageName, - ApplicationLabel = appLabel, - }; - } - - public static AndroidAppManifest Load (string filename) - { - return Load (XDocument.Load (filename)); - } - - public static AndroidAppManifest Load (XDocument doc) - { - return new AndroidAppManifest (doc); - } - - public void Write (XmlWriter writer) - { - doc.Save (writer); - } - - public void WriteToFile (string fileName) - { - var xmlSettings = new XmlWriterSettings () { - Encoding = Encoding.UTF8, - CloseOutput = false, - Indent = true, - IndentChars = "\t", - NewLineChars = "\n", - }; - - var tempFile = FileUtil.GetTempFilenameForWrite (fileName); - bool success = false; - try { - using (var writer = XmlTextWriter.Create (tempFile, xmlSettings)) { - Write (writer); - } - FileUtil.SystemRename (tempFile, fileName); - success = true; - } finally { - if (!success) { - try { - File.Delete (tempFile); - } catch { - //the original exception is more important than this one - } - } - } - } - - static string NullIfEmpty (string value) - { - return string.IsNullOrEmpty (value) ? null : value; - } - - public string PackageName { - get { return (string) manifest.Attribute ("package"); } - set { manifest.SetAttributeValue ("package", NullIfEmpty (value)); } - } - - public string ApplicationLabel { - get { return (string) application.Attribute (aNS + "label"); } - set { application.SetAttributeValue (aNS + "label", NullIfEmpty (value)); } - } - - public string ApplicationIcon { - get { return (string) application.Attribute (aNS + "icon"); } - set { application.SetAttributeValue (aNS + "icon", NullIfEmpty (value)); } - } - - public string ApplicationTheme { - get { return (string) application.Attribute (aNS + "theme"); } - set { application.SetAttributeValue (aNS + "theme", NullIfEmpty (value)); } - } - - public string VersionName { - get { return (string) manifest.Attribute (aNS + "versionName"); } - set { manifest.SetAttributeValue (aNS + "versionName", NullIfEmpty (value)); } - } - - public string VersionCode { - get { return (string) manifest.Attribute (aNS + "versionCode"); } - set { manifest.SetAttributeValue (aNS + "versionCode", NullIfEmpty (value)); } - } - - public string InstallLocation { - get { return (string) manifest.Attribute (aNS + "installLocation"); } - set { manifest.SetAttributeValue (aNS + "installLocation", NullIfEmpty (value)); } - } - - public int? MinSdkVersion { - get { return ParseSdkVersion (usesSdk.Attribute (aNS + "minSdkVersion")); } - set { usesSdk.SetAttributeValue (aNS + "minSdkVersion", value == null ? null : value.ToString ()); } - } - - public int? TargetSdkVersion { - get { return ParseSdkVersion (usesSdk.Attribute (aNS + "targetSdkVersion")); } - set { usesSdk.SetAttributeValue (aNS + "targetSdkVersion", value == null ? null : value.ToString ()); } - } - - int? ParseSdkVersion (XAttribute attribute) - { - var version = (string)attribute; - if (string.IsNullOrEmpty (version)) - return null; - int vn; - if (!int.TryParse (version, out vn)) - vn = AndroidVersion.MaxApiLevel; - return vn; - } - - public IEnumerable<string> AndroidPermissions { - get { - foreach (var el in manifest.Elements ("uses-permission")) { - var name = (string) el.Attribute (aName); - if (name == null) - continue; - var lastDot = name.LastIndexOf ('.'); - if (lastDot >= 0) - yield return name.Substring (lastDot + 1); - } - } - } - - public IEnumerable<string> AndroidPermissionsQualified { - get { - foreach (var el in manifest.Elements ("uses-permission")) { - var name = (string) el.Attribute (aName); - if (name != null) - yield return name; - } - } - } - - public bool? Debuggable { - get { return (bool?) application.Attribute (aNS + "debuggable"); } - set { application.SetAttributeValue (aNS + "debuggable", value); } - } - - public void SetAndroidPermissions (IEnumerable<string> permissions) - { - var newPerms = new HashSet<string> (permissions.Select (FullyQualifyPermission)); - var current = new HashSet<string> (AndroidPermissionsQualified); - AddAndroidPermissions (newPerms.Except (current)); - RemoveAndroidPermissions (current.Except (newPerms)); - } - - void AddAndroidPermissions (IEnumerable<string> permissions) - { - var newElements = permissions.Select (p => new XElement ("uses-permission", new XAttribute (aName, p))); - - var lastPerm = manifest.Elements ("uses-permission").LastOrDefault (); - if (lastPerm != null) { - foreach (var el in newElements) { - lastPerm.AddAfterSelf (el); - lastPerm = el; - } - } else { - var parentNode = (XNode) manifest.Element ("application") ?? manifest.LastNode; - foreach (var el in newElements) - parentNode.AddBeforeSelf (el); - } - } - - string FullyQualifyPermission (string permission) - { - //if already qualified, don't mess with it - if (permission.IndexOf ('.') > -1) - return permission; - - switch (permission) { - case "READ_HISTORY_BOOKMARKS": - case "WRITE_HISTORY_BOOKMARKS": - return string.Format ("com.android.browser.permission.{0}", permission); - default: - return string.Format ("android.permission.{0}", permission); - } - } - - void RemoveAndroidPermissions (IEnumerable<string> permissions) - { - var perms = new HashSet<string> (permissions); - var list = manifest.Elements ("uses-permission") - .Where (el => perms.Contains ((string)el.Attribute (aName))).ToList (); - foreach (var el in list) - el.Remove (); - } - - [Obsolete ("Use GetLaunchableFastdevActivityName or GetLaunchableUserActivityName")] - public string GetLaunchableActivityName () - { - return GetLaunchableFastDevActivityName (); - } - - /// <summary>Gets an activity that can be used to initialize the override directory for fastdev.</summary> - [Obsolete ("This should not be needed anymore; Activity execution is not part of installation.")] - public string GetLaunchableFastDevActivityName () - { - string first = null; - foreach (var a in GetLaunchableActivities ()) { - var name = (string) a.Attribute (aName); - //prefer the fastdev launcher, it's quicker - if (name == "mono.android.__FastDevLauncher") { - return name; - } - //else just use the first other launchable activity - if (first == null) { - first = name; - } - } - - return string.IsNullOrEmpty (first)? null : first; - } - - // We add a fake launchable activity for FastDev, but we don't want - // to launch that one when the user does Run or Debug - public string GetLaunchableUserActivityName () - { - return GetLaunchableActivities () - .Select (a => (string) a.Attribute (aName)) - .FirstOrDefault (name => !string.IsNullOrEmpty (name) && name != "mono.android.__FastDevLauncher"); - } - - IEnumerable<XElement> GetLaunchableActivities () - { - foreach (var activity in application.Elements ("activity")) { - var filter = activity.Element ("intent-filter"); - if (filter != null) { - foreach (var category in filter.Elements ("category")) - if (category != null && (string)category.Attribute (aName) == "android.intent.category.LAUNCHER") - yield return activity; - } - } - } - - public IEnumerable<string> GetAllActivityNames () - { - foreach (var activity in application.Elements ("activity")) { - var activityName = (string) activity.Attribute (aName); - if (activityName != "mono.android.__FastDevLauncher") - yield return activityName; - } - } - - public IEnumerable<string> GetLaunchableActivityNames () - { - return GetLaunchableActivities () - .Select (a => (string) a.Attribute (aName)) - .Where (name => !string.IsNullOrEmpty (name) && name != "mono.android.__FastDevLauncher"); - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/AndroidLogger.cs b/src/Xamarin.Android.Build.Utilities/AndroidLogger.cs deleted file mode 100644 index d06a0109ac4..00000000000 --- a/src/Xamarin.Android.Build.Utilities/AndroidLogger.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; - -namespace Xamarin.Android.Build.Utilities -{ - public delegate void MessageHandler (string task, string message); - public delegate void TaskLogHandler (AndroidTaskLog log); - - public static class AndroidLogger - { - public static event MessageHandler Info; - public static event MessageHandler Warning; - public static event MessageHandler Error; - public static event MessageHandler Debug; - public static event TaskLogHandler Task; - - public static void LogInfo (string format, params object[] args) - { - LogInfo (string.Empty, format, args); - } - - public static void LogInfo (string task, string format, params object[] args) - { - if (Info != null) { - if (args == null || args.Length == 0) - Info (task, format); - else - Info (task, String.Format (format, args)); - } else - throw new InvalidOperationException ("Internal Error: should initialize Info"); - } - - public static void LogWarning (string format, params object[] args) - { - LogWarning (string.Empty, format, args); - } - - public static void LogWarning (string task, string format, params object[] args) - { - if (Warning != null) { - if (args == null) - Warning (task, format); - else - Warning (task, String.Format (format, args)); - } else - throw new InvalidOperationException ("Internal Error: should initialize Warning"); - } - - public static void LogError (string format, params object[] args) - { - LogError (string.Empty, format, args); - } - - public static void LogError (string message, Exception ex) - { - message += (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty); - LogError (message); - } - - public static void LogError (string task, string format, params object[] args) - { - if (Error != null) { - if (args == null || args.Length == 0) - Error (task, format); - else - Error (task, String.Format (format, args)); - } else - throw new InvalidOperationException ("Internal Error: should initialize Error"); - } - - public static void LogDebug (string format, params object[] args) - { - LogDebug (string.Empty, format, args); - } - - public static void LogDebug (string task, string format, params object[] args) - { - if (Debug != null) { - if (args == null || args.Length == 0) - Debug (task, format); - else - Debug (task, String.Format (format, args)); - } else - throw new InvalidOperationException ("Internal Error: should initialize Debug"); - } - - public static void LogTask (AndroidTaskLog log) - { - if (Task != null) - Task (log); - else - throw new InvalidOperationException ("Internal Error: should initialize Task"); - } - } - - public class AndroidTaskLog - { - public string Task { get; private set; } - public string Input { get; private set; } - public string Output { get; private set; } - public DateTime StartTime { get; private set; } - public DateTime EndTime { get; private set; } - - public AndroidTaskLog (string task, string input) - { - Task = task; - Input = input; - StartTime = DateTime.Now; - } - - public AndroidTaskLog Complete (string output) - { - Output = output; - EndTime = DateTime.Now; - - return this; - } - - public AndroidTaskLog Complete (object output) - { - if (output == null) - output = ""; - Output = output.ToString(); - EndTime = DateTime.Now; - - return this; - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/AndroidSdk.cs b/src/Xamarin.Android.Build.Utilities/AndroidSdk.cs deleted file mode 100644 index 11b81559af5..00000000000 --- a/src/Xamarin.Android.Build.Utilities/AndroidSdk.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.IO; - -namespace Xamarin.Android.Build.Utilities -{ - public class AndroidSdk - { - private static AndroidSdkBase sdk; - - public static void Refresh (string androidSdkPath = null, string androidNdkPath = null, string javaSdkPath = null) - { - if (OS.IsWindows) - sdk = new AndroidSdkWindows (); - else - sdk = new AndroidSdkUnix (); - - try { - sdk.Initialize (androidSdkPath ?? sdk.PreferedAndroidSdkPath, androidNdkPath ?? sdk.PreferedAndroidNdkPath, - javaSdkPath ?? sdk.PreferedJavaSdkPath); - if (IsInstalled) { - var levels = GetInstalledPlatformVersions ().Select (l => l.ApiLevel.ToString ()).ToArray (); - string levelList; - if (levels == null || levels.Length == 0) - levelList = "(none)"; - else - levelList = string.Join (", ", levels); - AndroidLogger.LogInfo (null, "Found Android SDK. API levels: {0}", levelList); - } else { - AndroidLogger.LogInfo (null, "Did not find Android SDK"); - } - } catch (Exception ex) { - AndroidLogger.LogError ("Error finding Android/Java SDKs", ex); - } - } - - public static IEnumerable<string> GetBuildToolsPaths (string preferredBuildToolsVersion) - { - if (!string.IsNullOrEmpty (preferredBuildToolsVersion)) { - var preferredDir = Path.Combine (AndroidSdkPath, "build-tools", preferredBuildToolsVersion); - if (Directory.Exists (preferredDir)) - return new[] { preferredDir }.Concat (GetBuildToolsPaths ().Where (p => p!= preferredDir)); - } - return GetBuildToolsPaths (); - } - - public static IEnumerable<string> GetBuildToolsPaths () - { - ValidatePath (AndroidSdkPath); - - var buildTools = Path.Combine (AndroidSdkPath, "build-tools"); - if (Directory.Exists (buildTools)) { - var preview = Directory.EnumerateDirectories (buildTools) - .Where(x => TryParseVersion (Path.GetFileName (x)) == null) - .Select(x => x); - - foreach (var d in preview) - yield return d; - - var sorted = from p in Directory.EnumerateDirectories (buildTools) - let version = TryParseVersion (Path.GetFileName (p)) - where version != null - orderby version descending - select p; - - foreach (var d in sorted) - yield return d; - } - var ptPath = Path.Combine (AndroidSdkPath, "platform-tools"); - if (Directory.Exists (ptPath)) - yield return ptPath; - } - - static Version TryParseVersion (string v) - { - Version version; - if (Version.TryParse (v, out version)) - return version; - return null; - } - - // it was useful when android-21 was android-L, or android-23 was android-MNC. - // We will use this when similar preview release is out. - static string ToApiName (int apiLevel) - { - return apiLevel.ToString (); - } - - static string ValidatePath (string path) - { - if (String.IsNullOrEmpty (path)) - throw new InvalidOperationException ("This property is not valid when the SDK is not installed"); - return path; - } - - public static string GetPlatformDirectory (int apiLevel) - { - return Path.Combine (AndroidSdkPath, "platforms", "android-" + ToApiName (apiLevel)); - } - - public static string GetPlatformDirectory (string osVersion) - { - var level = AndroidVersion.TryOSVersionToApiLevel (osVersion); - if (level == 0) - return null; - return GetPlatformDirectory (level); - } - - public static bool IsPlatformInstalled (int apiLevel) - { - return apiLevel != 0 && Directory.Exists (GetPlatformDirectory (apiLevel)); - } - - public static IEnumerable<AndroidVersion> GetInstalledPlatformVersions () - { - var knownAndInstalledSdkLevels = AndroidVersion.KnownVersions.Where (v => IsPlatformInstalled (v.ApiLevel)); - - return knownAndInstalledSdkLevels.Where (version => { - var apiLevel = MonoDroidSdk.GetApiLevelForFrameworkVersion (version.OSVersion); - return MonoDroidSdk.IsSupportedFrameworkLevel (apiLevel); - }); - } - - public static bool IsInstalled { - get { - return !string.IsNullOrEmpty (AndroidSdkPath) && !string.IsNullOrEmpty (JavaSdkPath); - } - } - - public static string AndroidNdkPath { - get { return sdk.AndroidNdkPath; } - } - - public static string AndroidSdkPath { - get { return sdk.AndroidSdkPath; } - } - - public static string JavaSdkPath { - get { return sdk.JavaSdkPath; } - } - - public static string AndroidNdkHostPlatform { - get { return sdk.NdkHostPlatform; } - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/AndroidTargetArch.cs b/src/Xamarin.Android.Build.Utilities/AndroidTargetArch.cs deleted file mode 100644 index 7aebeee6fd8..00000000000 --- a/src/Xamarin.Android.Build.Utilities/AndroidTargetArch.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using System.IO; - -namespace Xamarin.Android.Build.Utilities -{ - [Flags] - public enum AndroidTargetArch - { - None = 0, - Arm = 1, - X86 = 2, - Mips = 4, - Arm64 = 8, - X86_64 = 16, - Other = 0x10000 // hope it's not too optimistic - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/AndroidVersion.cs b/src/Xamarin.Android.Build.Utilities/AndroidVersion.cs deleted file mode 100644 index a9803722dbb..00000000000 --- a/src/Xamarin.Android.Build.Utilities/AndroidVersion.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; - -namespace Xamarin.Android.Build.Utilities -{ - public class AndroidVersion - { - public static readonly int MaxApiLevel = 24; - - public AndroidVersion (int apilevel, string osVersion) - { - this.ApiLevel = apilevel; - this.OSVersion = osVersion; - } - - AndroidVersion (int apilevel, string osVersion, string codeName, Version version) - { - this.ApiLevel = apilevel; - // TODO: remove osVersion from parameter list and generate from version - this.OSVersion = osVersion; - this.CodeName = codeName; - this.Version = version; - } - - public int ApiLevel { get; private set; } - public string OSVersion { get; private set; } - public string CodeName { get; private set; } - public Version Version { get; private set; } - - public static int OSVersionToApiLevel (string osVersion) - { - int ret = TryOSVersionToApiLevel (osVersion); - if (ret == 0) - throw new ArgumentOutOfRangeException ("OS version not recognized: " + osVersion); - return ret; - } - - public static int TryOSVersionToApiLevel (string frameworkVersion) - { - // Use MonoDroidSdk.GetApiLevelForFrameworkVersion because that will translate XA versions >= 5.xx to the correct api level - var apiLevelText = MonoDroidSdk.GetApiLevelForFrameworkVersion (frameworkVersion); - int apiLevel; - int.TryParse (apiLevelText, out apiLevel); - return apiLevel; - } - - public static string ApiLevelToOSVersion (int apiLevel) - { - string ret = TryApiLevelToOSVersion (apiLevel); - if (ret == null) - throw new ArgumentOutOfRangeException ("API level not recognized: " + apiLevel); - return ret; - } - - public static string TryApiLevelToOSVersion (int apiLevel) - { - var osVersion = MonoDroidSdk.GetFrameworkVersionForApiLevel (apiLevel.ToString ()); - if (!string.IsNullOrEmpty (osVersion)) - return osVersion.TrimStart ('v'); - return null; - } - - public static string TryOSVersionToCodeName (string frameworkVersion) - { - // match on API level, the framework version might not match what we have here (>= XA 5.x uses a different version scheme) - var apiLevel = TryOSVersionToApiLevel (frameworkVersion); - - foreach (AndroidVersion version in KnownVersions) - if (version.ApiLevel == apiLevel) - return version.CodeName; - return null; - } - - public static string TryFrameworkVersionToOSVersion (string frameworkVersion) - { - // match on API level, the framework version might not match what we have here (>= XA 5.x uses a different version scheme) - var apiLevel = TryOSVersionToApiLevel (frameworkVersion); - - foreach (AndroidVersion version in KnownVersions) - if (version.ApiLevel == apiLevel) - return version.OSVersion; - return null; - } - - public static AndroidVersion[] KnownVersions = new[] { - new AndroidVersion (4, "1.6", "Donut", new Version (1, 6)), - new AndroidVersion (5, "2.0", "Eclair", new Version (2, 0)), - new AndroidVersion (6, "2.0.1", "Eclair", new Version (2, 0, 1)), - new AndroidVersion (7, "2.1", "Eclair", new Version (2, 1)), - new AndroidVersion (8, "2.2", "Froyo", new Version (2, 2)), - new AndroidVersion (10, "2.3", "Gingerbread", new Version (2, 3)), - new AndroidVersion (11, "3.0", "Honeycomb", new Version (3, 0)), - new AndroidVersion (12, "3.1", "Honeycomb", new Version (3, 1)), - new AndroidVersion (13, "3.2", "Honeycomb", new Version (3, 2)), - new AndroidVersion (14, "4.0", "Ice Cream Sandwich", new Version (4, 0)), - new AndroidVersion (15, "4.0.3", "Ice Cream Sandwich", new Version (4, 0, 3)), - new AndroidVersion (16, "4.1", "Jelly Bean", new Version (4, 1)), - new AndroidVersion (17, "4.2", "Jelly Bean", new Version (4, 2)), - new AndroidVersion (18, "4.3", "Jelly Bean", new Version (4, 3)), - new AndroidVersion (19, "4.4", "Kit Kat", new Version (4, 4)), - new AndroidVersion (20, "4.4.87", "Kit Kat + Wear support", new Version (4, 4, 87)), - new AndroidVersion (21, "5.0", "Lollipop", new Version (5, 0)), - new AndroidVersion (22, "5.1", "Lollipop", new Version (5, 1)), - new AndroidVersion (23, "6.0", "Marshmallow", new Version (6, 0)), - new AndroidVersion (24, "7.0", "Nougat", new Version (7, 0)), - }; - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/FileUtil.cs b/src/Xamarin.Android.Build.Utilities/FileUtil.cs index 7c81d7e4ad0..c7de9112884 100644 --- a/src/Xamarin.Android.Build.Utilities/FileUtil.cs +++ b/src/Xamarin.Android.Build.Utilities/FileUtil.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Runtime.InteropServices; +using Xamarin.Android.Tools; namespace Xamarin.Android.Build.Utilities { diff --git a/src/Xamarin.Android.Build.Utilities/GdbPaths.cs b/src/Xamarin.Android.Build.Utilities/GdbPaths.cs index e4079fc4765..97c22748547 100644 --- a/src/Xamarin.Android.Build.Utilities/GdbPaths.cs +++ b/src/Xamarin.Android.Build.Utilities/GdbPaths.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Xamarin.Android.Tools; namespace Xamarin.Android.Build.Utilities { diff --git a/src/Xamarin.Android.Build.Utilities/MonoDroidSdk.cs b/src/Xamarin.Android.Build.Utilities/MonoDroidSdk.cs deleted file mode 100644 index 9781e40a755..00000000000 --- a/src/Xamarin.Android.Build.Utilities/MonoDroidSdk.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.IO; - -namespace Xamarin.Android.Build.Utilities -{ - public static class MonoDroidSdk - { - static MonoDroidSdkBase sdk; - - public static string GetApiLevelForFrameworkVersion (string framework) - { - return GetSdk ().GetApiLevelForFrameworkVersion (framework); - } - - public static string GetFrameworkVersionForApiLevel (string apiLevel) - { - return GetSdk ().GetFrameworkVersionForApiLevel (apiLevel); - } - - public static bool IsSupportedFrameworkLevel (string apiLevel) - { - return GetSdk ().IsSupportedFrameworkLevel (apiLevel); - } - - public static void Refresh (string runtimePath = null, string binPath = null, string bclPath = null) - { - if (OS.IsWindows) { - sdk = new MonoDroidSdkWindows (); - } else { - sdk = new MonoDroidSdkUnix (); - } - - try { - sdk.Initialize (runtimePath, binPath, bclPath); - } catch (Exception ex) { - AndroidLogger.LogError ("Error finding Xamarin.Android SDK", ex); - } - } - - static MonoDroidSdkBase GetSdk () - { - if (sdk == null) { - Refresh (); - } - return sdk; - } - - public static string RuntimePath { get { return GetSdk ().RuntimePath; } } - - public static string BinPath { get { return GetSdk ().BinPath; } } - - public static string FrameworkPath { get { return GetSdk ().BclPath; } } - - [Obsolete ("Do not use.")] - public static string JavaDocToMDocExe { - get { return Path.Combine (BinPath, OS.IsWindows ? "javadoc-to-mdoc.exe" : "javadoc-to-mdoc"); } - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/OS.cs b/src/Xamarin.Android.Build.Utilities/OS.cs deleted file mode 100644 index 0ff07cd2185..00000000000 --- a/src/Xamarin.Android.Build.Utilities/OS.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.IO; -using System.Text; - -namespace Xamarin.Android.Build.Utilities -{ - public class OS - { - public readonly static bool IsWindows; - public readonly static bool IsMac; - - internal readonly static string ProgramFilesX86; - - static OS () - { - IsWindows = Path.DirectorySeparatorChar == '\\'; - IsMac = !IsWindows && IsRunningOnMac (); - - if (IsWindows) { - ProgramFilesX86 = GetProgramFilesX86 (); - } - } - - //From Managed.Windows.Forms/XplatUI - static bool IsRunningOnMac () - { - IntPtr buf = IntPtr.Zero; - try { - buf = Marshal.AllocHGlobal (8192); - // This is a hacktastic way of getting sysname from uname () - if (uname (buf) == 0) { - string os = System.Runtime.InteropServices.Marshal.PtrToStringAnsi (buf); - if (os == "Darwin") - return true; - } - } catch { - } finally { - if (buf != IntPtr.Zero) - System.Runtime.InteropServices.Marshal.FreeHGlobal (buf); - } - return false; - } - - [DllImport ("libc")] - static extern int uname (IntPtr buf); - - static string GetProgramFilesX86 () - { - //SpecialFolder.ProgramFilesX86 is broken on 32-bit WinXP - if (IntPtr.Size == 8) { - return Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86); - } else { - return Environment.GetFolderPath (Environment.SpecialFolder.ProgramFiles); - } - } - - internal static string GetXamarinAndroidCacheDir () - { - if (IsMac) { - var home = Environment.GetFolderPath (Environment.SpecialFolder.Personal); - return Path.Combine (home, "Library", "Caches", "Xamarin.Android"); - } else if (IsWindows) { - var localAppData = Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData); - return Path.Combine (localAppData, "Xamarin.Android", "Cache"); - } else { - var home = Environment.GetFolderPath (Environment.SpecialFolder.Personal); - var xdgCacheHome = Environment.GetEnvironmentVariable ("XDG_CACHE_HOME"); - if (string.IsNullOrEmpty (xdgCacheHome)) { - xdgCacheHome = Path.Combine (home, ".cache"); - } - return Path.Combine (xdgCacheHome, "Xamarin.Android"); - } - } - } - - public static class KernelEx { - [DllImport ("kernel32.dll", CharSet = CharSet.Auto)] - static extern int GetLongPathName ( - [MarshalAs (UnmanagedType.LPTStr)] string path, - [MarshalAs (UnmanagedType.LPTStr)] StringBuilder longPath, - int longPathLength - ); - - public static string GetLongPathName (string path) - { - StringBuilder sb = new StringBuilder (255); - GetLongPathName (path, sb, sb.Capacity); - return sb.ToString (); - } - - [DllImport ("kernel32.dll", CharSet = CharSet.Auto)] - static extern int GetShortPathName ( - [MarshalAs (UnmanagedType.LPTStr)] string path, - [MarshalAs (UnmanagedType.LPTStr)] StringBuilder shortPath, - int shortPathLength - ); - - public static string GetShortPathName (string path) - { - StringBuilder sb = new StringBuilder (255); - GetShortPathName (path, sb, sb.Capacity); - return sb.ToString (); - } - } - - internal static class RegistryEx - { - const string ADVAPI = "advapi32.dll"; - - public static UIntPtr CurrentUser = (UIntPtr)0x80000001; - public static UIntPtr LocalMachine = (UIntPtr)0x80000002; - - [DllImport (ADVAPI, CharSet = CharSet.Unicode, SetLastError = true)] - static extern int RegOpenKeyEx (UIntPtr hKey, string subKey, uint reserved, uint sam, out UIntPtr phkResult); - - [DllImport (ADVAPI, CharSet = CharSet.Unicode, SetLastError = true)] - static extern int RegQueryValueExW (UIntPtr hKey, string lpValueName, int lpReserved, out uint lpType, - StringBuilder lpData, ref uint lpcbData); - - [DllImport (ADVAPI, CharSet = CharSet.Unicode, SetLastError = true)] - static extern int RegSetValueExW (UIntPtr hKey, string lpValueName, int lpReserved, - uint dwType, string data, uint cbData); - - [DllImport (ADVAPI, CharSet = CharSet.Unicode, SetLastError = true)] - static extern int RegSetValueExW (UIntPtr hKey, string lpValueName, int lpReserved, - uint dwType, IntPtr data, uint cbData); - - [DllImport (ADVAPI, CharSet = CharSet.Unicode, SetLastError = true)] - static extern int RegCreateKeyEx (UIntPtr hKey, string subKey, uint reserved, string @class, uint options, - uint samDesired, IntPtr lpSecurityAttributes, out UIntPtr phkResult, out Disposition lpdwDisposition); - - [DllImport ("advapi32.dll", SetLastError = true)] - static extern int RegCloseKey (UIntPtr hKey); - - public static string GetValueString (UIntPtr key, string subkey, string valueName, Wow64 wow64) - { - UIntPtr regKeyHandle; - uint sam = (uint)Rights.QueryValue + (uint)wow64; - if (RegOpenKeyEx (key, subkey, 0, sam, out regKeyHandle) != 0) - return null; - - try { - uint type; - var sb = new StringBuilder (2048); - uint cbData = (uint) sb.Capacity; - if (RegQueryValueExW (regKeyHandle, valueName, 0, out type, sb, ref cbData) == 0) { - return sb.ToString (); - } - return null; - } finally { - RegCloseKey (regKeyHandle); - } - } - - public static void SetValueString (UIntPtr key, string subkey, string valueName, string value, Wow64 wow64) - { - UIntPtr regKeyHandle; - uint sam = (uint)(Rights.CreateSubKey | Rights.SetValue) + (uint)wow64; - uint options = (uint) Options.NonVolatile; - Disposition disposition; - if (RegCreateKeyEx (key, subkey, 0, null, options, sam, IntPtr.Zero, out regKeyHandle, out disposition) != 0) { - throw new Exception ("Could not open or craete key"); - } - - try { - uint type = (uint)ValueType.String; - uint lenBytesPlusNull = ((uint)value.Length + 1) * 2; - var result = RegSetValueExW (regKeyHandle, valueName, 0, type, value, lenBytesPlusNull); - if (result != 0) - throw new Exception (string.Format ("Error {0} setting registry key '{1}{2}@{3}'='{4}'", - result, key, subkey, valueName, value)); - } finally { - RegCloseKey (regKeyHandle); - } - } - - [Flags] - enum Rights : uint - { - None = 0, - QueryValue = 0x0001, - SetValue = 0x0002, - CreateSubKey = 0x0004, - EnumerateSubKey = 0x0008, - } - - enum Options - { - BackupRestore = 0x00000004, - CreateLink = 0x00000002, - NonVolatile = 0x00000000, - Volatile = 0x00000001, - } - - public enum Wow64 : uint - { - Key64 = 0x0100, - Key32 = 0x0200, - } - - enum ValueType : uint - { - None = 0, //REG_NONE - String = 1, //REG_SZ - UnexpandedString = 2, //REG_EXPAND_SZ - Binary = 3, //REG_BINARY - DWord = 4, //REG_DWORD - DWordLittleEndian = 4, //REG_DWORD_LITTLE_ENDIAN - DWordBigEndian = 5, //REG_DWORD_BIG_ENDIAN - Link = 6, //REG_LINK - MultiString = 7, //REG_MULTI_SZ - ResourceList = 8, //REG_RESOURCE_LIST - FullResourceDescriptor = 9, //REG_FULL_RESOURCE_DESCRIPTOR - ResourceRequirementsList = 10, //REG_RESOURCE_REQUIREMENTS_LIST - QWord = 11, //REG_QWORD - QWordLittleEndian = 11, //REG_QWORD_LITTLE_ENDIAN - } - - enum Disposition : uint - { - CreatedNewKey = 0x00000001, - OpenedExistingKey = 0x00000002, - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/ProcessUtils.cs b/src/Xamarin.Android.Build.Utilities/ProcessUtils.cs deleted file mode 100644 index cded992fb84..00000000000 --- a/src/Xamarin.Android.Build.Utilities/ProcessUtils.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using System.IO; -using System.Threading; - -namespace Xamarin.Android.Build.Utilities -{ - public static class ProcessUtils - { - public static async Task<int> StartProcess (ProcessStartInfo psi, TextWriter stdout, TextWriter stderr, CancellationToken cancellationToken, Action<Process> onStarted = null) - { - cancellationToken.ThrowIfCancellationRequested (); - psi.UseShellExecute = false; - psi.RedirectStandardOutput |= stdout != null; - psi.RedirectStandardError |= stderr != null; - - var process = new Process { - StartInfo = psi, - EnableRaisingEvents = true, - }; - - Task output = Task.FromResult (true); - Task error = Task.FromResult (true); - Task exit = WaitForExitAsync (process); - using (process) { - process.Start (); - if (onStarted != null) - onStarted (process); - - // If the token is cancelled while we're running, kill the process. - // Otherwise once we finish the Task.WhenAll we can remove this registration - // as there is no longer any need to Kill the process. - // - // We wrap `stdout` and `stderr` in syncronized wrappers for safety in case they - // end up writing to the same buffer, or they are the same object. - using (cancellationToken.Register (() => KillProcess (process))) { - if (psi.RedirectStandardOutput) - output = ReadStreamAsync (process.StandardOutput, TextWriter.Synchronized (stdout)); - - if (psi.RedirectStandardError) - error = ReadStreamAsync (process.StandardError, TextWriter.Synchronized (stderr)); - - await Task.WhenAll (new [] { output, error, exit }).ConfigureAwait (false); - } - // If we invoke 'KillProcess' our output, error and exit tasks will all complete normally. - // To protected against passing the user incomplete data we have to call - // `cancellationToken.ThrowIfCancellationRequested ()` here. - cancellationToken.ThrowIfCancellationRequested (); - return process.ExitCode; - } - } - - static void KillProcess (Process p) - { - try { - p.Kill (); - } catch (InvalidOperationException) { - // If the process has already exited this could happen - } - } - - static Task WaitForExitAsync (Process process) - { - var exitDone = new TaskCompletionSource<bool> (); - process.Exited += (o, e) => exitDone.TrySetResult (true); - return exitDone.Task; - } - - static async Task ReadStreamAsync (StreamReader stream, TextWriter destination) - { - int read; - var buffer = new char [4096]; - while ((read = await stream.ReadAsync (buffer, 0, buffer.Length).ConfigureAwait (false)) > 0) - destination.Write (buffer, 0, read); - } - - /// <summary> - /// Executes an Android Sdk tool and returns a result. The result is based on a function of the command output. - /// </summary> - public static Task<TResult> ExecuteToolAsync<TResult> (string exe, Func<string, TResult> result, CancellationToken token, Action<Process> onStarted = null) - { - var tcs = new TaskCompletionSource<TResult> (); - - var log = new StringWriter (); - var error = new StringWriter (); - - var psi = new ProcessStartInfo (exe); - psi.CreateNoWindow = true; - psi.RedirectStandardInput = onStarted != null; - - var processTask = ProcessUtils.StartProcess (psi, log, error, token, onStarted); - var exeName = Path.GetFileName (exe); - - processTask.ContinueWith (t => { - var output = log.ToString (); - var errorOutput = error.ToString (); - log.Dispose (); - error.Dispose (); - - if (t.IsCanceled) { - tcs.TrySetCanceled (); - return; - } - - if (t.IsFaulted) { - tcs.TrySetException (t.Exception.Flatten ().InnerException); - return; - } - - if (t.Result == 0) { - tcs.TrySetResult (result != null ? result (output) : default (TResult)); - } else { - var errorMessage = !string.IsNullOrEmpty (errorOutput) ? errorOutput : output; - - tcs.TrySetException (new InvalidOperationException (string.IsNullOrEmpty (errorMessage) ? exeName + " returned non-zero exit code" : string.Format ("{0} : {1}", t.Result, errorMessage))); - } - }, TaskContinuationOptions.ExecuteSynchronously); - - return tcs.Task; - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkBase.cs b/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkBase.cs deleted file mode 100644 index 60eb067eabe..00000000000 --- a/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkBase.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; -using System.Linq; -using System.IO; -using System.Collections.Generic; - -namespace Xamarin.Android.Build.Utilities -{ - abstract class AndroidSdkBase - { - string[] allAndroidSdks = null; - string[] allAndroidNdks = null; - - public string[] AllAndroidSdks { - get { - if (allAndroidSdks == null) - allAndroidSdks = GetAllAvailableAndroidSdks ().Distinct ().ToArray (); - return allAndroidSdks; - } - } - public string[] AllAndroidNdks { - get { - if (allAndroidNdks == null) - allAndroidNdks = GetAllAvailableAndroidNdks ().Distinct ().ToArray (); - return allAndroidNdks; - } - } - - public string AndroidSdkPath { get; private set; } - public string AndroidNdkPath { get; private set; } - public string JavaSdkPath { get; private set; } - public string JavaBinPath { get; private set; } - public string AndroidToolsPath { get; private set; } - public string AndroidPlatformToolsPath { get; private set; } - public string AndroidToolsPathShort { get; private set; } - public string AndroidPlatformToolsPathShort { get; private set; } - - public virtual string Adb { get; protected set; } = "adb"; - public virtual string Android { get; protected set; } = "android"; - public virtual string Emulator { get; protected set; } = "emulator"; - public virtual string Monitor { get; protected set; } = "monitor"; - public virtual string ZipAlign { get; protected set; } = "zipalign"; - public virtual string JarSigner { get; protected set; } = "jarsigner"; - public virtual string KeyTool { get; protected set; } = "keytool"; - - public virtual string NdkStack { get; protected set; } = "ndk-stack"; - public abstract string NdkHostPlatform32Bit { get; } - public abstract string NdkHostPlatform64Bit { get; } - public virtual string Javac { get; protected set; } = "javac"; - - public abstract string PreferedAndroidSdkPath { get; } - public abstract string PreferedAndroidNdkPath { get; } - public abstract string PreferedJavaSdkPath { get; } - - public virtual void Initialize (string androidSdkPath = null, string androidNdkPath = null, string javaSdkPath = null) - { - AndroidSdkPath = ValidateAndroidSdkLocation (androidSdkPath) ? androidSdkPath : AllAndroidSdks.FirstOrDefault (); - AndroidNdkPath = ValidateAndroidNdkLocation (androidNdkPath) ? androidNdkPath : AllAndroidNdks.FirstOrDefault (); - JavaSdkPath = ValidateJavaSdkLocation (javaSdkPath) ? javaSdkPath : GetJavaSdkPath (); - - if (!string.IsNullOrEmpty (JavaSdkPath)) { - JavaBinPath = Path.Combine (JavaSdkPath, "bin"); - } else { - JavaBinPath = null; - } - - if (!string.IsNullOrEmpty (AndroidSdkPath)) { - AndroidToolsPath = Path.Combine (AndroidSdkPath, "tools"); - AndroidToolsPathShort = GetShortFormPath (AndroidToolsPath); - AndroidPlatformToolsPath = Path.Combine (AndroidSdkPath, "platform-tools"); - AndroidPlatformToolsPathShort = GetShortFormPath (AndroidPlatformToolsPath); - } else { - AndroidToolsPath = null; - AndroidToolsPathShort = null; - AndroidPlatformToolsPath = null; - AndroidPlatformToolsPathShort = null; - } - - if (!string.IsNullOrEmpty (AndroidNdkPath)) { - // It would be nice if .NET had real globbing support in System.IO... - string toolchainsDir = Path.Combine (AndroidNdkPath, "toolchains"); - IsNdk64Bit = Directory.EnumerateDirectories (toolchainsDir, "arm-linux-androideabi-*") - .Any (dir => Directory.Exists (Path.Combine (dir, "prebuilt", NdkHostPlatform64Bit))); - } - // we need to look for extensions other than the default .exe|.bat - // google have a habbit of changing them. - Adb = GetExecutablePath (AndroidPlatformToolsPath, Adb); - Android = GetExecutablePath (AndroidToolsPath, Android); - Emulator = GetExecutablePath (AndroidToolsPath, Emulator); - Monitor = GetExecutablePath (AndroidToolsPath, Monitor); - NdkStack = GetExecutablePath (AndroidNdkPath, NdkStack); - } - - protected abstract IEnumerable<string> GetAllAvailableAndroidSdks (); - protected abstract IEnumerable<string> GetAllAvailableAndroidNdks (); - protected abstract string GetJavaSdkPath (); - protected abstract string GetShortFormPath (string path); - - public abstract void SetPreferredAndroidSdkPath (string path); - public abstract void SetPreferredJavaSdkPath (string path); - public abstract void SetPreferredAndroidNdkPath (string path); - - public bool IsNdk64Bit { get; private set; } - - public string NdkHostPlatform { - get { return IsNdk64Bit ? NdkHostPlatform64Bit : NdkHostPlatform32Bit; } - } - - /// <summary> - /// Checks that a value is the location of an Android SDK. - /// </summary> - public bool ValidateAndroidSdkLocation (string loc) - { - return !string.IsNullOrEmpty (loc) && FindExecutableInDirectory (Adb, Path.Combine (loc, "platform-tools")).Any (); - } - - /// <summary> - /// Checks that a value is the location of a Java SDK. - /// </summary> - public virtual bool ValidateJavaSdkLocation (string loc) - { - return !string.IsNullOrEmpty (loc) && FindExecutableInDirectory (JarSigner, Path.Combine (loc, "bin")).Any (); - } - - /// <summary> - /// Checks that a value is the location of an Android SDK. - /// </summary> - public bool ValidateAndroidNdkLocation (string loc) - { - return !string.IsNullOrEmpty (loc) && FindExecutableInDirectory(NdkStack, loc).Any(); - } - - protected IEnumerable<string> FindExecutableInPath (string executable) - { - var path = Environment.GetEnvironmentVariable ("PATH"); - var pathDirs = path.Split (new char[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var dir in pathDirs) { - foreach (var directory in FindExecutableInDirectory(executable, dir)) { - yield return directory; - } - } - } - - protected IEnumerable<string> FindExecutableInDirectory(string executable, string dir) - { - foreach (var exe in Executables (executable)) - if (File.Exists (Path.Combine (dir, exe))) - yield return dir; - } - - IEnumerable<string> Executables (string executable) - { - yield return executable; - var pathExt = Environment.GetEnvironmentVariable ("PATHEXT"); - var pathExts = pathExt?.Split (new char [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries); - - if (pathExts == null) - yield break; - - foreach (var ext in pathExts) - yield return Path.ChangeExtension (executable, ext); - } - - protected string NullIfEmpty (string s) - { - if (s == null || s.Length != 0) - return s; - - return null; - } - - string GetExecutablePath (string dir, string exe) - { - if (string.IsNullOrEmpty (dir)) - return exe; - foreach (var e in Executables (exe)) - if (File.Exists (Path.Combine (dir, e))) - return e; - return exe; - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkUnix.cs b/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkUnix.cs deleted file mode 100644 index 0545c90cdc0..00000000000 --- a/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkUnix.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System; -using System.Xml; -using System.Xml.Linq; -using System.Collections.Generic; -using System.IO; - -namespace Xamarin.Android.Build.Utilities -{ - class AndroidSdkUnix : AndroidSdkBase - { - public override string NdkHostPlatform32Bit { - get { return OS.IsMac ? "darwin-x86" : "linux-x86"; } - } - public override string NdkHostPlatform64Bit { - get { return OS.IsMac ? "darwin-x86_64" : "linux-x86_64"; } - } - - public override string PreferedAndroidSdkPath { - get { - var config_file = GetUnixConfigFile (); - var androidEl = config_file.Root.Element ("android-sdk"); - - if (androidEl != null) { - var path = (string)androidEl.Attribute ("path"); - - if (ValidateAndroidSdkLocation (path)) - return path; - } - return null; - } - } - - public override string PreferedAndroidNdkPath { - get { - var config_file = GetUnixConfigFile (); - var androidEl = config_file.Root.Element ("android-ndk"); - - if (androidEl != null) { - var path = (string)androidEl.Attribute ("path"); - - if (ValidateAndroidNdkLocation (path)) - return path; - } - return null; - } - } - - public override string PreferedJavaSdkPath { - get { - var config_file = GetUnixConfigFile (); - var javaEl = config_file.Root.Element ("java-sdk"); - - if (javaEl != null) { - var path = (string)javaEl.Attribute ("path"); - - if (ValidateJavaSdkLocation (path)) - return path; - } - return null; - } - } - - protected override IEnumerable<string> GetAllAvailableAndroidSdks () - { - var preferedSdkPath = PreferedAndroidSdkPath; - if (!string.IsNullOrEmpty (preferedSdkPath)) - yield return preferedSdkPath; - - // Look in PATH - foreach (var path in FindExecutableInPath (Adb)) { - // Strip off "platform-tools" - var dir = Path.GetDirectoryName (path); - - if (ValidateAndroidSdkLocation (dir)) - yield return dir; - } - } - - protected override string GetJavaSdkPath () - { - var preferedJavaSdkPath = PreferedJavaSdkPath; - if (!string.IsNullOrEmpty (preferedJavaSdkPath)) - return preferedJavaSdkPath; - - // Look in PATH - foreach (var path in FindExecutableInPath (JarSigner)) { - // Strip off "bin" - var dir = Path.GetDirectoryName (path); - - if (ValidateJavaSdkLocation (dir)) - return dir; - } - - return null; - } - - public override bool ValidateJavaSdkLocation (string loc) - { - var result = base.ValidateJavaSdkLocation (loc); - - if (result) { - // handle apple's java stub - const string javaHomeExe = "/usr/libexec/java_home"; - - if (File.Exists (javaHomeExe)) { - // returns true if there is a java installed - var javaHomeTask = ProcessUtils.ExecuteToolAsync<bool> (javaHomeExe, - (output) => { - if (output.Contains ("(null)")) { - return false; - } - - return true; - }, System.Threading.CancellationToken.None - ); - - if (!javaHomeTask.Result) { - return false; - } - } - } - - return result; - } - - protected override IEnumerable<string> GetAllAvailableAndroidNdks () - { - var preferedNdkPath = PreferedAndroidNdkPath; - if (!string.IsNullOrEmpty (preferedNdkPath)) - yield return preferedNdkPath; - - // Look in PATH - foreach (var path in FindExecutableInPath (NdkStack)) { - if (ValidateAndroidNdkLocation (path)) - yield return path; - } - } - - protected override string GetShortFormPath (string path) - { - // This is a Windows-ism, don't do anything for Unix - return path; - } - - public override void SetPreferredAndroidSdkPath (string path) - { - path = NullIfEmpty (path); - - var doc = GetUnixConfigFile (); - var androidEl = doc.Root.Element ("android-sdk"); - - if (androidEl == null) { - androidEl = new XElement ("android-sdk"); - doc.Root.Add (androidEl); - } - - androidEl.SetAttributeValue ("path", path); - doc.Save (UnixConfigPath); - } - - public override void SetPreferredJavaSdkPath (string path) - { - path = NullIfEmpty (path); - - var doc = GetUnixConfigFile (); - var javaEl = doc.Root.Element ("java-sdk"); - - if (javaEl == null) { - javaEl = new XElement ("java-sdk"); - doc.Root.Add (javaEl); - } - - javaEl.SetAttributeValue ("path", path); - doc.Save (UnixConfigPath); - } - - public override void SetPreferredAndroidNdkPath (string path) - { - path = NullIfEmpty (path); - - var doc = GetUnixConfigFile (); - var androidEl = doc.Root.Element ("android-ndk"); - - if (androidEl == null) { - androidEl = new XElement ("android-ndk"); - doc.Root.Add (androidEl); - } - - androidEl.SetAttributeValue ("path", path); - doc.Save (UnixConfigPath); - } - - private static string UnixConfigPath { - get { - var p = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData); - return Path.Combine (Path.Combine (p, "xbuild"), "monodroid-config.xml"); - } - } - - private static XDocument GetUnixConfigFile () - { - var file = UnixConfigPath; - XDocument doc = null; - if (!File.Exists (file)) { - string dir = Path.GetDirectoryName (file); - if (!Directory.Exists (dir)) - Directory.CreateDirectory (dir); - } else { - try { - doc = XDocument.Load (file); - } catch (Exception ex) { - AndroidLogger.LogError ("Could not load monodroid configuration file", ex); - - // move out of the way and create a new one - doc = new XDocument (new XElement ("monodroid")); - var newFileName = file + ".old"; - if (File.Exists (newFileName)) { - File.Delete (newFileName); - } - - File.Move (file, newFileName); - } - } - - if (doc == null || doc.Root == null) { - doc = new XDocument (new XElement ("monodroid")); - } - return doc; - } - - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkWindows.cs b/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkWindows.cs deleted file mode 100644 index 21ebd3e94a0..00000000000 --- a/src/Xamarin.Android.Build.Utilities/Sdks/AndroidSdkWindows.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Xamarin.Android.Build.Utilities -{ - class AndroidSdkWindows : AndroidSdkBase - { - const string MDREG_KEY = @"SOFTWARE\Novell\Mono for Android"; - const string MDREG_ANDROID_SDK = "AndroidSdkDirectory"; - const string MDREG_ANDROID_NDK = "AndroidNdkDirectory"; - const string MDREG_JAVA_SDK = "JavaSdkDirectory"; - const string ANDROID_INSTALLER_PATH = @"SOFTWARE\Android SDK Tools"; - const string ANDROID_INSTALLER_KEY = "Path"; - const string XAMARIN_ANDROID_INSTALLER_PATH = @"SOFTWARE\Xamarin\MonoAndroid"; - const string XAMARIN_ANDROID_INSTALLER_KEY = "PrivateAndroidSdkPath"; - - public override string ZipAlign { get; protected set; } = "zipalign.exe"; - public override string JarSigner { get; protected set; } = "jarsigner.exe"; - public override string KeyTool { get; protected set; } = "keytool.exe"; - - public override string NdkHostPlatform32Bit { get { return "windows"; } } - public override string NdkHostPlatform64Bit { get { return "windows-x86_64"; } } - public override string Javac { get; protected set; } = "javac.exe"; - - public override string PreferedAndroidSdkPath { - get { - var wow = RegistryEx.Wow64.Key32; - if (CheckRegistryKeyForExecutable (RegistryEx.CurrentUser, MDREG_KEY, MDREG_ANDROID_SDK, wow, "platform-tools", Adb)) - return RegistryEx.GetValueString (RegistryEx.CurrentUser, MDREG_KEY, MDREG_ANDROID_SDK, wow); - return null; - } - } - public override string PreferedAndroidNdkPath { - get { - var wow = RegistryEx.Wow64.Key32; - if (CheckRegistryKeyForExecutable (RegistryEx.CurrentUser, MDREG_KEY, MDREG_ANDROID_NDK, wow, ".", NdkStack)) - return RegistryEx.GetValueString (RegistryEx.CurrentUser, MDREG_KEY, MDREG_ANDROID_NDK, wow); - return null; - } - } - public override string PreferedJavaSdkPath { - get { - var wow = RegistryEx.Wow64.Key32; - if (CheckRegistryKeyForExecutable (RegistryEx.CurrentUser, MDREG_KEY, MDREG_JAVA_SDK, wow, "bin", JarSigner)) - return RegistryEx.GetValueString (RegistryEx.CurrentUser, MDREG_KEY, MDREG_JAVA_SDK, wow); - return null; - } - } - - protected override IEnumerable<string> GetAllAvailableAndroidSdks () - { - var roots = new[] { RegistryEx.CurrentUser, RegistryEx.LocalMachine }; - var wow = RegistryEx.Wow64.Key32; - - AndroidLogger.LogInfo ("sdk", "Looking for Android SDK.."); - - // Check for the key the user gave us in the VS/addin options - foreach (var root in roots) - if (CheckRegistryKeyForExecutable (root, MDREG_KEY, MDREG_ANDROID_SDK, wow, "platform-tools", Adb)) - yield return RegistryEx.GetValueString (root, MDREG_KEY, MDREG_ANDROID_SDK, wow); - - // Check for the key written by the Xamarin installer - if (CheckRegistryKeyForExecutable (RegistryEx.CurrentUser, XAMARIN_ANDROID_INSTALLER_PATH, XAMARIN_ANDROID_INSTALLER_KEY, wow, "platform-tools", Adb)) - yield return RegistryEx.GetValueString (RegistryEx.CurrentUser, XAMARIN_ANDROID_INSTALLER_PATH, XAMARIN_ANDROID_INSTALLER_KEY, wow); - - // Check for the key written by the Android SDK installer - foreach (var root in roots) - if (CheckRegistryKeyForExecutable (root, ANDROID_INSTALLER_PATH, ANDROID_INSTALLER_KEY, wow, "platform-tools", Adb)) - yield return RegistryEx.GetValueString (root, ANDROID_INSTALLER_PATH, ANDROID_INSTALLER_KEY, wow); - - // Check some hardcoded paths for good measure - var xamarin_private = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), "Xamarin", "MonoAndroid", "android-sdk-windows"); - var android_default = Path.Combine (OS.ProgramFilesX86, "Android", "android-sdk-windows"); - var cdrive_default = @"C:\android-sdk-windows"; - - if (ValidateAndroidSdkLocation (xamarin_private)) - yield return xamarin_private; - - if (ValidateAndroidSdkLocation (android_default)) - yield return android_default; - - if (ValidateAndroidSdkLocation (cdrive_default)) - yield return cdrive_default; - } - - protected override string GetJavaSdkPath () - { - // check the user specified path - var roots = new[] { RegistryEx.CurrentUser, RegistryEx.LocalMachine }; - const RegistryEx.Wow64 wow = RegistryEx.Wow64.Key32; - - foreach (var root in roots) { - if (CheckRegistryKeyForExecutable (root, MDREG_KEY, MDREG_JAVA_SDK, wow, "bin", JarSigner)) - return RegistryEx.GetValueString (root, MDREG_KEY, MDREG_JAVA_SDK, wow); - } - - string subkey = @"SOFTWARE\JavaSoft\Java Development Kit"; - - AndroidLogger.LogInfo ("sdk", "Looking for Java 6 SDK.."); - - foreach (var wow64 in new[] { RegistryEx.Wow64.Key32, RegistryEx.Wow64.Key64 }) { - string key_name = string.Format (@"{0}\{1}\{2}", "HKLM", subkey, "CurrentVersion"); - var currentVersion = RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey, "CurrentVersion", wow64); - - if (!string.IsNullOrEmpty (currentVersion)) { - AndroidLogger.LogInfo ("sdk", " Key {0} found.", key_name); - - // No matter what the CurrentVersion is, look for 1.6 or 1.7 or 1.8 - if (CheckRegistryKeyForExecutable (RegistryEx.LocalMachine, subkey + "\\" + "1.6", "JavaHome", wow64, "bin", JarSigner)) - return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.6", "JavaHome", wow64); - - if (CheckRegistryKeyForExecutable (RegistryEx.LocalMachine, subkey + "\\" + "1.7", "JavaHome", wow64, "bin", JarSigner)) - return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.7", "JavaHome", wow64); - - if (CheckRegistryKeyForExecutable (RegistryEx.LocalMachine, subkey + "\\" + "1.8", "JavaHome", wow64, "bin", JarSigner)) - return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.8", "JavaHome", wow64); - } - - AndroidLogger.LogInfo ("sdk", " Key {0} not found.", key_name); - } - - // We ran out of things to check.. - return null; - } - - protected override IEnumerable<string> GetAllAvailableAndroidNdks () - { - var roots = new[] { RegistryEx.CurrentUser, RegistryEx.LocalMachine }; - var wow = RegistryEx.Wow64.Key32; - - AndroidLogger.LogInfo ("sdk", "Looking for Android NDK.."); - - // Check for the key the user gave us in the VS/addin options - foreach (var root in roots) - if (CheckRegistryKeyForExecutable (root, MDREG_KEY, MDREG_ANDROID_NDK, wow, ".", NdkStack)) - yield return RegistryEx.GetValueString (root, MDREG_KEY, MDREG_ANDROID_NDK, wow); - - /* - // Check for the key written by the Xamarin installer - if (CheckRegistryKeyForExecutable (RegistryEx.CurrentUser, XAMARIN_ANDROID_INSTALLER_PATH, XAMARIN_ANDROID_INSTALLER_KEY, wow, "platform-tools", Adb)) - yield return RegistryEx.GetValueString (RegistryEx.CurrentUser, XAMARIN_ANDROID_INSTALLER_PATH, XAMARIN_ANDROID_INSTALLER_KEY, wow); - */ - - // Check some hardcoded paths for good measure - var xamarin_private = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), "Xamarin", "MonoAndroid"); - var android_default = Path.Combine (OS.ProgramFilesX86, "Android"); - var cdrive_default = @"C:\"; - - foreach (var basePath in new string [] {xamarin_private, android_default, cdrive_default}) - if (Directory.Exists (basePath)) - foreach (var dir in Directory.GetDirectories (basePath, "android-ndk-r*")) - if (ValidateAndroidNdkLocation (dir)) - yield return dir; - } - - protected override string GetShortFormPath (string path) - { - return KernelEx.GetShortPathName (path); - } - - public override void SetPreferredAndroidSdkPath (string path) - { - RegistryEx.SetValueString (RegistryEx.CurrentUser, MDREG_KEY, MDREG_ANDROID_SDK, path ?? "", RegistryEx.Wow64.Key32); - } - - public override void SetPreferredJavaSdkPath (string path) - { - RegistryEx.SetValueString (RegistryEx.CurrentUser, MDREG_KEY, MDREG_JAVA_SDK, path ?? "", RegistryEx.Wow64.Key32); - } - - public override void SetPreferredAndroidNdkPath (string path) - { - RegistryEx.SetValueString (RegistryEx.CurrentUser, MDREG_KEY, MDREG_ANDROID_NDK, path ?? "", RegistryEx.Wow64.Key32); - } - - #region Helper Methods - private bool CheckRegistryKeyForExecutable (UIntPtr key, string subkey, string valueName, RegistryEx.Wow64 wow64, string subdir, string exe) - { - string key_name = string.Format (@"{0}\{1}\{2}", key == RegistryEx.CurrentUser ? "HKCU" : "HKLM", subkey, valueName); - - var path = NullIfEmpty (RegistryEx.GetValueString (key, subkey, valueName, wow64)); - - if (path == null) { - AndroidLogger.LogInfo ("sdk", " Key {0} not found.", key_name); - return false; - } - - if (!FindExecutableInDirectory (exe, Path.Combine (path, subdir)).Any ()) { - AndroidLogger.LogInfo ("sdk", " Key {0} found:\n Path does not contain {1} in \\{2} ({3}).", key_name, exe, subdir, path); - return false; - } - - AndroidLogger.LogInfo ("sdk", " Key {0} found:\n Path contains {1} in \\{2} ({3}).", key_name, exe, subdir, path); - - return true; - } - #endregion - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkBase.cs b/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkBase.cs deleted file mode 100644 index dfdb9829a50..00000000000 --- a/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkBase.cs +++ /dev/null @@ -1,292 +0,0 @@ -using System; -using System.Linq; -using System.IO; -using System.Collections.Generic; -using System.Xml; - -namespace Xamarin.Android.Build.Utilities -{ - abstract class MonoDroidSdkBase - { - protected readonly static string DebugRuntime = "Mono.Android.DebugRuntime-debug.apk"; - protected readonly static string ClassParseExe = "class-parse.exe"; - protected readonly static string GeneratorScript = "generator"; - - // I can never remember the difference between SdkPath and anything else... - [Obsolete ("Do not use.")] - public string SdkPath { get; private set; } - - // Contains mandroid - public string BinPath { get; private set; } - - // Not actually shipped... - public string IncludePath { get; private set; } - - // Contains Mono.Android.DebugRuntime-*.apk, platforms/*/*.apk. - public string RuntimePath { get; private set; } - - // Root directory for XA libraries, contains designer dependencies - public string LibrariesPath { get; private set; } - - // Contains mscorlib.dll - public string BclPath { get; private set; } - - public int SharedRuntimeVersion { get; private set; } - - // expectedRuntimePath: contains Mono.Android.DebugRuntime-*.apk - // binPath: contains mandroid - // mscorlibDir: contains mscorlib.dll - public void Initialize (string expectedRuntimePath = null, string binPath = null, string bclPath = null) - { - var runtimePath = GetValidPath ("MonoAndroidToolsPath", expectedRuntimePath, ValidateRuntime, () => FindRuntime ()); - if (runtimePath != null) { - binPath = GetValidPath ("MonoAndroidBinPath", binPath, ValidateBin, () => FindBin (runtimePath)); - bclPath = GetValidPath ("mscorlib.dll", bclPath, ValidateFramework, () => FindFramework (runtimePath)); - } else { - if (expectedRuntimePath != null) - AndroidLogger.LogWarning (null, "Runtime was not found at {0}", expectedRuntimePath); - binPath = bclPath = null; - } - - if (runtimePath == null || binPath == null || bclPath == null) { - Reset (); - return; - } - - RuntimePath = runtimePath; - #pragma warning disable 0618 - SdkPath = Path.GetFullPath (Path.Combine (runtimePath, "..", "..")); - #pragma warning restore 0618 - BinPath = binPath; - BclPath = bclPath; - LibrariesPath = FindLibraries (runtimePath); - - IncludePath = FindInclude (runtimePath); - if (IncludePath != null && !Directory.Exists (IncludePath)) - IncludePath = null; - - SharedRuntimeVersion = GetCurrentSharedRuntimeVersion (); - FindSupportedFrameworks (); - } - - static string GetValidPath (string description, string path, Func<string, bool> validator, Func<string> defaultPath) - { - if (!string.IsNullOrEmpty (path)) { - if (Directory.Exists (path)) { - if (validator (path)) - return path; - AndroidLogger.LogWarning (null, "{0} path '{1}' is explicitly specified, but it was not valid; skipping.", description, path); - } else - AndroidLogger.LogWarning (null, "{0} path '{1}' is explicitly specified, but it was not found; skipping.", description, path); - } - path = defaultPath (); - if (path != null && validator (path)) - return path; - if (path != null) - AndroidLogger.LogWarning (null, "{0} path is defaulted to '{1}', but it was not valid; skipping", description, path); - else - AndroidLogger.LogWarning (null, "{0} path is not found and no default location is provided; skipping", description); - return null; - } - - public void Reset () - { - #pragma warning disable 0618 - SdkPath = BinPath = IncludePath = RuntimePath = BclPath = null; - #pragma warning restore 0618 - SharedRuntimeVersion = 0; - } - - protected abstract string FindRuntime (); - protected abstract string FindFramework (string runtimePath); - - // Check for platform-specific `mandroid` name - protected abstract bool ValidateBin (string binPath); - - protected static bool ValidateRuntime (string loc) - { - return !string.IsNullOrWhiteSpace (loc) && - (File.Exists (Path.Combine (loc, DebugRuntime)) || // Normal/expected - File.Exists (Path.Combine (loc, ClassParseExe)) || // Normal/expected - File.Exists (Path.Combine (loc, "Ionic.Zip.dll"))); // Wrench builds - } - - protected static bool ValidateFramework (string loc) - { - return loc != null && File.Exists (Path.Combine (loc, "mscorlib.dll")); - } - - public string FindVersionFile () - { - #pragma warning disable 0618 - if (string.IsNullOrEmpty (SdkPath)) - return null; - #pragma warning restore 0618 - foreach (var loc in GetVersionFileLocations ()) { - if (File.Exists (loc)) { - return loc; - } - } - return null; - } - - protected virtual IEnumerable<string> GetVersionFileLocations () - { - #pragma warning disable 0618 - yield return Path.Combine (SdkPath, "Version"); - #pragma warning restore 0618 - } - - protected abstract string FindBin (string runtimePath); - - protected abstract string FindInclude (string runtimePath); - - protected abstract string FindLibraries (string runtimePath); - - [Obsolete ("Do not use.")] - public string GetPlatformNativeLibPath (string abi) - { - return FindPlatformNativeLibPath (SdkPath, abi); - } - - [Obsolete ("Do not use.")] - public string GetPlatformNativeLibPath (AndroidTargetArch arch) - { - return FindPlatformNativeLibPath (SdkPath, GetMonoDroidArchName (arch)); - } - - [Obsolete ("Do not use.")] - static string GetMonoDroidArchName (AndroidTargetArch arch) - { - switch (arch) { - case AndroidTargetArch.Arm: - return "armeabi"; - case AndroidTargetArch.Mips: - return "mips"; - case AndroidTargetArch.X86: - return "x86"; - } - return null; - } - - [Obsolete] - protected string FindPlatformNativeLibPath (string sdk, string arch) - { - return Path.Combine (sdk, "lib", arch); - } - - static XmlReaderSettings GetSafeReaderSettings () - { - //allow DTD but not try to resolve it from web - return new XmlReaderSettings { - CloseInput = true, - DtdProcessing = DtdProcessing.Ignore, - XmlResolver = null, - }; - } - - int GetCurrentSharedRuntimeVersion () - { - string file = Path.Combine (RuntimePath, "Mono.Android.DebugRuntime-debug.xml"); - - return GetManifestVersion (file); - } - - internal static int GetManifestVersion (string file) - { - // It seems that MfA 1.0 on Windows didn't include the xml files to get the runtime version. - if (!File.Exists (file)) - return int.MaxValue; - - try { - using (var r = XmlReader.Create (file, GetSafeReaderSettings())) { - if (r.MoveToContent () == XmlNodeType.Element && r.MoveToAttribute ("android:versionCode")) { - int value; - if (int.TryParse (r.Value, out value)) - return value; - AndroidLogger.LogInfo ("Cannot parse runtime version code: ({0})", r.Value); - } - } - } catch (Exception ex) { - AndroidLogger.LogError ("Error trying to find shared runtime version", ex); - } - return int.MaxValue; - } - - internal static Version ToVersion (string frameworkDir) - { - string version = Path.GetFileName (frameworkDir); - if (!version.StartsWith ("v", StringComparison.OrdinalIgnoreCase)) { - // wat? - return new Version (); - } - version = version.Substring (1); - Version v; - if (Version.TryParse (version, out v)) - return v; - return new Version (); - } - - void FindSupportedFrameworks () - { - string bclDir = MonoDroidSdk.FrameworkPath; - string frameworksDir = Path.GetDirectoryName (bclDir); - foreach (var framework in Directory.EnumerateDirectories (frameworksDir).Select (ToVersion)) { - if (framework.Major == 0) - continue; - string apiLevel; - if (FrameworkToApiLevels.TryGetValue (framework, out apiLevel)) - SupportedFrameworks.Add (framework, apiLevel); - } - } - - readonly Dictionary<Version, string> SupportedFrameworks = new Dictionary<Version, string> (); - - static readonly Dictionary<Version, string> FrameworkToApiLevels = new Dictionary<Version, string> (AndroidVersion.KnownVersions.ToDictionary<AndroidVersion, Version, string> (k => k.Version, v => v.ApiLevel.ToString ())); - static readonly Dictionary<Version, string> LegacyFrameworkToApiLevels = new Dictionary<Version, string> { - { new Version (4, 5), "21" } // L Preview - }; - - public IEnumerable<string> GetSupportedApiLevels () - { - return SupportedFrameworks.Select (e => e.Value); - } - - public string GetApiLevelForFrameworkVersion (string framework) - { - Version v; - if (!Version.TryParse (framework.TrimStart ('v'), out v)) - return null; - string apiLevel; - if (SupportedFrameworks.TryGetValue (v, out apiLevel) - || FrameworkToApiLevels.TryGetValue (v, out apiLevel) - || LegacyFrameworkToApiLevels.TryGetValue (v, out apiLevel)) - return apiLevel; - return null; - } - - public string GetFrameworkVersionForApiLevel (string apiLevel) - { - // API level 9 was discontinued immediately for 10, in the rare case we get it just upgrade the number - if (apiLevel == "9") - apiLevel = "10"; - var maxFrameworkVersion = SupportedFrameworks.Concat (FrameworkToApiLevels) - .Where (e => e.Value == apiLevel) - .OrderByDescending (e => e.Key, Comparer<Version>.Default) - .Select (e => e.Key) - .FirstOrDefault (); - if (maxFrameworkVersion != null) - return "v" + maxFrameworkVersion; - return null; - } - - /// <summary> - /// Determines if the given apiLevel is supported by an installed Framework - /// </summary> - public bool IsSupportedFrameworkLevel (string apiLevel) - { - return SupportedFrameworks.Any ((sf => sf.Value == apiLevel)); - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkUnix.cs b/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkUnix.cs deleted file mode 100644 index ebe35c2d08a..00000000000 --- a/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkUnix.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Collections.Generic; - -namespace Xamarin.Android.Build.Utilities -{ - class MonoDroidSdkUnix : MonoDroidSdkBase - { - readonly static string[] RuntimeToFrameworkPaths = new[]{ - Path.Combine ("..", "..", "..", ".xamarin.android", "lib", "xbuild-frameworks", "MonoAndroid"), - Path.Combine ("..", "xbuild-frameworks", "MonoAndroid"), - Path.Combine ("..", "mono", "2.1"), - }; - - readonly static string[] SearchPaths = { - "/Library/Frameworks/Xamarin.Android.framework/Versions/Current/lib/mandroid", - "/Developer/MonoAndroid/usr/lib/mandroid", - "/opt/mono-android/lib/mandroid" - }; - - protected override string FindRuntime () - { - string monoAndroidPath = Environment.GetEnvironmentVariable ("MONO_ANDROID_PATH"); - if (!string.IsNullOrEmpty (monoAndroidPath)) { - string libMandroid = Path.Combine (monoAndroidPath, "lib", "mandroid"); - if (Directory.Exists (libMandroid)) { - if (ValidateRuntime (libMandroid)) - return libMandroid; - AndroidLogger.LogInfo (null, "MONO_ANDROID_PATH points to {0}, but it is invalid.", monoAndroidPath); - } else - AndroidLogger.LogInfo (null, "MONO_ANDROID_PATH points to {0}, but it does not exist.", monoAndroidPath); - } - - // check also in the users folder - var personal = Environment.GetFolderPath (Environment.SpecialFolder.Personal); - var additionalSearchPaths = new [] { - // for Mono.Posix and Mono.Data.Sqlite builds in xamarin-android. - monoAndroidPath = Path.GetFullPath (Path.Combine (new Uri (GetType ().Assembly.CodeBase).LocalPath, "..", "..", "..", "..", "..", "lib", "mandroid")), - Path.Combine (personal, @".xamarin.android/lib/mandroid") - }; - - return additionalSearchPaths.Concat (SearchPaths).FirstOrDefault (ValidateRuntime); - } - - protected override bool ValidateBin (string binPath) - { - return !string.IsNullOrWhiteSpace (binPath) && - File.Exists (Path.Combine (binPath, GeneratorScript)); - } - - protected override string FindFramework (string runtimePath) - { - foreach (var relativePath in RuntimeToFrameworkPaths) { - var fullPath = Path.GetFullPath (Path.Combine (runtimePath, relativePath)); - if (Directory.Exists (fullPath)) { - if (ValidateFramework (fullPath)) - return fullPath; - - // check to see if full path is the folder that contains each framework version, eg contains folders of the form v1.0, v2.3 etc - var subdirs = Directory.GetDirectories (fullPath, "v*").OrderBy (x => x).ToArray (); - foreach (var subdir in subdirs) { - if (ValidateFramework (subdir)) - return subdir; - } - } - } - - return null; - } - - protected override string FindBin (string runtimePath) - { - string binPath = Path.GetFullPath (Path.Combine (runtimePath, "..", "..", "bin")); - if (File.Exists (Path.Combine (binPath, GeneratorScript))) - return binPath; - return null; - } - - protected override string FindInclude (string runtimePath) - { - string includeDir = Path.GetFullPath (Path.Combine (runtimePath, "..", "..", "include")); - if (Directory.Exists (includeDir)) - return includeDir; - return null; - } - - protected override string FindLibraries (string runtimePath) - { - return Path.GetFullPath (Path.Combine (runtimePath, "..")); - } - - protected override IEnumerable<string> GetVersionFileLocations () - { - yield return Path.GetFullPath (Path.Combine (RuntimePath, "..", "..", "Version")); - string sdkPath = Path.GetDirectoryName (Path.GetDirectoryName (RuntimePath)); - if (Path.GetFileName (sdkPath) == "usr") - yield return Path.GetFullPath (Path.Combine (Path.GetDirectoryName (sdkPath), "Version")); - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkWindows.cs b/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkWindows.cs deleted file mode 100644 index a5905cec24c..00000000000 --- a/src/Xamarin.Android.Build.Utilities/Sdks/MonoDroidSdkWindows.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; - -namespace Xamarin.Android.Build.Utilities -{ - class MonoDroidSdkWindows : MonoDroidSdkBase - { - protected override string FindRuntime () - { - string monoAndroidPath = Environment.GetEnvironmentVariable ("MONO_ANDROID_PATH"); - if (!string.IsNullOrEmpty (monoAndroidPath)) { - string libMandroid = Path.Combine (monoAndroidPath, "lib", "mandroid"); - if (Directory.Exists (libMandroid) && ValidateRuntime (libMandroid)) - return libMandroid; - } - string xamarinSdk = Path.Combine (OS.ProgramFilesX86, "MSBuild", "Xamarin", "Android"); - return Directory.Exists (xamarinSdk) - ? xamarinSdk - : OS.ProgramFilesX86 + @"\MSBuild\Novell"; - } - - static readonly string[] RuntimeToFrameworkPaths = new []{ - Path.Combine ("..", "..", "..", "Reference Assemblies", "Microsoft", "Framework", "MonoAndroid"), - Path.Combine (OS.ProgramFilesX86, "Reference Assemblies", "Microsoft", "Framework", "MonoAndroid"), - }; - - protected override string FindFramework (string runtimePath) - { - foreach (var relativePath in RuntimeToFrameworkPaths) { - var fullPath = Path.GetFullPath (Path.Combine (runtimePath, relativePath)); - if (Directory.Exists (fullPath)) { - if (ValidateFramework (fullPath)) - return fullPath; - - // check to see if full path is the folder that contains each framework version, eg contains folders of the form v1.0, v2.3 etc - var subdirs = Directory.GetDirectories (fullPath, "v*").OrderBy (x => x).ToArray (); - foreach (var subdir in subdirs) { - if (ValidateFramework (subdir)) - return subdir; - } - } - } - - return null; - } - - protected override string FindBin (string runtimePath) - { - return runtimePath; - } - - protected override bool ValidateBin (string binPath) - { - return !string.IsNullOrWhiteSpace (binPath) && - File.Exists (Path.Combine (binPath, "generator.exe")); - } - - protected override string FindInclude (string runtimePath) - { - return Path.GetFullPath (Path.Combine (runtimePath, "include")); - } - - protected override string FindLibraries (string runtimePath) - { - return Path.GetFullPath (runtimePath); - } - - protected override IEnumerable<string> GetVersionFileLocations () - { - yield return Path.GetFullPath (Path.Combine (RuntimePath, "Version")); - } - } -} - diff --git a/src/Xamarin.Android.Build.Utilities/Xamarin.Android.Build.Utilities.csproj b/src/Xamarin.Android.Build.Utilities/Xamarin.Android.Build.Utilities.csproj index da208f36abe..81195b900f5 100644 --- a/src/Xamarin.Android.Build.Utilities/Xamarin.Android.Build.Utilities.csproj +++ b/src/Xamarin.Android.Build.Utilities/Xamarin.Android.Build.Utilities.csproj @@ -35,25 +35,14 @@ <ItemGroup> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="GdbPaths.cs" /> - <Compile Include="AndroidTargetArch.cs" /> - <Compile Include="OS.cs" /> - <Compile Include="MonoDroidSdk.cs" /> - <Compile Include="AndroidAppManifest.cs" /> - <Compile Include="AndroidVersion.cs" /> <Compile Include="FileUtil.cs" /> - <Compile Include="AndroidSdk.cs" /> <Compile Include="SatelliteAssembly.cs" /> - <Compile Include="Sdks\MonoDroidSdkBase.cs" /> - <Compile Include="Sdks\MonoDroidSdkUnix.cs" /> - <Compile Include="Sdks\MonoDroidSdkWindows.cs" /> - <Compile Include="AndroidLogger.cs" /> - <Compile Include="Sdks\AndroidSdkBase.cs" /> - <Compile Include="Sdks\AndroidSdkUnix.cs" /> - <Compile Include="Sdks\AndroidSdkWindows.cs" /> - <Compile Include="ProcessUtils.cs" /> </ItemGroup> - <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> - <Folder Include="Sdks\" /> + <ProjectReference Include="..\..\external\xamarin-android-tools\src\Xamarin.Android.Tools\Xamarin.Android.Tools.csproj"> + <Project>{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}</Project> + <Name>Xamarin.Android.Tools</Name> + </ProjectReference> </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project>