Exemple #1
0
        public static void AddRange(this List <BundleItem> list, List <BclFile> bclFiles)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }

            if (bclFiles == null)
            {
                throw new ArgumentNullException(nameof(bclFiles));
            }

            foreach (BclFile bf in bclFiles)
            {
                if (bf == null)
                {
                    continue;
                }

                // BCL file's *destination* location is our *source* path
                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(bf);
                list.Add(destFilePath);
                if (bf.ExcludeDebugSymbols || !File.Exists(debugSymbolsDestPath))
                {
                    continue;
                }
                list.Add(debugSymbolsDestPath);
            }
        }
Exemple #2
0
        public static void AddRange(this List <BundleItem> list, List <MonoUtilityFile> muFiles)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }

            if (muFiles == null)
            {
                throw new ArgumentNullException(nameof(muFiles));
            }

            foreach (MonoUtilityFile muf in muFiles)
            {
                if (muf == null)
                {
                    continue;
                }

                // MU file's *destination* location is our *source* path
                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(muf);
                list.Add(destFilePath);
                if (muf.IgnoreDebugInfo || String.IsNullOrEmpty(debugSymbolsDestPath))
                {
                    continue;
                }
                list.Add(debugSymbolsDestPath);
            }
        }
Exemple #3
0
        public static void AddRange(this List <BundleItem> list, List <TestAssembly> testAssemblies)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }

            if (testAssemblies == null)
            {
                throw new ArgumentNullException(nameof(testAssemblies));
            }

            foreach (TestAssembly tasm in testAssemblies)
            {
                if (tasm == null)
                {
                    continue;
                }

                // Test assembly's *destination* location is our *source* path
                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(tasm);
                list.Add(destFilePath);
                if (String.IsNullOrEmpty(debugSymbolsDestPath))
                {
                    continue;
                }
                list.Add(debugSymbolsDestPath);
            }
        }
        void InstallBCLFiles(List <BclFile> files)
        {
            foreach (BclFile bf in files)
            {
                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(bf);

                Utilities.CopyFile(bf.SourcePath, destFilePath);
                if (bf.ExcludeDebugSymbols)
                {
                    continue;
                }
                if (debugSymbolsDestPath == null)
                {
                    Log.DebugLine($"Debug symbols not found for BCL file {bf.Name} ({bf.Type})");
                    continue;
                }

                if (!File.Exists(bf.DebugSymbolsPath))
                {
                    Log.DebugLine($"Debug symbols file does not exist: {bf.DebugSymbolsPath}");
                    continue;
                }

                Utilities.CopyFile(bf.DebugSymbolsPath, debugSymbolsDestPath);
            }
        }
