Exemple #1
0
 static string GetNdkToolchainLibraryDir(string binDir, AndroidTargetArch arch)
 {
     return(GetNdkToolchainLibraryDir(binDir, NdkUtil.GetArchDirName(arch)));
 }
Exemple #2
0
        IEnumerable <Config> GetAotConfigs()
        {
            if (!Directory.Exists(AotOutputDirectory))
            {
                Directory.CreateDirectory(AotOutputDirectory);
            }

            var sdkBinDirectory = MonoAndroidHelper.GetOSBinPath();

            foreach (var abi in SupportedAbis)
            {
                string            aotCompiler = "";
                string            outdir      = "";
                string            mtriple     = "";
                AndroidTargetArch arch;

                switch (abi)
                {
                case "armeabi-v7a":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-arm");
                    outdir      = Path.Combine(AotOutputDirectory, "armeabi-v7a");
                    mtriple     = "armv7-linux-gnueabi";
                    arch        = AndroidTargetArch.Arm;
                    break;

                case "arm64":
                case "arm64-v8a":
                case "aarch64":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-arm64");
                    outdir      = Path.Combine(AotOutputDirectory, "arm64-v8a");
                    mtriple     = "aarch64-linux-android";
                    arch        = AndroidTargetArch.Arm64;
                    break;

                case "x86":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-x86");
                    outdir      = Path.Combine(AotOutputDirectory, "x86");
                    mtriple     = "i686-linux-android";
                    arch        = AndroidTargetArch.X86;
                    break;

                case "x86_64":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-x86_64");
                    outdir      = Path.Combine(AotOutputDirectory, "x86_64");
                    mtriple     = "x86_64-linux-android";
                    arch        = AndroidTargetArch.X86_64;
                    break;

                // case "mips":
                default:
                    throw new Exception("Unsupported Android target architecture ABI: " + abi);
                }

                if (!NdkUtil.ValidateNdkPlatform(Log, AndroidNdkDirectory, arch, enableLLVM:EnableLLVM))
                {
                    yield return(Config.Invalid);

                    yield break;
                }

                if (!ValidateAotConfiguration(Log, arch, EnableLLVM))
                {
                    yield return(Config.Invalid);

                    yield break;
                }

                outdir = Path.GetFullPath(outdir);
                if (!Directory.Exists(outdir))
                {
                    Directory.CreateDirectory(outdir);
                }

                int    level         = GetNdkApiLevel(AndroidNdkDirectory, AndroidApiLevel, arch);
                string toolPrefix    = NdkUtil.GetNdkToolPrefix(AndroidNdkDirectory, arch, level);
                var    toolchainPath = toolPrefix.Substring(0, toolPrefix.LastIndexOf(Path.DirectorySeparatorChar));
                var    ldFlags       = string.Empty;
                if (EnableLLVM)
                {
                    string androidLibPath = string.Empty;
                    try {
                        androidLibPath = NdkUtil.GetNdkPlatformLibPath(AndroidNdkDirectory, arch, level);
                    } catch (InvalidOperationException ex) {
                        Diagnostic.Error(5101, ex.Message);
                    }

                    string toolchainLibDir;
                    if (NdkUtil.UsingClangNDK)
                    {
                        toolchainLibDir = GetNdkToolchainLibraryDir(toolchainPath, arch);
                    }
                    else
                    {
                        toolchainLibDir = GetNdkToolchainLibraryDir(toolchainPath);
                    }

                    var libs = new List <string>();
                    if (NdkUtil.UsingClangNDK)
                    {
                        libs.Add($"-L{GetShortPath (toolchainLibDir)}");
                        libs.Add($"-L{GetShortPath (androidLibPath)}");

                        if (arch == AndroidTargetArch.Arm)
                        {
                            // Needed for -lunwind to work
                            string compilerLibDir = Path.Combine(toolchainPath, "..", "sysroot", "usr", "lib", NdkUtil.GetArchDirName(arch));
                            libs.Add($"-L{GetShortPath (compilerLibDir)}");
                        }
                    }

                    libs.Add(GetShortPath(Path.Combine(toolchainLibDir, "libgcc.a")));
                    libs.Add(GetShortPath(Path.Combine(androidLibPath, "libc.so")));
                    libs.Add(GetShortPath(Path.Combine(androidLibPath, "libm.so")));

                    ldFlags = string.Join(";", libs);
                }

                foreach (var assembly in ResolvedAssemblies)
                {
                    string outputFile = Path.Combine(outdir, string.Format("libaot-{0}.so",
                                                                           Path.GetFileName(assembly.ItemSpec)));

                    string seqpointsFile = Path.Combine(outdir, string.Format("{0}.msym",
                                                                              Path.GetFileName(assembly.ItemSpec)));

                    string tempDir = Path.Combine(outdir, Path.GetFileName(assembly.ItemSpec));
                    if (!Directory.Exists(tempDir))
                    {
                        Directory.CreateDirectory(tempDir);
                    }

                    List <string> aotOptions = new List <string> ();

                    if (Profiles != null && Profiles.Length > 0)
                    {
                        aotOptions.Add("profile-only");
                        foreach (var p in Profiles)
                        {
                            var fp = Path.GetFullPath(p.ItemSpec);
                            aotOptions.Add($"profile={GetShortPath (fp)}");
                        }
                    }
                    if (!string.IsNullOrEmpty(AotAdditionalArguments))
                    {
                        aotOptions.Add(AotAdditionalArguments);
                    }
                    if (sequencePointsMode == SequencePointsMode.Offline)
                    {
                        aotOptions.Add("msym-dir=" + GetShortPath(outdir));
                    }
                    if (AotMode != AotMode.Normal)
                    {
                        aotOptions.Add(AotMode.ToString().ToLowerInvariant());
                    }

                    aotOptions.Add("outfile=" + GetShortPath(outputFile));
                    aotOptions.Add("asmwriter");
                    aotOptions.Add("mtriple=" + mtriple);
                    aotOptions.Add("tool-prefix=" + GetShortPath(toolPrefix));
                    aotOptions.Add("ld-flags=" + ldFlags);
                    aotOptions.Add("llvm-path=" + GetShortPath(sdkBinDirectory));
                    aotOptions.Add("temp-path=" + GetShortPath(tempDir));

                    string aotOptionsStr = (EnableLLVM ? "--llvm " : "") + "--aot=" + string.Join(",", aotOptions);

                    if (!string.IsNullOrEmpty(ExtraAotOptions))
                    {
                        aotOptionsStr += (aotOptions.Count > 0 ? "," : "") + ExtraAotOptions;
                    }

                    // Due to a Monodroid MSBuild bug we can end up with paths to assemblies that are not in the intermediate
                    // assembly directory (typically obj/assemblies). This can lead to problems with the Mono loader not being
                    // able to find their dependency laters, since framework assemblies are stored in different directories.
                    // This can happen when linking is disabled (AndroidLinkMode=None). Workaround this problem by resolving
                    // the paths to the right assemblies manually.
                    var resolvedPath             = Path.GetFullPath(assembly.ItemSpec);
                    var intermediateAssemblyPath = Path.Combine(IntermediateAssemblyDir, Path.GetFileName(assembly.ItemSpec));

                    if (LinkMode.ToLowerInvariant() == "none")
                    {
                        if (!resolvedPath.Contains(IntermediateAssemblyDir) && File.Exists(intermediateAssemblyPath))
                        {
                            resolvedPath = intermediateAssemblyPath;
                        }
                    }

                    var assembliesPath = Path.GetFullPath(Path.GetDirectoryName(resolvedPath));
                    var assemblyPath   = QuoteFileName(Path.GetFullPath(resolvedPath));

                    yield return(new Config(assembliesPath, QuoteFileName(aotCompiler), aotOptionsStr, assemblyPath, outputFile));
                }
            }
        }
