Beispiel #1
0
        /// <summary>
        /// Resolves the various file paths used by the AndroidDebugLauncher and returns an initialized InstallPaths object
        /// </summary>
        /// <param name="token">token to check for cancelation</param>
        /// <param name="launchOptions">[Required] launch options object</param>
        /// <returns>[Required] Created InstallPaths object</returns>
        public static InstallPaths Resolve(CancellationToken token, AndroidLaunchOptions launchOptions)
        {
            var result = new InstallPaths();

            if (launchOptions.SDKRoot != null)
            {
                result.SDKRoot = launchOptions.SDKRoot;
            }
            else
            {
                result.SDKRoot = GetDirectoryFromRegistry(@"SOFTWARE\Android SDK Tools", "Path", checkBothBitnesses: true, externalProductName: LauncherResources.ProductName_NDK);
            }

            string ndkRoot = launchOptions.NDKRoot;

            if (ndkRoot == null)
            {
                ndkRoot = GetDirectoryFromRegistry(RegistryRoot.Value + @"\Setup\VS\SecondaryInstaller\AndroidNDK", "NDK_HOME", checkBothBitnesses: false, externalProductName: LauncherResources.ProductName_SDK);
            }

            string ndkReleaseVersionFile = Path.Combine(ndkRoot, "RELEASE.TXT");

            if (!File.Exists(ndkReleaseVersionFile))
            {
                ThrowExternalFileNotFoundException(ndkReleaseVersionFile, LauncherResources.ProductName_NDK);
            }

            NdkReleaseId ndkReleaseId;

            NdkReleaseId.TryParseFile(ndkReleaseVersionFile, out ndkReleaseId);
            MICore.Logger.WriteLine("Using NDK '{0}' from path '{1}'", ndkReleaseId, ndkRoot);

            string targetArchitectureName;

            NDKToolChainFilePath[] possibleGDBPaths;
            switch (launchOptions.TargetArchitecture)
            {
            case MICore.TargetArchitecture.X86:
                targetArchitectureName = "x86";
                possibleGDBPaths       = NDKToolChainFilePath.x86_GDBPaths();
                break;

            case MICore.TargetArchitecture.X64:
                targetArchitectureName = "x64";
                possibleGDBPaths       = NDKToolChainFilePath.x64_GDBPaths();
                break;

            case MICore.TargetArchitecture.ARM:
                targetArchitectureName = "arm";
                possibleGDBPaths       = NDKToolChainFilePath.ARM_GDBPaths();
                break;

            case MICore.TargetArchitecture.ARM64:
                targetArchitectureName = "arm64";
                possibleGDBPaths       = NDKToolChainFilePath.ARM64_GDBPaths();
                break;

            default:
                Debug.Fail("Should be impossible");
                throw new InvalidOperationException();
            }

            NDKToolChainFilePath matchedPath;

            result.GDBPath = GetNDKFilePath(
                string.Concat("Android-", targetArchitectureName, "-GDBPath"),
                ndkRoot,
                possibleGDBPaths,
                out matchedPath
                );
            if (launchOptions.TargetArchitecture == MICore.TargetArchitecture.X86 && matchedPath != null)
            {
                var r10b = new NdkReleaseId(10, 'b', true);

                // Before r10b, the 'windows-x86_64' ndk didn't support x86 debugging
                if (ndkReleaseId.IsValid && ndkReleaseId.CompareVersion(r10b) < 0 && matchedPath.PartialFilePath.Contains(@"\windows-x86_64\"))
                {
                    throw new LauncherException(Telemetry.LaunchFailureCode.NoReport, LauncherResources.Error_64BitNDKNotSupportedForX86);
                }
            }

            token.ThrowIfCancellationRequested();

            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Obtains the path to an NDK file
        /// </summary>
        /// <param name="registryValueName">[Required] registry value to check first</param>
        /// <param name="ndkRoot">[Required] Path to the NDK</param>
        /// <param name="possiblePaths">[Required] Array of possible paths with in the NDK where the file may be found</param>
        /// <param name="matchedPath">[Optional] If the returned path comes from an NDK location, returns the source object</param>
        /// <returns>[Required] value to use, file path will exist</returns>
        private static string GetNDKFilePath(string registryValueName, string ndkRoot, NDKToolChainFilePath[] possiblePaths, out NDKToolChainFilePath matchedPath)
        {
            matchedPath = null;

            if (string.IsNullOrEmpty(ndkRoot))
            {
                throw new ArgumentNullException("ndkRoot");
            }

            if (possiblePaths == null || possiblePaths.Length <= 0)
            {
                throw new ArgumentOutOfRangeException("possiblePaths");
            }

            string value = TryGetRegistryValue(RegistryRoot.Value + @"\Debugger", registryValueName, RegistryView.Default);
            if (value != null)
            {
                if (File.Exists(value))
                {
                    return value;
                }

                // fall through to throw an exception
            }
            else
            {
                foreach (NDKToolChainFilePath pathObject in possiblePaths)
                {
                    value = pathObject.TryResolve(ndkRoot);
                    if (value != null)
                    {
                        matchedPath = pathObject;
                        return value;
                    }
                }

                value = possiblePaths.First().GetSearchPathDescription(ndkRoot);
                // fall through to throw an exception
            }

            ThrowExternalFileNotFoundException(value, LauncherResources.ProductName_NDK);
            return null; // unreachable code
        }
Beispiel #3
0
        /// <summary>
        /// Obtains the path to an NDK file
        /// </summary>
        /// <param name="registryValueName">[Required] registry value to check first</param>
        /// <param name="ndkRoot">[Required] Path to the NDK</param>
        /// <param name="possiblePaths">[Required] Array of possible paths with in the NDK where the file may be found</param>
        /// <param name="matchedPath">[Optional] If the returned path comes from an NDK location, returns the source object</param>
        /// <returns>[Required] value to use, file path will exist</returns>
        private static string GetNDKFilePath(string registryValueName, string ndkRoot, NDKToolChainFilePath[] possiblePaths, out NDKToolChainFilePath matchedPath)
        {
            matchedPath = null;

            if (string.IsNullOrEmpty(ndkRoot))
            {
                throw new ArgumentNullException("ndkRoot");
            }

            if (possiblePaths == null || possiblePaths.Length <= 0)
            {
                throw new ArgumentOutOfRangeException("possiblePaths");
            }

            string value = TryGetRegistryValue(RegistryRoot.Value + @"\Debugger", registryValueName, RegistryView.Default);

            if (value != null)
            {
                if (File.Exists(value))
                {
                    return(value);
                }

                // fall through to throw an exception
            }
            else
            {
                foreach (NDKToolChainFilePath pathObject in possiblePaths)
                {
                    value = pathObject.TryResolve(ndkRoot);
                    if (value != null)
                    {
                        matchedPath = pathObject;
                        return(value);
                    }
                }

                value = possiblePaths.First().GetSearchPathDescription(ndkRoot);
                // fall through to throw an exception
            }

            ThrowExternalFileNotFoundException(value, LauncherResources.ProductName_NDK);
            return(null); // unreachable code
        }
Beispiel #4
0
        /// <summary>
        /// Resolves the various file paths used by the AndroidDebugLauncher and returns an initialized InstallPaths object
        /// </summary>
        /// <param name="token">token to check for cancelation</param>
        /// <param name="launchOptions">[Required] launch options object</param>
        /// <returns>[Required] Created InstallPaths object</returns>
        public static InstallPaths Resolve(CancellationToken token, AndroidLaunchOptions launchOptions, MICore.Logger logger)
        {
            var result = new InstallPaths();

            if (launchOptions.SDKRoot != null)
            {
                result.SDKRoot = launchOptions.SDKRoot;
            }
            else
            {
                result.SDKRoot = GetDirectoryFromRegistry(@"SOFTWARE\Android SDK Tools", "Path", checkBothBitnesses: true, externalProductName: LauncherResources.ProductName_SDK);
            }

            string ndkRoot = launchOptions.NDKRoot;

            if (ndkRoot == null)
            {
                ndkRoot = GetDirectoryFromRegistry(RegistryRoot.Value + @"\Setup\VS\SecondaryInstaller\AndroidNDK", "NDK_HOME", checkBothBitnesses: false, externalProductName: LauncherResources.ProductName_NDK);
            }

            NdkReleaseId ndkReleaseId            = new NdkReleaseId();
            string       ndkReleaseVersionFile   = Path.Combine(ndkRoot, "RELEASE.TXT");
            string       ndkSourcePropertiesFile = Path.Combine(ndkRoot, "source.properties");

            // NDK releases >= r11 have a source.properties file
            if (File.Exists(ndkSourcePropertiesFile))
            {
                NdkReleaseId.TryParsePropertiesFile(ndkSourcePropertiesFile, out ndkReleaseId);
            }
            // NDK releases < r11 have a RELEASE.txt file
            else if (File.Exists(ndkReleaseVersionFile))
            {
                NdkReleaseId.TryParseFile(ndkReleaseVersionFile, out ndkReleaseId);
            }
            else
            {
                ThrowExternalFileNotFoundException(ndkReleaseVersionFile, LauncherResources.ProductName_NDK);
            }

            logger.WriteLine("Using NDK '{0}' from path '{1}'", ndkReleaseId, ndkRoot);

            // 32 vs 64-bit doesn't matter when comparing
            var r11 = new NdkReleaseId(11, 'a');
            // In NDK r11 and later, gdb is multi-arch and there's only one binary
            // in the prebuilt directory
            bool usePrebuiltGDB = ndkReleaseId.CompareVersion(r11) >= 0;
            IEnumerable <INDKFilePath> prebuiltGDBPath = NDKPrebuiltFilePath.GDBPaths();

            string targetArchitectureName;
            IEnumerable <INDKFilePath> possibleGDBPaths;

            switch (launchOptions.TargetArchitecture)
            {
            case MICore.TargetArchitecture.X86:
                targetArchitectureName = "x86";
                possibleGDBPaths       = usePrebuiltGDB ? prebuiltGDBPath: NDKToolChainFilePath.x86_GDBPaths();
                break;

            case MICore.TargetArchitecture.X64:
                targetArchitectureName = "x64";
                possibleGDBPaths       = usePrebuiltGDB ? prebuiltGDBPath : NDKToolChainFilePath.x64_GDBPaths();
                break;

            case MICore.TargetArchitecture.ARM:
                targetArchitectureName = "arm";
                possibleGDBPaths       = usePrebuiltGDB ? prebuiltGDBPath : NDKToolChainFilePath.ARM_GDBPaths();
                break;

            case MICore.TargetArchitecture.ARM64:
                targetArchitectureName = "arm64";
                possibleGDBPaths       = usePrebuiltGDB ? prebuiltGDBPath : NDKToolChainFilePath.ARM64_GDBPaths();
                break;

            default:
                Debug.Fail("Should be impossible");
                throw new InvalidOperationException();
            }

            INDKFilePath matchedPath;

            result.GDBPath = GetNDKFilePath(
                string.Concat("Android-", targetArchitectureName, "-GDBPath"),
                ndkRoot,
                possibleGDBPaths,
                out matchedPath
                );
            if (launchOptions.TargetArchitecture == MICore.TargetArchitecture.X86 && matchedPath != null)
            {
                var r10b = new NdkReleaseId(10, 'b');

                // Before r10b, the 'windows-x86_64' ndk didn't support x86 debugging
                if (ndkReleaseId.IsValid && ndkReleaseId.CompareVersion(r10b) < 0 && matchedPath.PartialFilePath.Contains(@"\windows-x86_64\"))
                {
                    throw new LauncherException(Telemetry.LaunchFailureCode.NoReport, LauncherResources.Error_64BitNDKNotSupportedForX86);
                }
            }

            token.ThrowIfCancellationRequested();

            return(result);
        }