Exemple #5
0
        bool InstallUtilities(Context context)
        {
            string destDir = MonoRuntimesHelpers.UtilitiesDestinationDir;

            Utilities.CreateDirectory(destDir);

            string managedRuntime     = context.Properties.GetRequiredValue(KnownProperties.ManagedRuntime);
            bool   haveManagedRuntime = !String.IsNullOrEmpty(managedRuntime);
            string remapper           = Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, context.Properties.GetRequiredValue(KnownProperties.RemapAssemblyRefToolExecutable));
            string targetCecil        = Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, Path.Combine(Configurables.Paths.BuildBinDir, "Xamarin.Android.Cecil.dll"));

            StatusStep(context, "Installing runtime utilities");
            foreach (MonoUtilityFile muf in allRuntimes.UtilityFilesToInstall)
            {
                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(muf);
                Utilities.CopyFile(muf.SourcePath, destFilePath);
                if (!muf.IgnoreDebugInfo)
                {
                    if (!String.IsNullOrEmpty(debugSymbolsDestPath))
                    {
                        Utilities.CopyFile(muf.DebugSymbolsPath, debugSymbolsDestPath);
                    }
                    else
                    {
                        Log.DebugLine($"Debug symbols not found for utility file {Path.GetFileName (muf.SourcePath)}");
                    }
                }

                if (!muf.RemapCecil)
                {
                    continue;
                }

                string relDestFilePath = Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, destFilePath);
                StatusSubStep(context, $"Remapping Cecil references for {relDestFilePath}");
                bool result = Utilities.RunCommand(
                    haveManagedRuntime ? managedRuntime : remapper, // command
                    BuildPaths.XamarinAndroidSourceRoot,            // workingDirectory
                    true,                                           // ignoreEmptyArguments

                    // arguments
                    haveManagedRuntime ? remapper : String.Empty,
                    Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, muf.SourcePath),
                    relDestFilePath,
                    "Mono.Cecil",
                    targetCecil);

                if (result)
                {
                    continue;
                }

                Log.ErrorLine($"Failed to remap cecil reference for {destFilePath}");
                return(false);
            }

            return(true);
        }
        List <Runtime> GetEnabledRuntimes(bool enableLogging)
        {
            var enabledRuntimes = new List <Runtime> ();

            if (allRuntimes == null)
            {
                allRuntimes = new Runtimes();
            }
            return(MonoRuntimesHelpers.GetEnabledRuntimes(allRuntimes, enableLogging));
        }
        void EnsureAllSDKHeadersAreIncluded(Context context, Runtimes allRuntimes)
        {
            string topDirTail = Configurables.Paths.MonoSDKRelativeIncludeSourceDir;

            if (!topDirTail.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            {
                topDirTail += Path.DirectorySeparatorChar;
            }

            // Find first enabled runtime - all headers are the same across all runtimes, so we don't care
            // where they come from.
            Runtime runtime = MonoRuntimesHelpers.GetEnabledRuntimes(allRuntimes, enableLogging: false)?.FirstOrDefault();

            if (runtime == null)
            {
                Log.WarningLine("No enabled runtimes (?!)");
                return;
            }

            string runtimeIncludeDirRoot        = Path.Combine(Configurables.Paths.MonoSourceFullPath, MonoRuntimesHelpers.GetRootDir(runtime), Configurables.Paths.MonoSDKRelativeIncludeSourceDir);
            IEnumerable <string> sourceIncludes = Directory.EnumerateFiles(runtimeIncludeDirRoot, "*", SearchOption.AllDirectories);
            var destinationIncludes             = new List <string> ();

            foreach (RuntimeFile rf in allRuntimes.RuntimeFilesToInstall.Where(rf => rf.Type == RuntimeFileType.SdkHeader))
            {
                destinationIncludes.Add(Path.Combine(Configurables.Paths.MonoSourceFullPath, rf.Source(runtime)));
            }

            bool haveDifference = false;

            haveDifference &= ReportDifference(sourceIncludes.Except(destinationIncludes).ToList(), "runtime", "bundle");
            haveDifference &= ReportDifference(destinationIncludes.Except(sourceIncludes).ToList(), "bundle", "runtime");

            if (haveDifference)
            {
                throw new InvalidOperationException("Differences found between the Mono SDK header files shipped in Mono archive and included in Xamarin.Android bundle");
            }

            bool ReportDifference(List <string> diff, string foundIn, string notFoundIn)
            {
                if (diff.Count == 0)
                {
                    return(false);
                }

                Log.ErrorLine($"There are files found in the {foundIn} but not in the {notFoundIn}:");
                foreach (string f in diff)
                {
                    Log.ErrorLine($"  {context.Characters.Bullet} {Utilities.GetRelativePath (runtimeIncludeDirRoot, f)}");
                }
                Log.ErrorLine();
                return(true);
            }
        }
        protected override Task <bool> Execute(Context context)
        {
            List <Runtime> enabledRuntimes = MonoRuntimesHelpers.GetEnabledRuntimes(new Runtimes(), enableLogging: true);

            if (enabledRuntimes.Count == 0)
            {
                Log.StatusLine("No runtimes to build/install");
            }

            return(Task.FromResult(true));
        }
Exemple #9
0
        void InstallBCLFiles(List <BclFile> files)
        {
            foreach (BclFile bf in files)
            {
                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(bf);

                Utilities.CopyFile(bf.SourcePath, destFilePath);
                if (!bf.ExcludeDebugSymbols && !String.IsNullOrEmpty(bf.DebugSymbolsPath) && debugSymbolsDestPath.Length > 0)
                {
                    Utilities.CopyFile(bf.DebugSymbolsPath !, debugSymbolsDestPath);
                }
            }
        }
        async Task <bool> DownloadMonoArchive(Context context)
        {
            if (context.ForceRuntimesBuild)
            {
                Log.StatusLine("Mono runtime rebuild forced, Mono Archive download skipped");
                return(false);
            }

            Log.StatusLine("Checking if all runtime files are present");
            var allRuntimes = new Runtimes();

            if (MonoRuntimesHelpers.AllBundleItemsPresent(allRuntimes))
            {
                // User might have changed the set of ABIs to build, we need to check and rebuild if necessary
                if (!Utilities.AbiChoiceChanged(context))
                {
                    Log.StatusLine("Mono runtimes already present and complete. No need to download or build.");
                    return(true);
                }

                Log.StatusLine("Mono already present, but the choice of ABIs changed since previous build, runtime refresh is necessary");
            }
            Log.Instance.StatusLine($"  {Context.Instance.Characters.Bullet} some files are missing, download/rebuild/reinstall forced");

            bool result = await DownloadAndUpackIfNeeded(
                context,
                "Mono",
                Configurables.Paths.MonoArchiveLocalPath,
                Configurables.Paths.MonoArchiveFileName,
                Configurables.Paths.MonoSDKSOutputDir
                );

            if (!result)
            {
                return(false);
            }

            return(await DownloadAndUpackIfNeeded(
                       context,
                       "Windows Mono",
                       Configurables.Paths.MonoArchiveWindowsLocalPath,
                       Configurables.Paths.MonoArchiveWindowsFileName,
                       Configurables.Paths.BCLWindowsOutputDir
                       ));
        }
Exemple #11
0
        public static void AddRange(this List <BundleItem> list, List <RuntimeFile> runtimeFiles)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }

            if (runtimeFiles == null)
            {
                throw new ArgumentNullException(nameof(runtimeFiles));
            }

            var sharedFiles = new HashSet <string> (StringComparer.Ordinal);

            foreach (Runtime runtime in MonoRuntimesHelpers.GetEnabledRuntimes(new Runtimes(), false))
            {
                foreach (RuntimeFile rtf in runtimeFiles)
                {
                    if (rtf == null)
                    {
                        continue;
                    }

                    // Runtime file's *destination* location is our *source* path
                    (bool skipFile, string _, string destFilePath) = MonoRuntimesHelpers.GetRuntimeFilePaths(runtime, rtf);
                    if (rtf.Shared && sharedFiles.Contains(destFilePath))
                    {
                        continue;
                    }

                    if (skipFile)
                    {
                        continue;
                    }
                    list.Add(destFilePath);

                    if (rtf.Shared)
                    {
                        sharedFiles.Add(destFilePath);
                    }
                }
            }
        }
 static string GetAndroidInputLibDir(Runtime runtime)
 {
     return(Path.Combine(MonoRuntimesHelpers.GetRootDir(runtime), "lib"));
 }
        async Task <bool> InstallRuntimes(Context context, List <Runtime> enabledRuntimes)
        {
            StatusStep(context, "Installing tests");
            foreach (TestAssembly tasm in Runtimes.TestAssemblies)
            {
                string sourceBasePath;

                switch (tasm.TestType)
                {
                case TestAssemblyType.Reference:
                case TestAssemblyType.TestRunner:
                    sourceBasePath = Path.Combine(Configurables.Paths.MonoProfileDir);
                    break;

                case TestAssemblyType.XUnit:
                case TestAssemblyType.NUnit:
                case TestAssemblyType.Satellite:
                    sourceBasePath = Configurables.Paths.BCLTestsSourceDir;
                    break;

                default:
                    throw new InvalidOperationException($"Unsupported test assembly type: {tasm.TestType}");
                }

                (string destFilePath, string debugSymbolsDestPath) = MonoRuntimesHelpers.GetDestinationPaths(tasm);
                CopyFile(Path.Combine(sourceBasePath, tasm.Name), destFilePath);
                if (debugSymbolsDestPath != null)
                {
                    CopyFile(Path.Combine(sourceBasePath, Utilities.GetDebugSymbolsPath(tasm.Name)), debugSymbolsDestPath);
                }
            }

            StatusSubStep(context, "Creating BCL tests archive");
            Utilities.DeleteFileSilent(MonoRuntimesHelpers.BCLTestsArchivePath);
            var sevenZip = new SevenZipRunner(context);

            if (!await sevenZip.Zip(MonoRuntimesHelpers.BCLTestsArchivePath, MonoRuntimesHelpers.BCLTestsDestinationDir, new List <string> {
                "."
            }))
            {
                Log.ErrorLine("BCL tests archive creation failed, see the log files for details.");
                return(false);
            }

            StatusStep(context, "Installing runtimes");
            foreach (Runtime runtime in enabledRuntimes)
            {
                StatusSubStep(context, $"Installing {runtime.Flavor} runtime {runtime.Name}");

                string src, dst;
                bool   skipFile;
                foreach (RuntimeFile rtf in allRuntimes.RuntimeFilesToInstall)
                {
                    if (rtf.Shared && rtf.AlreadyCopied)
                    {
                        continue;
                    }

                    (skipFile, src, dst) = MonoRuntimesHelpers.GetRuntimeFilePaths(runtime, rtf);
                    if (skipFile)
                    {
                        continue;
                    }

                    CopyFile(src, dst);
                    if (!StripFile(runtime, rtf, dst))
                    {
                        return(false);
                    }

                    if (rtf.Shared)
                    {
                        rtf.AlreadyCopied = true;
                    }
                }
            }

            return(true);

            bool StripFile(Runtime runtime, RuntimeFile rtf, string filePath)
            {
                if (rtf.Type != RuntimeFileType.StrippableBinary)
                {
                    return(true);
                }

                var monoRuntime = runtime.As <MonoRuntime> ();

                if (monoRuntime == null || !monoRuntime.CanStripNativeLibrary || !rtf.Strip)
                {
                    return(true);
                }

                if (String.IsNullOrEmpty(monoRuntime.Strip))
                {
                    Log.WarningLine($"Binary stripping impossible, runtime {monoRuntime.Name} doesn't define the strip command");
                    return(true);
                }

                bool result;

                if (!String.IsNullOrEmpty(monoRuntime.StripFlags))
                {
                    result = Utilities.RunCommand(monoRuntime.Strip, monoRuntime.StripFlags, filePath);
                }
                else
                {
                    result = Utilities.RunCommand(monoRuntime.Strip, filePath);
                }

                if (result)
                {
                    return(true);
                }

                Log.ErrorLine($"Failed to strip the binary file {filePath}, see logs for error details");
                return(false);
            }

            void CopyFile(string src, string dest)
            {
                if (!CheckFileExists(src, true))
                {
                    return;
                }

                Utilities.CopyFile(src, dest);
            }
        }
