Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        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));
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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}");
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
 public static bool GetNdkToolchainRelease(string androidNdkPath, out NdkUtilOld.NdkVersion ndkVersion)
 {
     return(NdkUtilOld.GetNdkToolchainRelease(androidNdkPath, out ndkVersion));
 }
Ejemplo n.º 11
0
        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);
        }