/// <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); }
/// <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); }
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); }
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); }
/// <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); } } }
/// <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); } }
/// <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)); } } }
/// <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; } }
/// <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; }
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; }
/// <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); }
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; }
/// <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; }
/// <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; }
/// <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; }
/// <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); }
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); }