Exemple #1
0
        /// <summary>
        /// Try to parse the revision from the ndk
        /// </summary>
        /// <param name="revision">[Required] revision of the ndk in the format major.hotfix.build</param>
        /// <param name="result">On success, a valid version</param>
        /// <returns>true if successful</returns>
        public static bool TryParseRevision(string revision, out NdkReleaseId result)
        {
            result = new NdkReleaseId();

            string[] numbers = revision.Split('.');
            if (numbers.Length != 3)
            {
                return(false);
            }

            string releaseString = numbers[0];
            uint   releaseNumber;

            if (!uint.TryParse(releaseString, NumberStyles.None, CultureInfo.InvariantCulture, out releaseNumber) ||
                releaseNumber == 0)
            {
                return(false);
            }

            string subReleaseString = numbers[1];
            char   subReleaseChar   = 'a';
            int    subReleaseNumber;

            if (!int.TryParse(subReleaseString, out subReleaseNumber))
            {
                return(false);
            }

            subReleaseChar += Convert.ToChar(subReleaseNumber);

            result = new NdkReleaseId(releaseNumber, subReleaseChar);
            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Compare this version to another, ignoring 32-bit vs. 64-bit.
        /// </summary>
        /// <param name="other">value to compare against</param>
        /// <returns>
        /// Less than zero: This object is less than the other parameter.
        /// Zero: This object is equal to other.
        /// Greater than zero: This object is greater than other.
        /// </returns>
        public int CompareVersion(NdkReleaseId other)
        {
            if (this.ReleaseNumber != other.ReleaseNumber)
            {
                if (this.ReleaseNumber < other.ReleaseNumber)
                {
                    return(-1);
                }
                else
                {
                    return(1);
                }
            }

            if (this.SubRelease != other.SubRelease)
            {
                if (this.SubRelease < other.SubRelease)
                {
                    return(-1);
                }
                else
                {
                    return(1);
                }
            }

            return(0);
        }
Exemple #3
0
        public static bool TryParse(string value, out NdkReleaseId result)
        {
            // The version number should look like:
            //   r10
            //   -or-
            //   r10b
            //   -or-
            //   r10b (64-bit)

            result = new NdkReleaseId();

            if (value.Length < 2)
            {
                return(false);
            }

            if (value[0] != 'r')
            {
                return(false);
            }

            int currentPosition = 1;

            while (currentPosition < value.Length && char.IsDigit(value[currentPosition]))
            {
                currentPosition++;
            }

            if (currentPosition == 1)
            {
                return(false); // no number
            }

            string numberString = value.Substring(1, currentPosition - 1);
            uint   releaseNumber;

            if (!uint.TryParse(numberString, NumberStyles.None, CultureInfo.InvariantCulture, out releaseNumber) ||
                releaseNumber == 0)
            {
                return(false);
            }

            char subRelease = (char)0;

            if (currentPosition < value.Length)
            {
                subRelease = value[currentPosition];
                currentPosition++;

                if (subRelease < 'a' || subRelease > 'z')
                {
                    return(false);
                }
            }

            result = new NdkReleaseId(releaseNumber, subRelease);
            return(true);
        }
        public void TestNdkReleaseIdCompare()
        {
            NdkReleaseId r10 = new NdkReleaseId(10, (char)0);
            NdkReleaseId r10b = new NdkReleaseId(10, 'b');
            NdkReleaseId r9d = new NdkReleaseId(9, 'd');

            Assert.True(r10.CompareVersion(r10) == 0);
            Assert.True(r10.CompareVersion(r10b) < 0);
            Assert.True(r10b.CompareVersion(r10) > 0);
            Assert.True(r10.CompareVersion(r9d) > 0);
            Assert.True(r9d.CompareVersion(r10) < 0);
        }
Exemple #5
0
        public void TestNdkReleaseId2()
        {
            NdkReleaseId r10 = new NdkReleaseId(10, (char)0, true);
            NdkReleaseId r10_64bit = new NdkReleaseId(10, (char)0, false);
            NdkReleaseId r10b = new NdkReleaseId(10, 'b', true);
            NdkReleaseId r9d = new NdkReleaseId(9, 'd', true);

            Assert.True(r10.CompareVersion(r10) == 0);
            Assert.True(r10.CompareVersion(r10_64bit) == 0);
            Assert.True(r10.CompareVersion(r10b) < 0);
            Assert.True(r10b.CompareVersion(r10) > 0);
            Assert.True(r10.CompareVersion(r9d) > 0);
            Assert.True(r9d.CompareVersion(r10) < 0);
        }
Exemple #6
0
        /// <summary>
        /// Try to parse the version number from the ndk release.txt file.
        /// </summary>
        /// <param name="ndkReleaseVersionFile">[Required] path to the NDK release.txt file. This file must exist</param>
        /// <param name="result">On success, a valid version</param>
        /// <returns>true if successful</returns>
        public static bool TryParseFile(string ndkReleaseVersionFile, out NdkReleaseId result)
        {
            result = new NdkReleaseId();

            using (StreamReader reader = File.OpenText(ndkReleaseVersionFile))
            {
                while (true)
                {
                    string version = reader.ReadLine();
                    if (version == null)
                        return false; // end of file

                    version = version.Trim();
                    if (version.Length == 0)
                        continue; // ignore any blank lines. I don't expect there to be any, but it seems reasonable to do

                    return TryParse(version, out result);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Try to parse the revision from the ndk source.properties file
        /// </summary>
        /// <param name="ndkSourcePropertiesFilePath">[Required] path to the NDK source.properties file. This file must exist</param>
        /// <param name="result"></param>
        /// <returns>true if successful</returns>
        public static bool TryParsePropertiesFile(string ndkSourcePropertiesFilePath, out NdkReleaseId result)
        {
            result = new NdkReleaseId();

            using (StreamReader reader = File.OpenText(ndkSourcePropertiesFilePath))
            {
                Dictionary <string, string> properties = new Dictionary <string, string>();
                while (true)
                {
                    string line = reader.ReadLine();
                    if (line == null)
                    {
                        break; // end of file
                    }
                    line = line.Trim();
                    if (line.Length == 0)
                    {
                        continue; // ignore any blank lines. I don't expect there to be any, but it seems reasonable to do
                    }
                    // .properties files can theoretically have '=' characters in the value portion,
                    // but I don't expect this will happen and our parsing logic below can't handle it anyway
                    string[] keyValue = line.Split('=');
                    if (keyValue.Length != 2)
                    {
                        return(false);
                    }

                    properties.Add(keyValue[0].Trim(), keyValue[1].Trim());
                }

                string revision;
                if (properties.TryGetValue("Pkg.Revision", out revision))
                {
                    return(TryParseRevision(revision, out result));
                }

                return(false);
            }
        }
Exemple #8
0
        /// <summary>
        /// Try to parse the version number from the ndk release.txt file.
        /// </summary>
        /// <param name="ndkReleaseVersionFile">[Required] path to the NDK release.txt file. This file must exist</param>
        /// <param name="result">On success, a valid version</param>
        /// <returns>true if successful</returns>
        public static bool TryParseFile(string ndkReleaseVersionFile, out NdkReleaseId result)
        {
            result = new NdkReleaseId();

            using (StreamReader reader = File.OpenText(ndkReleaseVersionFile))
            {
                while (true)
                {
                    string version = reader.ReadLine();
                    if (version == null)
                    {
                        return(false); // end of file
                    }
                    version = version.Trim();
                    if (version.Length == 0)
                    {
                        continue; // ignore any blank lines. I don't expect there to be any, but it seems reasonable to do
                    }
                    return(TryParse(version, out result));
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Try to parse the revision from the ndk source.properties file
        /// </summary>
        /// <param name="ndkSourcePropertiesFilePath">[Required] path to the NDK source.properties file. This file must exist</param>
        /// <param name="result"></param>
        /// <returns>true if successful</returns>
        public static bool TryParsePropertiesFile(string ndkSourcePropertiesFilePath, out NdkReleaseId result)
        {
            result = new NdkReleaseId();

            using (StreamReader reader = File.OpenText(ndkSourcePropertiesFilePath))
            {
                Dictionary<string, string> properties = new Dictionary<string, string>();
                while (true)
                {
                    string line = reader.ReadLine();
                    if (line == null)
                        break; // end of file

                    line = line.Trim();
                    if (line.Length == 0)
                        continue; // ignore any blank lines. I don't expect there to be any, but it seems reasonable to do

                    // .properties files can theoretically have '=' characters in the value portion,
                    // but I don't expect this will happen and our parsing logic below can't handle it anyway
                    string[] keyValue = line.Split('=');
                    if (keyValue.Length != 2)
                    {
                        return false;
                    }

                    properties.Add(keyValue[0].Trim(), keyValue[1].Trim());
                }

                string revision;
                if (properties.TryGetValue("Pkg.Revision", out revision))
                {
                    return TryParseRevision(revision, out result);
                }

                return false;
            }
        }
Exemple #10
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);
            }

            string ndkReleaseVersionFile = Path.Combine(ndkRoot, "RELEASE.TXT");
            if (!File.Exists(ndkReleaseVersionFile))
            {
                ThrowExternalFileNotFoundException(ndkReleaseVersionFile, LauncherResources.ProductName_NDK);
            }

            NdkReleaseId ndkReleaseId;
            NdkReleaseId.TryParseFile(ndkReleaseVersionFile, out ndkReleaseId);
            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;
        }
Exemple #11
0
        public static bool TryParse(string value, out NdkReleaseId result)
        {
            // The version number should look like:
            //   r10
            //   -or-
            //   r10b
            //   -or-
            //   r10b (64-bit)

            result = new NdkReleaseId();

            if (value.Length < 2)
                return false;

            if (value[0] != 'r')
                return false;

            int currentPosition = 1;
            while (currentPosition < value.Length && char.IsDigit(value[currentPosition]))
            {
                currentPosition++;
            }

            if (currentPosition == 1)
            {
                return false; // no number
            }

            string numberString = value.Substring(1, currentPosition - 1);
            uint releaseNumber;
            if (!uint.TryParse(numberString, NumberStyles.None, CultureInfo.InvariantCulture, out releaseNumber) ||
                releaseNumber == 0)
            {
                return false;
            }

            char subRelease = (char)0;

            if (currentPosition < value.Length)
            {
                subRelease = value[currentPosition];
                currentPosition++;

                if (subRelease < 'a' || subRelease > 'z')
                    return false;
            }

            result = new NdkReleaseId(releaseNumber, subRelease);
            return true;
        }
Exemple #12
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);
        }
Exemple #13
0
        public static bool TryParse(string value, out NdkReleaseId result)
        {
            // The version number should look like:
            //   r10
            //   -or-
            //   r10b
            //   -or-
            //   r10b (64-bit)

            result = new NdkReleaseId();

            if (value.Length < 2)
                return false;

            if (value[0] != 'r')
                return false;

            int currentPosition = 1;
            while (currentPosition < value.Length && char.IsDigit(value[currentPosition]))
            {
                currentPosition++;
            }

            if (currentPosition == 1)
            {
                return false; // no number
            }

            string numberString = value.Substring(1, currentPosition - 1);
            uint releaseNumber;
            if (!uint.TryParse(numberString, NumberStyles.None, CultureInfo.InvariantCulture, out releaseNumber) ||
                releaseNumber == 0)
            {
                return false;
            }

            char subRelease = (char)0;
            bool is32bit = true;

            if (currentPosition < value.Length)
            {
                subRelease = value[currentPosition];
                currentPosition++;

                if (subRelease < 'a' || subRelease > 'z')
                    return false;

                // skip past any spaces
                while (currentPosition < value.Length && value[currentPosition] == ' ')
                {
                    currentPosition++;
                }

                if (currentPosition < value.Length)
                {
                    string suffix = value.Substring(currentPosition);
                    if (!suffix.Equals("(64-bit)", StringComparison.OrdinalIgnoreCase))
                    {
                        return false;
                    }

                    is32bit = false;
                }
            }

            result = new NdkReleaseId(releaseNumber, subRelease, is32bit);
            return true;
        }
Exemple #14
0
        /// <summary>
        /// Compare this version to another, ignoring 32-bit vs. 64-bit.
        /// </summary>
        /// <param name="other">value to compare against</param>
        /// <returns>
        /// Less than zero: This object is less than the other parameter.
        /// Zero: This object is equal to other. 
        /// Greater than zero: This object is greater than other.
        /// </returns>
        public int CompareVersion(NdkReleaseId other)
        {
            if (this.ReleaseNumber != other.ReleaseNumber)
            {
                if (this.ReleaseNumber < other.ReleaseNumber)
                    return -1;
                else
                    return 1;
            }

            if (this.SubRelease != other.SubRelease)
            {
                if (this.SubRelease < other.SubRelease)
                    return -1;
                else
                    return 1;
            }

            return 0;
        }
Exemple #15
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 = launchOptions.TargetArchitecture.ToNDKArchitectureName();
            IEnumerable<INDKFilePath> possibleGDBPaths;

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

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

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

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

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

            INDKFilePath gdbMatchedPath;
            result.GDBPath = GetNDKFilePath(
                string.Concat("Android-", targetArchitectureName, "-GDBPath"),
                ndkRoot,
                possibleGDBPaths,
                out gdbMatchedPath
                );
            if (launchOptions.TargetArchitecture == MICore.TargetArchitecture.X86 && gdbMatchedPath != 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 && gdbMatchedPath.PartialFilePath.Contains(@"\windows-x86_64\"))
                {
                    throw new LauncherException(Telemetry.LaunchFailureCode.NoReport, LauncherResources.Error_64BitNDKNotSupportedForX86);
                }
            }

            IEnumerable<INDKFilePath> gdbServerPath = NDKPrebuiltFilePath.GDBServerPaths(targetArchitectureName);
            INDKFilePath gdbServerMatchedPath;
            result.GDBServerPath = GetNDKFilePath(
                string.Concat("Android-", targetArchitectureName, "-GDBServerPath"),
                ndkRoot,
                gdbServerPath,
                out gdbServerMatchedPath // not used
                );

            token.ThrowIfCancellationRequested();

            return result;
        }
Exemple #16
0
        /// <summary>
        /// Try to parse the revision from the ndk
        /// </summary>
        /// <param name="revision">[Required] revision of the ndk in the format major.hotfix.build</param>
        /// <param name="result">On success, a valid version</param>
        /// <returns>true if successful</returns>
        public static bool TryParseRevision(string revision, out NdkReleaseId result)
        {
            result = new NdkReleaseId();

            string[] numbers = revision.Split('.');
            if (numbers.Length != 3)
            {
                return false;
            }

            string releaseString = numbers[0];
            uint releaseNumber;

            if (!uint.TryParse(releaseString, NumberStyles.None, CultureInfo.InvariantCulture, out releaseNumber) ||
                releaseNumber == 0)
            {
                return false;
            }

            string subReleaseString = numbers[1];
            char subReleaseChar = 'a';
            int subReleaseNumber;
            if (!int.TryParse(subReleaseString, out subReleaseNumber))
            {
                return false;
            }

            subReleaseChar += Convert.ToChar(subReleaseNumber);

            result = new NdkReleaseId(releaseNumber, subReleaseChar);
            return true;
        }
Exemple #17
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);
        }