Exemple #14
0
        async Task <bool> DownloadMonoArchive(Context context)
        {
            if (context.ForceRuntimesBuild)
            {
                Log.StatusLine("Mono runtime rebuild forced, Mono Archive download skipped");
                return(false);
            }

            Log.StatusLine("Checking if all runtime files are present");
            var allRuntimes = new Runtimes();

            if (MonoRuntimesHelpers.AreRuntimeItemsInstalled(context, allRuntimes))
            {
                // User might have changed the set of ABIs to build, we need to check and rebuild if necessary
                if (!Utilities.AbiChoiceChanged(context))
                {
                    Log.StatusLine("Mono runtimes already present and complete. No need to download or build.");
                    return(true);
                }

                Log.StatusLine("Mono already present, but the choice of ABIs changed since previous build, runtime refresh is necessary");
            }
            Log.Instance.StatusLine($"  {Context.Instance.Characters.Bullet} some files are missing, download and extraction required");

            string localPath, archiveFileName;

            if (string.IsNullOrEmpty(context.MonoArchiveCustomUrl))
            {
                localPath       = Configurables.Paths.MonoArchiveLocalPath;
                archiveFileName = Configurables.Paths.MonoArchiveFileName;
            }
            else
            {
                var uri = new Uri(context.MonoArchiveCustomUrl);
                archiveFileName = Path.GetFileName(uri.LocalPath);
                localPath       = Path.Combine(context.Properties.GetRequiredValue(KnownProperties.AndroidToolchainCacheDirectory), archiveFileName);
            }

            bool result = false;

            for (uint i = 0; i < 3; i++)
            {
                result = await DownloadAndUpackIfNeeded(
                    context,
                    "Mono",
                    context.MonoArchiveCustomUrl,
                    localPath,
                    archiveFileName,
                    Configurables.Paths.MonoSDKSOutputDir
                    );

                if (result)
                {
                    break;
                }
            }

            if (!result)
            {
                return(false);
            }

            for (uint i = 0; i < 3; i++)
            {
                result = await DownloadAndUpackIfNeeded(
                    context,
                    "Windows Mono",
                    customUrl : String.Empty,
                    localPath : Configurables.Paths.MonoArchiveWindowsLocalPath,
                    archiveFileName : Configurables.Paths.MonoArchiveWindowsFileName,
                    destinationDirectory : Configurables.Paths.BCLWindowsOutputDir
                    );

                if (result)
                {
                    break;
                }
            }

            return(result);
        }
