Exemplo n.º 1
0
        public static bool ValidateNdkPlatform(TaskLoggingHelper log, string ndkPath, AndroidTargetArch arch, bool enableLLVM)
        {
            // Check that we have a compatible NDK version for the targeted ABIs.
            NdkUtil.NdkVersion ndkVersion;
            bool hasNdkVersion = NdkUtil.GetNdkToolchainRelease(ndkPath, out ndkVersion);

            if (NdkUtil.IsNdk64BitArch(arch) && hasNdkVersion && ndkVersion.Version < 10)
            {
                log.LogMessage(MessageImportance.High,
                               "The detected Android NDK version is incompatible with the targeted 64-bit architecture, " +
                               "please upgrade to NDK r10 or newer.");
            }

            // NDK r10d is buggy and cannot link x86_64 ABI shared libraries because they are 32-bits.
            // See https://code.google.com/p/android/issues/detail?id=161421
            if (enableLLVM && ndkVersion.Version == 10 && ndkVersion.Revision == "d" && arch == AndroidTargetArch.X86_64)
            {
                log.LogCodedError("XA3004", "Android NDK r10d is buggy and provides an incompatible x86_64 libm.so. " +
                                  "See https://code.google.com/p/android/issues/detail?id=161422.");
                return(false);
            }

            if (enableLLVM && (ndkVersion.Version < 10 || (ndkVersion.Version == 10 && ndkVersion.Revision[0] < 'd')))
            {
                log.LogCodedError("XA3005",
                                  "The detected Android NDK version is incompatible with the targeted LLVM configuration, " +
                                  "please upgrade to NDK r10d or newer.");
            }

            return(true);
        }
Exemplo n.º 2
0
        IEnumerable <Config> GetAotConfigs()
        {
            if (!Directory.Exists(AotOutputDirectory))
            {
                Directory.CreateDirectory(AotOutputDirectory);
            }

            // Check that we have a compatible NDK version for the targeted ABIs.
            NdkUtil.NdkVersion ndkVersion;
            bool hasNdkVersion = NdkUtil.GetNdkToolchainRelease(AndroidNdkDirectory, out ndkVersion);

            var sdkBinDirectory = MonoAndroidHelper.GetOSBinPath();

            var abis = SupportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

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

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

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

                var toolPrefix    = NdkUtil.GetNdkToolPrefix(AndroidNdkDirectory, arch);
                var toolchainPath = toolPrefix.Substring(0, toolPrefix.LastIndexOf(Path.DirectorySeparatorChar));
                var ldFlags       = string.Empty;
                if (EnableLLVM)
                {
                    int level = GetNdkApiLevel(AndroidNdkDirectory, AndroidApiLevel, arch);

                    string androidLibPath = string.Empty;
                    try {
                        androidLibPath = NdkUtil.GetNdkPlatformLibPath(AndroidNdkDirectory, arch, level);
                    } catch (InvalidOperationException ex) {
                        Diagnostic.Error(5101, ex.Message);
                    }
                    var libs = new List <string>()
                    {
                        GetShortPath(Path.Combine(GetNdkToolchainLibraryDir(toolchainPath), "libgcc.a")),
                        GetShortPath(Path.Combine(androidLibPath, "libc.so")),
                        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 (!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));
                }
            }
        }