Exemple #18
0
        public static bool TryParse(string value, out NdkReleaseId result)
        {
            // The version number should look like:
            //   r10
            //   -or-
            //   r10b
            //   -or-
            //   r10b (64-bit)

            result = new NdkReleaseId();

            if (value.Length < 2)
            {
                return(false);
            }

            if (value[0] != 'r')
            {
                return(false);
            }

            int currentPosition = 1;

            while (currentPosition < value.Length && char.IsDigit(value[currentPosition]))
            {
                currentPosition++;
            }

            if (currentPosition == 1)
            {
                return(false); // no number
            }

            string numberString = value.Substring(1, currentPosition - 1);
            uint   releaseNumber;

            if (!uint.TryParse(numberString, NumberStyles.None, CultureInfo.InvariantCulture, out releaseNumber) ||
                releaseNumber == 0)
            {
                return(false);
            }

            char subRelease = (char)0;
            bool is32bit    = true;

            if (currentPosition < value.Length)
            {
                subRelease = value[currentPosition];
                currentPosition++;

                if (subRelease < 'a' || subRelease > 'z')
                {
                    return(false);
                }

                // skip past any spaces
                while (currentPosition < value.Length && value[currentPosition] == ' ')
                {
                    currentPosition++;
                }

                if (currentPosition < value.Length)
                {
                    string suffix = value.Substring(currentPosition);
                    if (!suffix.Equals("(64-bit)", StringComparison.OrdinalIgnoreCase))
                    {
                        return(false);
                    }

                    is32bit = false;
                }
            }

            result = new NdkReleaseId(releaseNumber, subRelease, is32bit);
            return(true);
        }