Exemple #15
0
        protected override async Task <bool> Execute(Context context)
        {
            if (context.ForceRuntimesBuild)
            {
                if (osSupportsMonoBuild)
                {
                    Log.InfoLine("Rebuilding Mono runtimes as requested");
                    return(false);
                }

                Log.InfoLine($"Forced Mono runtimes rebuild requested but rebuilding on {context.OS.Type} is currently not supported.");
            }

            string localPackagePath = Configurables.Paths.BundleArchivePath;

            Log.DebugLine($"Local bundle path: {localPackagePath}");

            if (await Utilities.VerifyArchive(localPackagePath))
            {
                Log.StatusLine("Xamarin.Android Bundle archive already downloaded and valid");
            }
            else
            {
                if (!String.IsNullOrEmpty(context.XABundlePath))
                {
                    // User indicated they wanted to use a specific bundle that's supposed to be on disk. It's not (or
                    // it's invalid) and that means we have no way of getting it - we can't download the default one
                    // since that was not the intention behind overriding the location. Thus, we error out.
                    Log.DebugLine($"Bundle directory from command line: {context.XABundlePath}");
                    throw new InvalidOperationException($"Xamarin.Android bundle indicated on the command line does not exist ({context.XABundlePath})");
                }

                var bundleUrl = new Uri(BundleUriPrefix, BundleFileName);

                Log.StatusLine("Bundle URL: ", $"{bundleUrl}", tailColor: ConsoleColor.Cyan);

                HttpStatusCode status;
                bool           success;
                ulong          size;

                (success, size, status) = await Utilities.GetDownloadSizeWithStatus(bundleUrl);

                if (!success)
                {
                    if (status == HttpStatusCode.NotFound)
                    {
                        if (osSupportsMonoBuild)
                        {
                            Log.StatusLine("   not found, will need to rebuild");
                        }
                        else
                        {
                            Log.ErrorLine($"   not found, rebuilding on {context.OS.Type} is not currently supported");
                        }
                        return(false);
                    }

                    if (String.IsNullOrEmpty(bundle404Message))
                    {
                        throw new InvalidOperationException($"Failed to access bundle at {bundleUrl} (HTTP status: {status})");
                    }
                    else
                    {
                        throw new InvalidOperationException(bundle404Message);
                    }
                }

                DownloadStatus downloadStatus = Utilities.SetupDownloadStatus(context, size, context.InteractiveSession);
                Log.StatusLine($"  {context.Characters.Link} {bundleUrl}", ConsoleColor.White);
                await Download(context, bundleUrl, localPackagePath, "Xamarin.Android Bundle", Path.GetFileName(localPackagePath), downloadStatus);

                if (!File.Exists(localPackagePath))
                {
                    Log.ErrorLine($"Download of Xamarin.Android Bundle from {bundleUrl} failed.");
                    return(false);
                }
            }

            Log.StatusLine($"Unpacking bundle to {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, Configurables.Paths.BundleInstallDir)}");
            string tempDir = $"{Configurables.Paths.BundleInstallDir}-bundle.temp";

            try {
                if (!await Utilities.Unpack(localPackagePath, tempDir, cleanDestinatioBeforeUnpacking: true))
                {
                    Log.WarningLine("Failed to unpack bundle, will need to rebuild");
                    return(false);
                }

                Log.DebugLine($"Moving unpacked bundle from {tempDir} to {Configurables.Paths.BundleInstallDir}");
                Utilities.MoveDirectoryContentsRecursively(tempDir, Configurables.Paths.BundleInstallDir, resetFileTimestamp: true, ignoreDeletionErrors: true);
            } finally {
                Utilities.DeleteDirectorySilent(tempDir);
            }

            string managedRuntime     = context.Properties.GetRequiredValue(KnownProperties.ManagedRuntime);
            bool   haveManagedRuntime = !String.IsNullOrEmpty(managedRuntime);

            if (!await Utilities.BuildRemapRef(context, haveManagedRuntime, managedRuntime))
            {
                return(false);
            }

            Utilities.PropagateXamarinAndroidCecil(context);

            if (String.IsNullOrEmpty(context.XABundleCopyDir))
            {
                return(HaveEverything());
            }

            string destPackagePath = Path.Combine(context.XABundleCopyDir, Path.GetFileName(localPackagePath));

            Log.DebugLine($"Copy of the XA bundle was requested to be created at {destPackagePath}");
            if (Utilities.FileExists(destPackagePath))
            {
                Log.DebugLine("Bundle copy already exists");
                return(HaveEverything());
            }

            // Utilities.FileExists above will return `false` for a dangling symlink at `destPackagePath`, doesn't hurt
            // to remove it here just in case
            Utilities.DeleteFileSilent(destPackagePath);
            Utilities.CopyFile(localPackagePath, destPackagePath);

            return(HaveEverything());

            bool HaveEverything()
            {
                bool ret = MonoRuntimesHelpers.AllBundleItemsPresent(new Runtimes());

                if (!ret)
                {
                    Log.Instance.StatusLine($"Some bundle files are missing, download/rebuild/reinstall forced");
                }
                return(ret);
            }
        }