Exemplo n.º 3
0
        bool DoExecute()
        {
            Log.LogDebugMessage("Aot:", AndroidAotMode);
            Log.LogDebugMessage("  AndroidApiLevel: {0}", AndroidApiLevel);
            Log.LogDebugMessage("  AndroidAotMode: {0}", AndroidAotMode);
            Log.LogDebugMessage("  AndroidSequencePointsMode: {0}", AndroidSequencePointsMode);
            Log.LogDebugMessage("  AndroidNdkDirectory: {0}", AndroidNdkDirectory);
            Log.LogDebugMessage("  AotOutputDirectory: {0}", AotOutputDirectory);
            Log.LogDebugMessage("  EnableLLVM: {0}", EnableLLVM);
            Log.LogDebugMessage("  IntermediateAssemblyDir: {0}", IntermediateAssemblyDir);
            Log.LogDebugMessage("  LinkMode: {0}", LinkMode);
            Log.LogDebugMessage("  SdkBinDirectory: {0}", SdkBinDirectory);
            Log.LogDebugMessage("  SupportedAbis: {0}", SupportedAbis);
            Log.LogDebugTaskItems("  ResolvedAssemblies:", ResolvedAssemblies);
            Log.LogDebugTaskItems("  AdditionalNativeLibraryReferences:", AdditionalNativeLibraryReferences);

            bool hasValidAotMode = GetAndroidAotMode(AndroidAotMode, out AotMode);

            if (!hasValidAotMode)
            {
                Log.LogCodedError("XA3001", "Invalid AOT mode: {0}", AndroidAotMode);
                return(false);
            }

            TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode);

            var nativeLibs = new List <string> ();

            if (!Directory.Exists(AotOutputDirectory))
            {
                Directory.CreateDirectory(AotOutputDirectory);
            }

            // Check that we have a compatible NDK version for the targeted ABIs.
            NdkUtil.NdkVersion ndkVersion;
            bool hasNdkVersion = NdkUtil.GetNdkToolchainRelease(AndroidNdkDirectory, out ndkVersion);

            var abis = SupportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

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

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

                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))
                {
                    return(false);
                }

                if (!ValidateAotConfiguration(Log, arch, EnableLLVM))
                {
                    return(false);
                }

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

                var toolPrefix    = NdkUtil.GetNdkToolPrefix(AndroidNdkDirectory, arch);
                var toolchainPath = toolPrefix.Substring(0, toolPrefix.LastIndexOf(Path.DirectorySeparatorChar));
                var ldFlags       = string.Empty;
                if (EnableLLVM)
                {
                    int level = GetNdkApiLevel(AndroidNdkDirectory, AndroidApiLevel, arch);

                    string androidLibPath = string.Empty;
                    try {
                        androidLibPath = NdkUtil.GetNdkPlatformLibPath(AndroidNdkDirectory, arch, level);
                    } catch (InvalidOperationException ex) {
                        Diagnostic.Error(5101, ex.Message);
                    }
                    var libs = new List <string>()
                    {
                        QuoteFileName(Path.Combine(GetNdkToolchainLibraryDir(toolchainPath), "libgcc.a")),
                        QuoteFileName(Path.Combine(androidLibPath, "libc.so")),
                        QuoteFileName(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 aotOptions = string.Format(
                        "{0}--aot={8}{1}outfile={2},asmwriter,mtriple={3},tool-prefix={4},ld-flags={5},llvm-path={6},temp-path={7}",
                        EnableLLVM ? "--llvm " : string.Empty,
                        AotMode != AotMode.Normal ? string.Format("{0},", AotMode.ToString().ToLowerInvariant()) : string.Empty,
                        QuoteFileName(outputFile),
                        mtriple,
                        QuoteFileName(toolPrefix),
                        ldFlags,
                        QuoteFileName(SdkBinDirectory),
                        QuoteFileName(outdir),
                        sequencePointsMode == SequencePointsMode.Offline ? string.Format("gen-seq-points-file={0},", seqpointsFile) : string.Empty
                        );

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

                    if (!RunAotCompiler(assembliesPath, aotCompiler, aotOptions, assemblyPath))
                    {
                        Log.LogCodedError("XA3001", "Could not AOT the assembly: {0}", assembly.ItemSpec);
                        return(false);
                    }
                    nativeLibs.Add(outputFile);
                }
            }

            NativeLibrariesReferences = nativeLibs.ToArray();

            Log.LogDebugTaskItems("Aot Outputs:");
            Log.LogDebugTaskItems("  NativeLibrariesReferences: ", NativeLibrariesReferences);

            return(true);
        }