Exemple #3
0
        IEnumerable <Config> GetAotConfigs()
        {
            if (!Directory.Exists(AotOutputDirectory))
            {
                Directory.CreateDirectory(AotOutputDirectory);
            }

            var sdkBinDirectory = MonoAndroidHelper.GetOSBinPath();

            foreach (var abi in SupportedAbis)
            {
                string            aotCompiler = "";
                string            outdir      = "";
                string            mtriple     = "";
                AndroidTargetArch arch;

                switch (abi)
                {
                case "armeabi-v7a":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-arm");
                    outdir      = Path.Combine(AotOutputDirectory, "armeabi-v7a");
                    mtriple     = "armv7-linux-gnueabi";
                    arch        = AndroidTargetArch.Arm;
                    break;

                case "arm64":
                case "arm64-v8a":
                case "aarch64":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-arm64");
                    outdir      = Path.Combine(AotOutputDirectory, "arm64-v8a");
                    mtriple     = "aarch64-linux-android";
                    arch        = AndroidTargetArch.Arm64;
                    break;

                case "x86":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-x86");
                    outdir      = Path.Combine(AotOutputDirectory, "x86");
                    mtriple     = "i686-linux-android";
                    arch        = AndroidTargetArch.X86;
                    break;

                case "x86_64":
                    aotCompiler = Path.Combine(sdkBinDirectory, "cross-x86_64");
                    outdir      = Path.Combine(AotOutputDirectory, "x86_64");
                    mtriple     = "x86_64-linux-android";
                    arch        = AndroidTargetArch.X86_64;
                    break;

                // case "mips":
                default:
                    throw new Exception("Unsupported Android target architecture ABI: " + abi);
                }

                if (EnableLLVM && !NdkUtil.ValidateNdkPlatform(LogMessage, LogCodedError, AndroidNdkDirectory, arch, enableLLVM:EnableLLVM))
                {
                    yield return(Config.Invalid);

                    yield break;
                }

                outdir = Path.GetFullPath(outdir);
                if (!Directory.Exists(outdir))
                {
                    Directory.CreateDirectory(outdir);
                }

                // dont use a full path if the outdir is withing the WorkingDirectory.
                if (outdir.StartsWith(WorkingDirectory, StringComparison.InvariantCultureIgnoreCase))
                {
                    outdir = outdir.Replace(WorkingDirectory + Path.DirectorySeparatorChar, string.Empty);
                }

                int    level      = 0;
                string toolPrefix = EnableLLVM
                                        ? NdkUtil.GetNdkToolPrefix(AndroidNdkDirectory, arch, level = GetNdkApiLevel(AndroidNdkDirectory, AndroidApiLevel, arch))
                                        : Path.Combine(AndroidBinUtilsDirectory, $"{NdkUtil.GetArchDirName (arch)}-");
                var toolchainPath = toolPrefix.Substring(0, toolPrefix.LastIndexOf(Path.DirectorySeparatorChar));
                var ldFlags       = string.Empty;
                if (EnableLLVM)
                {
                    if (string.IsNullOrEmpty(AndroidNdkDirectory))
                    {
                        yield return(Config.Invalid);

                        yield break;
                    }

                    string androidLibPath = string.Empty;
                    try {
                        androidLibPath = NdkUtil.GetNdkPlatformLibPath(AndroidNdkDirectory, arch, level);
                    } catch (InvalidOperationException ex) {
                        Diagnostic.Error(5101, ex.Message);
                    }

                    string toolchainLibDir;
                    if (NdkUtil.UsingClangNDK)
                    {
                        toolchainLibDir = GetNdkToolchainLibraryDir(toolchainPath, arch);
                    }
                    else
                    {
                        toolchainLibDir = GetNdkToolchainLibraryDir(toolchainPath);
                    }

                    var libs = new List <string>();
                    if (NdkUtil.UsingClangNDK)
                    {
                        libs.Add($"-L{toolchainLibDir}");
                        libs.Add($"-L{androidLibPath}");

                        if (arch == AndroidTargetArch.Arm)
                        {
                            // Needed for -lunwind to work
                            string compilerLibDir = Path.Combine(toolchainPath, "..", "sysroot", "usr", "lib", NdkUtil.GetArchDirName(arch));
                            libs.Add($"-L{compilerLibDir}");
                        }
                    }

                    libs.Add($"\\\"{Path.Combine (toolchainLibDir, "libgcc.a")}\\\"");
                    libs.Add($"\\\"{Path.Combine (androidLibPath, "libc.so")}\\\"");
                    libs.Add($"\\\"{Path.Combine (androidLibPath, "libm.so")}\\\"");

                    ldFlags = string.Join(";", libs);
                }

                string ldName = String.Empty;
                if (EnableLLVM)
                {
                    ldName = NdkUtil.GetNdkTool(AndroidNdkDirectory, arch, "ld", level);
                    if (!String.IsNullOrEmpty(ldName))
                    {
                        ldName = Path.GetFileName(ldName);
                        if (ldName.IndexOf('-') >= 0)
                        {
                            ldName = ldName.Substring(ldName.LastIndexOf("-") + 1);
                        }
                    }
                }
                else
                {
                    ldName = "ld";
                }

                foreach (var assembly in ResolvedAssemblies)
                {
                    string outputFile = Path.Combine(outdir, string.Format("libaot-{0}.so",
                                                                           Path.GetFileName(assembly.ItemSpec)));

                    string seqpointsFile = Path.Combine(outdir, string.Format("{0}.msym",
                                                                              Path.GetFileName(assembly.ItemSpec)));

                    string tempDir = Path.Combine(outdir, Path.GetFileName(assembly.ItemSpec));
                    if (!Directory.Exists(tempDir))
                    {
                        Directory.CreateDirectory(tempDir);
                    }

                    List <string> aotOptions = new List <string> ();

                    if (Profiles != null && Profiles.Length > 0)
                    {
                        aotOptions.Add("profile-only");
                        foreach (var p in Profiles)
                        {
                            var fp = Path.GetFullPath(p.ItemSpec);
                            aotOptions.Add($"profile={fp}");
                        }
                    }
                    if (!string.IsNullOrEmpty(AotAdditionalArguments))
                    {
                        aotOptions.Add(AotAdditionalArguments);
                    }
                    if (sequencePointsMode == SequencePointsMode.Offline)
                    {
                        aotOptions.Add($"msym-dir={outdir}");
                    }
                    if (AotMode != AotMode.Normal)
                    {
                        aotOptions.Add(AotMode.ToString().ToLowerInvariant());
                    }

                    aotOptions.Add($"outfile={outputFile}");
                    aotOptions.Add("asmwriter");
                    aotOptions.Add($"mtriple={mtriple}");
                    aotOptions.Add($"tool-prefix={toolPrefix}");
                    aotOptions.Add($"llvm-path={sdkBinDirectory}");
                    aotOptions.Add($"temp-path={tempDir}");

                    if (!String.IsNullOrEmpty(ldName))
                    {
                        // MUST be before `ld-flags`, otherwise Mono fails to parse it on Windows
                        aotOptions.Add($"ld-name={ldName}");
                    }

                    aotOptions.Add($"ld-flags={ldFlags}");

                    // we need to quote the entire --aot arguments here to make sure it is parsed
                    // on windows as one argument. Otherwise it will be split up into multiple
                    // values, which wont work.
                    string aotOptionsStr = (EnableLLVM ? "--llvm " : "") + $"\"--aot={string.Join (",", aotOptions)}\"";

                    if (!string.IsNullOrEmpty(ExtraAotOptions))
                    {
                        aotOptionsStr += (aotOptions.Count > 0 ? " " : "") + ExtraAotOptions;
                    }

                    // Due to a Monodroid MSBuild bug we can end up with paths to assemblies that are not in the intermediate
                    // assembly directory (typically obj/assemblies). This can lead to problems with the Mono loader not being
                    // able to find their dependency laters, since framework assemblies are stored in different directories.
                    // This can happen when linking is disabled (AndroidLinkMode=None). Workaround this problem by resolving
                    // the paths to the right assemblies manually.
                    var resolvedPath             = Path.GetFullPath(assembly.ItemSpec);
                    var intermediateAssemblyPath = Path.Combine(IntermediateAssemblyDir, Path.GetFileName(assembly.ItemSpec));

                    if (LinkMode.ToLowerInvariant() == "none")
                    {
                        if (!resolvedPath.Contains(IntermediateAssemblyDir) && File.Exists(intermediateAssemblyPath))
                        {
                            resolvedPath = intermediateAssemblyPath;
                        }
                    }

                    var assembliesPath = Path.GetFullPath(Path.GetDirectoryName(resolvedPath));
                    var assemblyPath   = Path.GetFullPath(resolvedPath);

                    yield return(new Config(assembliesPath, aotCompiler, aotOptionsStr, assemblyPath, outputFile, Path.Combine(tempDir, "response.txt")));
                }
            }
        }