Exemple #16
0
        protected override async Task <bool> Execute(Context context)
        {
            List <Runtime> enabledRuntimes = GetEnabledRuntimes(enableLogging: false);

            if (enabledRuntimes.Count == 0)
            {
                Log.StatusLine("No runtimes to build/install");
                return(true);
            }

            if (!context.MonoArchiveDownloaded)
            {
                // https://github.com/xamarin/xamarin-android/pull/3816
                throw new NotImplementedException("Unable to build mono runtimes from sources.");
            }

            Log.StatusLine("Checking if all runtime files are present");
            var allRuntimes = new Runtimes();

            if (MonoRuntimesHelpers.AreRuntimeItemsInstalled(context, allRuntimes))
            {
                // User might have changed the set of ABIs to build, we need to check and rebuild if necessary
                if (!Utilities.AbiChoiceChanged(context))
                {
                    Log.StatusLine("Mono runtimes already present and complete. No need to download or build.");
                    return(true);
                }

                Log.StatusLine("Mono already present, but the choice of ABIs changed since previous build, runtime refresh is necessary");
            }
            Log.Instance.StatusLine($"  {Context.Instance.Characters.Bullet} some files are missing, rebuild/reinstall forced");

            CleanupBeforeInstall();
            Log.StatusLine();

            string managedRuntime     = context.Properties.GetRequiredValue(KnownProperties.ManagedRuntime);
            bool   haveManagedRuntime = !String.IsNullOrEmpty(managedRuntime);

            if (!await ConjureXamarinCecilAndRemapRef(context, haveManagedRuntime, managedRuntime))
            {
                return(false);
            }

            if (!await InstallRuntimes(context, enabledRuntimes))
            {
                return(false);
            }

            if (!InstallBCL(context))
            {
                return(false);
            }

            if (!InstallUtilities(context, haveManagedRuntime, managedRuntime))
            {
                return(false);
            }

            Utilities.PropagateXamarinAndroidCecil(context);

            return(true);
        }
        static string GetCrossRuntimeOutputSourcePath(Runtime runtime)
        {
            var crossRuntime = EnsureRuntimeType <MonoCrossRuntime> (runtime, "cross compilation");

            return(Path.Combine(MonoRuntimesHelpers.GetRootDir(runtime), "bin", $"{crossRuntime.ExePrefix}mono-sgen{crossRuntime.ExeSuffix}"));
        }