public static string GetNdkPlatformLibPath(string androidNdkPath, AndroidTargetArch arch, int apiLevel) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkPlatformLibPath(androidNdkPath, arch, apiLevel)); } var checkedPaths = new List <string> (); string lib = arch == AndroidTargetArch.X86_64 ? "lib64" : "lib"; string path = Path.Combine(androidNdkPath, "platforms", $"android-{apiLevel}", $"arch-{GetPlatformArch (arch)}", "usr", lib); if (!Directory.Exists(path)) { checkedPaths.Add(path); path = Path.Combine(GetNdk22OrNewerSysrootDir(androidNdkPath), GetArchDirName(arch), apiLevel.ToString()); } if (!Directory.Exists(path)) { checkedPaths.Add(path); string paths = String.Join("; ", checkedPaths); throw new InvalidOperationException($"Platform library directory for target {arch} and API Level {apiLevel} was not found. Checked paths: {paths}"); } return(path); }
public static string GetNdkToolchainPrefix(AndroidTargetArch arch, bool forCompiler) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkToolchainPrefix(arch)); } switch (arch) { case AndroidTargetArch.Arm: return(forCompiler ? "armv7a-linux-androideabi" : "arm-linux-androideabi"); case AndroidTargetArch.Arm64: return("aarch64-linux-android"); case AndroidTargetArch.X86: return("i686-linux-android"); case AndroidTargetArch.X86_64: return("x86_64-linux-android"); default: // return empty. Since this method returns the "prefix", the resulting // tool path just becomes the tool name i.e. "gcc" becomes "gcc". // This should work for any custom arbitrary platform. return(String.Empty); } }
public static string GetNdkAsmIncludePath(string androidNdkPath, AndroidTargetArch arch, int apiLevel) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkAsmIncludePath(androidNdkPath, arch, apiLevel)); } string path = GetUnifiedHeadersPath(androidNdkPath); string archDir = GetArchDirName(arch); return(Path.Combine(path, archDir)); }
public static string GetNdkToolPrefix(string androidNdkPath, AndroidTargetArch arch, int apiLevel) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkToolPrefix(androidNdkPath, arch)); } var path = GetNdkTool(androidNdkPath, arch, "as", apiLevel); if (path != null) { path = path.Substring(0, path.LastIndexOf("-") + 1); } return(path); }
public static string GetNdkPlatformLibPath(string androidNdkPath, AndroidTargetArch arch, int apiLevel) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkPlatformLibPath(androidNdkPath, arch, apiLevel)); } string lib = arch == AndroidTargetArch.X86_64 ? "lib64" : "lib"; string path = Path.Combine(androidNdkPath, "platforms", $"android-{apiLevel}", $"arch-{GetPlatformArch (arch)}", "usr", lib); if (!Directory.Exists(path)) { throw new InvalidOperationException($"Platform library directory for target {arch} and API Level {apiLevel} was not found. Expected path is \"{path}\""); } return(path); }
public static string GetNdkPlatformIncludePath(string androidNdkPath, AndroidTargetArch arch, int apiLevel) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkPlatformIncludePath(androidNdkPath, arch, apiLevel)); } string path = GetUnifiedHeadersPath(androidNdkPath); if (Directory.Exists(path)) { return(path); } throw new InvalidOperationException($"Android include path not found. Tried: {path}"); }
public static int GetMinimumApiLevelFor(AndroidTargetArch arch, string androidNdkPath) { if (!UsingClangNDK) { return(NdkUtilOld.GetMinimumApiLevelFor(arch, androidNdkPath)); } int minValue = 0; string archName = GetPlatformArch(arch); if (!XABuildConfig.ArchAPILevels.TryGetValue(archName, out minValue)) { throw new InvalidOperationException($"Unable to determine minimum API level for architecture {arch}"); } return(minValue); }
public static bool ValidateNdkPlatform(Action <string> logMessage, Action <string, string> logError, string ndkPath, AndroidTargetArch arch, bool enableLLVM) { if (!UsingClangNDK) { return(NdkUtilOld.ValidateNdkPlatform(logMessage, logError, ndkPath, arch, enableLLVM)); } // Check that we have a compatible NDK version for the targeted ABIs. Version ndkVersion; bool hasNdkVersion = GetNdkToolchainRelease(ndkPath, out ndkVersion); if (hasNdkVersion && ndkVersion.Major < 19) { logMessage( "The detected Android NDK version is incompatible with this version of Xamarin.Android, " + "please upgrade to NDK r19 or newer."); } return(true); }
static string GetPlatformArch(AndroidTargetArch arch) { if (!UsingClangNDK) { return(NdkUtilOld.GetPlatformArch(arch)); } switch (arch) { case AndroidTargetArch.Arm: return("arm"); case AndroidTargetArch.Arm64: return("arm64"); case AndroidTargetArch.X86: return("x86"); case AndroidTargetArch.X86_64: return("x86_64"); } return(null); }
public static bool GetNdkToolchainRelease(string androidNdkPath, out NdkUtilOld.NdkVersion ndkVersion) { return(NdkUtilOld.GetNdkToolchainRelease(androidNdkPath, out ndkVersion)); }
public static string GetNdkTool(string androidNdkPath, AndroidTargetArch arch, string tool, int apiLevel) { if (!UsingClangNDK) { return(NdkUtilOld.GetNdkTool(androidNdkPath, arch, tool)); } string toolchainDir = GetToolchainDir(androidNdkPath); string toolName; bool forCompiler = false; if (String.Compare(tool, "gcc", StringComparison.Ordinal) == 0 || String.Compare(tool, "clang", StringComparison.Ordinal) == 0) { forCompiler = true; toolName = "clang"; } else if (String.Compare(tool, "g++", StringComparison.Ordinal) == 0 || String.Compare(tool, "clang++", StringComparison.Ordinal) == 0) { forCompiler = true; toolName = "clang++"; } else { toolName = tool; } // // NDK r19 bug. // // The llvm toolchain directory contains a selection of shell scripts (both Unix and Windows) // which call `clang/clang++` with different `-target` parameters depending on both the target // architecture and API level. For instance, the clang/clang++ compilers targetting aarch64 on API level // 28 will have the following Unix shell scripts present in the toolchain `bin` directory: // // aarch64-linux-android28-clang // aarch64-linux-android28-clang++ // // However, the Windows version of the NDK has a bug where there is only one Windows // counterpart to the above Unix scripts: // // aarch64-linux-android28-clang.cmd // // This script, despite its name suggesting that it calls `clang.exe` in fact calls // `clang++.exe` which breaks compilation of some C programs (including the code generated by // Mono's mkbundle utility) because `clang++` treats the input as C++. There is no corresponding // `aarch64-linux-android28-clang++.cmd` and so invocation of `clang.exe` becomes harder and, // most certainly, non-standard as far as cross-platform NDK compatibility is concerned. // // The code below tries to rectify the situation by special-casing the compiler tool handling to // return path to the actual .exe instead of the CMD. Unfortunately, the caller of this code // will need to provide the correct parameters for the compilers. // string toolchainPrefix; if (forCompiler) { if (!OS.IsWindows) { toolchainPrefix = $"{GetNdkToolchainPrefix (arch, true)}{apiLevel}"; } else { toolchainPrefix = String.Empty; } } else { toolchainPrefix = GetNdkToolchainPrefix(arch, false); } string extension = OS.IsWindows ? ".exe" : String.Empty; if (forCompiler && OS.IsWindows) { toolName = $"{toolName}{extension}"; } else { toolName = $"{toolchainPrefix}-{toolName}{extension}"; } string binDir = Path.Combine(toolchainDir, "bin"); string toolExe = MonoAndroidHelper.GetExecutablePath(binDir, toolName); string toolPath = Path.Combine(binDir, toolExe); if (File.Exists(toolPath)) { return(toolPath); } Diagnostic.Error(5105, Properties.Resources.XA5105, toolName, arch, toolchainDir); return(null); }