#pragma warning disable CS1998 protected override async Task <bool> Execute(Context context) { // Ignore copying if not installing the NDK if (!dependencyTypeToInstall.HasFlag(AndroidToolchainComponentType.BuildDependency)) { Log.DebugLine("NDK is not being installed, binutils installation skipped."); return(true); } string ndkRoot = context.Properties.GetRequiredValue(KnownProperties.AndroidNdkDirectory); string sourceDirectory = Configurables.Paths.AndroidToolchainBinDirectory; string destinationDirectory = Configurables.Paths.HostBinutilsInstallDir; Log.StatusLine("Copying host binutils:"); foreach (var kvp in Configurables.Defaults.AndroidToolchainPrefixes) { string archPrefix = kvp.Value; foreach (NDKTool ndkTool in Configurables.Defaults.NDKTools) { string sourcePath = context.OS.AppendExecutableExtension(Path.Combine(sourceDirectory, $"{archPrefix}-{ndkTool.Name}")); string destName = ndkTool.DestinationName.Length == 0 ? ndkTool.Name : ndkTool.DestinationName; string destPath = context.OS.AppendExecutableExtension(Path.Combine(destinationDirectory, $"{archPrefix}-{destName}")); Log.Status($" {context.Characters.Bullet} {Path.GetFileName (sourcePath)} "); Log.Status($"{context.Characters.RightArrow}", ConsoleColor.Cyan); Log.StatusLine($" {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, destPath)}"); Utilities.CopyFile(sourcePath, destPath); } } return(true); }
public async Task <bool> Run(string logTag, string sourceDirectory, string workingDirectory, List <string> arguments) { if (String.IsNullOrEmpty(logTag)) { throw new ArgumentException("must not be null or empty", nameof(logTag)); } if (String.IsNullOrEmpty(sourceDirectory)) { throw new ArgumentException("must not be null or empty", nameof(sourceDirectory)); } if (String.IsNullOrEmpty(workingDirectory)) { throw new ArgumentException("must not be null or empty", nameof(workingDirectory)); } var runner = CreateProcessRunner(); AddArguments(runner, arguments); runner.AddQuotedArgument(Utilities.GetRelativePath(workingDirectory, sourceDirectory)); try { return(await RunTool(() => { using (var outputSink = (OutputSink)SetupOutputSink(runner, $"cmake.{logTag}")) { runner.WorkingDirectory = workingDirectory; StartTwiddler(); return runner.Run(); } } )); } finally { StopTwiddler(); } }
#pragma warning disable CS1998 protected override async Task <bool> Execute(Context context) { List <GeneratedFile>?filesToGenerate = GetFilesToGenerate(context); if (filesToGenerate != null && filesToGenerate.Count > 0) { foreach (GeneratedFile gf in filesToGenerate) { if (gf == null) { continue; } Log.Status("Generating "); Log.Status(Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, gf.OutputPath), ConsoleColor.White); if (!String.IsNullOrEmpty(gf.InputPath)) { Log.StatusLine($" {context.Characters.LeftArrow} ", Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, gf.InputPath), leadColor: ConsoleColor.Cyan, tailColor: ConsoleColor.White); } else { Log.StatusLine(); } gf.Generate(context); } } return(true); }
public async Task <bool> Restore(string solutionFilePath) { if (String.IsNullOrEmpty(solutionFilePath)) { throw new ArgumentException("must not be null or empty", nameof(solutionFilePath)); } if (!File.Exists(solutionFilePath)) { throw new InvalidOperationException($"Solution file '{solutionFilePath}' does not exist"); } ProcessRunner runner = CreateProcessRunner("restore"); runner.AddArgument("-Verbosity").AddArgument("detailed"); runner.AddArgument("-NonInteractive"); runner.AddArgument("-ForceEnglishOutput"); runner.AddQuotedArgument(solutionFilePath); try { return(await RunTool(() => { using (TextWriter outputSink = SetupOutputSink(runner, $"nuget-restore.{Path.GetFileName (solutionFilePath)}", "restoring NuGet packages")) { Log.StatusLine($"Solution file: {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, solutionFilePath)}", ConsoleColor.White); runner.WorkingDirectory = Path.GetDirectoryName(solutionFilePath); StartTwiddler(); return runner.Run(); } } )); } finally { StopTwiddler(); } }
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); }
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); } }
#pragma warning disable CS1998 protected override async Task <bool> Execute(Context context) { var runner = new BrewRunner(context); if (!runner.List("libzip", out List <string> lines) || lines == null || lines.Count == 0) { Log.ErrorLine("Failed to retrieve libzip package contents"); return(false); } string libZipPath = null; foreach (string line in lines) { Match match = libZipDylib.Match(line); if (!match.Success) { continue; } libZipPath = line; break; } if (String.IsNullOrEmpty(libZipPath)) { Log.ErrorLine("`libzip` package does not contain the dynamic library"); return(false); } if (!File.Exists(libZipPath)) { Log.ErrorLine($"`libzip` package lists the dynamic library at {libZipPath} but the file does not exist"); return(false); } Log.DebugLine($"`libzip` library found at {libZipPath}"); string destFile = Path.Combine(Configurables.Paths.InstallMSBuildDir, Path.GetFileName(libZipPath)); Log.Status("Installing "); Log.Status(Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, destFile), ConsoleColor.White); Log.StatusLine($" {context.Characters.LeftArrow} ", libZipPath, leadColor: ConsoleColor.Cyan, tailColor: ConsoleColor.White); Utilities.CopyFile(libZipPath, destFile); if (!File.Exists(destFile)) { Log.ErrorLine("Failed to copy the libzip dynamic library."); return(false); } return(true); }
bool FileSetsDiffer(IEnumerable <TestAssembly> assemblies, string directoryPath, string batchName, HashSet <string>?ignoreFiles = null) { List <string> tests = FilesFromDir(directoryPath, ignoreFiles).ToList(); tests.AddRange( FilesFromDir( directoryPath, globPattern: "*.resources.dll", stripPath: false, searchSubdirs: true ).Select(f => Utilities.GetRelativePath(directoryPath, f)) ); return(FileSetsDiffer(ToStringSet(assemblies), tests, batchName)); }
void GenerateMonodroidTargets(Context context, StreamWriter sw) { string sourceDir = Utilities.GetRelativePath(Configurables.Paths.BuildBinDir, Configurables.Paths.MonodroidSourceDir); var commonReplacements = new Dictionary <string, string> (StringComparer.Ordinal) { { "@BUILD_TYPE@", "" }, { "@CONFIGURATION@", "" }, { "@SOURCE_DIRECTORY@", $"$(MSBuildThisFileDirectory){sourceDir}" }, }; var androidRuntimeReplacements = new Dictionary <string, string> (StringComparer.Ordinal) { { "@CmakeAndroidFlags@", "$(_CmakeAndroidFlags)" }, { "@NATIVE_API_LEVEL@", "" }, { "@ABI@", "%(AndroidSupportedTargetJitAbi.Identity)" }, { "@OUTPUT_DIRECTORY@", "" }, }; var hostRuntimeReplacements = new Dictionary <string, string> (StringComparer.Ordinal) { { "@CmakeHostFlags@", "%(_HostRuntime.CmakeFlags)" }, { "@JdkIncludePath@", "@(JdkIncludePath->'%(Identity)', ' ')" }, { "@OUTPUT_DIRECTORY@", "" }, }; AddReplacements(commonReplacements, androidRuntimeReplacements); AddReplacements(commonReplacements, hostRuntimeReplacements); WriteMSBuildProjectStart(sw); sw.WriteLine(" <Target Name=\"_PrepareConfigureRuntimeCommands\" DependsOnTargets=\"_GetBuildHostRuntimes\">"); string indent = " "; foreach (CmakeBuilds.RuntimeCommand rc in CmakeBuilds.AndroidRuntimeCommands) { WriteMSBuildConfigureAndroidRuntimeCommands(sw, indent, rc, androidRuntimeReplacements); } foreach (CmakeBuilds.RuntimeCommand rc in CmakeBuilds.HostRuntimeCommands) { WriteMSBuildConfigureHostRuntimeCommands(sw, indent, rc, hostRuntimeReplacements); } ; sw.WriteLine(" </Target>"); WriteMSBuildProjectEnd(sw); }
protected override async Task <bool> Execute(Context context) { var allRuntimes = new Runtimes(); string binRoot = Configurables.Paths.BinDir; string bundlePath = Path.Combine(binRoot, Configurables.Paths.XABundleFileName); Log.StatusLine("Generating bundle archive: ", Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, bundlePath), tailColor: ConsoleColor.White); Utilities.DeleteFileSilent(bundlePath); var sevenZip = new SevenZipRunner(context); CompressionFormat cf = context.CompressionFormat; Func <string, string, List <string>, Task <bool> > compressor; if (String.Compare(cf.Name, Configurables.Defaults.ZipCompressionFormatName, StringComparison.OrdinalIgnoreCase) == 0) { compressor = sevenZip.Zip; } else if (String.Compare(cf.Name, Configurables.Defaults.SevenZipCompressionFormatName, StringComparison.OrdinalIgnoreCase) == 0) { compressor = sevenZip.SevenZip; } else { throw new InvalidOperationException($"Unsupported compression type: {cf.Description}"); } EnsureAllSDKHeadersAreIncluded(context, allRuntimes); List <string> items = allRuntimes.BundleItems.Where(item => item.ShouldInclude == null || item.ShouldInclude(context)).Select( item => { string relPath = Utilities.GetRelativePath(binRoot, item.SourcePath); Log.DebugLine($"Bundle item: {item.SourcePath} (archive path: {relPath})"); return(relPath); } ).Distinct().ToList(); items.Sort(); if (!await compressor(bundlePath, binRoot, items)) { Log.ErrorLine("Bundle archive creation failed, see the log files for details."); return(false); } return(true); }
public async Task <bool> Run(string projectPath, string logTag, List <string> arguments = null, string binlogName = null, string workingDirectory = null) { if (String.IsNullOrEmpty(logTag)) { throw new ArgumentException("must not be null or empty", nameof(logTag)); } if (String.IsNullOrEmpty(workingDirectory)) { workingDirectory = BuildPaths.XamarinAndroidSourceRoot; } ProcessRunner runner = CreateProcessRunner(); AddArguments(runner, StandardArguments); if (!String.IsNullOrEmpty(binlogName)) { string logPath = Utilities.GetRelativePath(workingDirectory, Path.Combine(Configurables.Paths.BuildBinDir, $"msbuild-{Context.BuildTimeStamp}-{binlogName}.binlog")); runner.AddArgument("/v:normal"); runner.AddQuotedArgument($"/bl:{logPath}"); } AddArguments(runner, arguments); runner.AddQuotedArgument(Utilities.GetRelativePath(workingDirectory, projectPath)); string message = GetLogMessage(runner); Log.Info(message, CommandMessageColor); Log.StatusLine(); try { return(await RunTool( () => { using (var outputSink = (OutputSink)SetupOutputSink(runner, $"msbuild.{logTag}")) { runner.WorkingDirectory = workingDirectory; StartTwiddler(); return runner.Run(); } } )); } finally { StopTwiddler(); } }
public async Task <bool> ReSign(string snkPath, string assemblyPath, string logTag, string workingDirectory = null) { if (String.IsNullOrEmpty(snkPath)) { throw new ArgumentException("must not be null or empty", nameof(snkPath)); } if (String.IsNullOrEmpty(assemblyPath)) { throw new ArgumentException("must not be null or empty", nameof(assemblyPath)); } if (String.IsNullOrEmpty(logTag)) { throw new ArgumentException("must not be null or empty", nameof(logTag)); } if (String.IsNullOrEmpty(workingDirectory)) { workingDirectory = BuildPaths.XamarinAndroidSourceRoot; } ProcessRunner runner = CreateProcessRunner(); runner.AddQuotedArgument("-R"); runner.AddQuotedArgument(Utilities.GetRelativePath(workingDirectory, assemblyPath)); runner.AddQuotedArgument(Utilities.GetRelativePath(workingDirectory, snkPath)); string message = GetLogMessage(runner); Log.Info(message, CommandMessageColor); Log.StatusLine(); return(await RunTool( () => { using (var outputSink = (OutputSink)SetupOutputSink(runner, $"sn.{logTag}")) { runner.WorkingDirectory = workingDirectory; return runner.Run(); } } )); }
void HashFiles(HashAlgorithm ha, List <string> globPatterns) { var block = new byte [4096]; foreach (string glob in globPatterns) { string pattern = glob?.Trim(); if (String.IsNullOrEmpty(pattern)) { continue; } foreach (string file in Directory.EnumerateFiles(Path.GetDirectoryName(pattern), Path.GetFileName(pattern))) { Log.StatusLine(" file: ", Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, file), tailColor: ConsoleColor.Cyan); HashFile(ha, file, block); } } ha.TransformFinalBlock(block, 0, 0); }
async Task <bool> ReadEntry(HttpClient httpClient, Uri url, CDHeader cdh, BinaryReader br, string destinationDirectory) { Context context = Context.Instance; string destFilePath = Path.Combine(destinationDirectory, Path.GetFileName(cdh.FileName)); string compressedFilePath = Path.Combine(destinationDirectory, $"{destFilePath}.deflated"); Log.Status($" {context.Characters.Bullet} {Path.GetFileName (cdh.FileName)} "); Log.Status($"{context.Characters.RightArrow}", ConsoleColor.Cyan); Log.StatusLine($" {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, destFilePath)}"); Log.DebugLine($" {cdh.FileName} (offset: {cdh.RelativeOffsetOfLocalHeader})"); (bool success, Stream contentStream) = await ReadFileData(httpClient, url, cdh); if (!success) { Log.ErrorLine("Failed to read file data"); return(false); } using (var destFile = new BinaryWriter(File.OpenWrite(compressedFilePath))) { using (var fbr = new BinaryReader(contentStream)) { if (!await DownloadAndExtract(fbr, contentStream, destFile, compressedFilePath)) { return(CleanupAndReturn(false)); } } } return(CleanupAndReturn(true)); bool CleanupAndReturn(bool retval) { if (File.Exists(compressedFilePath)) { File.Delete(compressedFilePath); } return(retval); } }
protected TextWriter SetupOutputSink(ProcessRunner runner, string tags = null, string messagePrefix = null) { string logFilePath = null; if (!String.IsNullOrEmpty(tags)) { logFilePath = Context.GetLogFilePath(tags ?? String.Empty); if (String.IsNullOrEmpty(messagePrefix)) { messagePrefix = "running"; } Log.StatusLine($"{LogMessageIndent}[{ToolName}] {messagePrefix}"); Log.StatusLine($"[{ToolName}] log file: ", $"{Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, logFilePath)}", tailColor: Log.DestinationColor); } TextWriter ret = CreateLogSink(logFilePath); runner.AddStandardErrorSink(ret); runner.AddStandardOutputSink(ret); return(ret); }
protected override async Task <bool> Execute(Context context) { string xcrun = context.OS.Which("xcrun"); var libs = new string[] { Path.Combine(Configurables.Paths.HostRuntimeDir, Configurables.Paths.UnstrippedLibMonoSgenName), Path.Combine(Configurables.Paths.HostRuntimeDir, Configurables.Paths.StrippedLibMonoSgenName), }; bool result = true; Log.StatusLine("Changing id for:"); foreach (string libPath in libs) { if (!Utilities.FileExists(libPath)) { Log.StatusLine(" not found", ConsoleColor.Magenta); continue; } if (!ChangeID(libPath)) { Log.StatusLine(" failed", ConsoleColor.Magenta); result = false; } } return(result); bool ChangeID(string path) { Log.DebugLine($"Changing dylib id for {path}"); Log.StatusLine($" {context.Characters.Bullet} {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, path)}"); var runner = new ProcessRunner(xcrun, "install_name_tool", "-id", "@loader_path/libmonosgen-2.0.dylib", path); return(runner.Run()); } }
List <string> GetCmakeArguments(Context context, string workingDirectory, bool sixtyFourBit) { string cmakeToolchainFile; string zlibRoot; if (sixtyFourBit) { cmakeToolchainFile = Configurables.Paths.Mingw64CmakePath; zlibRoot = context.Properties.GetRequiredValue(KnownProperties.MingwZlibRootDirectory64); } else { cmakeToolchainFile = Configurables.Paths.Mingw32CmakePath; zlibRoot = context.Properties.GetRequiredValue(KnownProperties.MingwZlibRootDirectory32); } if (!String.IsNullOrEmpty(zlibRootPrefix)) { zlibRoot = Path.Combine(zlibRootPrefix, zlibRoot); } string zlibLibrary = Path.Combine(zlibRoot, "lib", context.Properties.GetRequiredValue(KnownProperties.MingwZlibLibraryName)); string zlibIncludeDir = Path.Combine(zlibRoot, "include"); return(new List <string> { "-GNinja", "-DCMAKE_MAKE_PROGRAM=ninja", "-DCMAKE_POLICY_DEFAULT_CMP0074=NEW", "-DENABLE_GNUTLS=OFF", "-DENABLE_OPENSSL=OFF", "-DENABLE_COMMONCRYPTO=OFF", "-Wno-dev", // Hushes some warnings that are useless for us $"-DCMAKE_TOOLCHAIN_FILE={Utilities.GetRelativePath (workingDirectory, cmakeToolchainFile)}", $"-DZLIB_ROOT={zlibRoot}", $"-DZLIB_LIBRARY={zlibLibrary}", $"-DZLIB_INCLUDE_DIR={zlibIncludeDir}" }); }
public static List <ExternalGitDependency> GetDependencies(Context context, string externalFilePath, bool quiet = false) { if (!quiet) { Log.Instance.StatusLine($" {context.Characters.Bullet} Reading external dependencies from {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, externalFilePath)}"); } string[] unparsedExternals = File.ReadAllLines(externalFilePath); var externals = new List <ExternalGitDependency> (unparsedExternals.Length); bool includeCommercial = context.CheckCondition(KnownConditions.IncludeCommercial); foreach (string external in unparsedExternals) { Match match = externalRegex.Match(external); if (match != null && match.Success) { if (match.Groups["comment"].Success) { // Ignore matching lines which start with '#'. continue; } string owner = match.Groups["owner"].Value; string repo = match.Groups["repo"].Value; if (!includeCommercial && Configurables.Defaults.CommercialExternalDependencies.Contains($"{owner}/{repo}")) { Log.Instance.DebugLine($"Ignoring external commercial dependency '{owner}/{repo}'"); continue; } var e = new ExternalGitDependency { Branch = match.Groups["branch"].Value, Commit = match.Groups["commit"].Value, Name = repo, Owner = owner, }; externals.Add(e); if (!quiet) { Log.Instance.StatusLine($" {context.Characters.Bullet} {e.Owner}/{e.Name} ({e.Commit})"); } } } return(externals); }
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); } }
#pragma warning restore CS1998 void GenerateThirdPartyNotices(string outputPath, ThirdPartyLicenseType licenseType, bool includeExternalDeps, bool includeBuildDeps) { List <Type> types = Utilities.GetTypesWithCustomAttribute <TPNAttribute> (); if (types.Count == 0) { Log.StatusLine("No Third Party Notice entries found", ConsoleColor.Gray); return; } var licenses = new SortedDictionary <string, ThirdPartyNotice> (StringComparer.OrdinalIgnoreCase); foreach (Type type in types) { EnsureValidTPNType(type); if (type.IsSubclassOf(typeof(ThirdPartyNoticeGroup))) { ProcessTPN(licenses, Activator.CreateInstance(type) as ThirdPartyNoticeGroup, includeExternalDeps, includeBuildDeps); continue; } if (type.IsSubclassOf(typeof(ThirdPartyNotice))) { ProcessTPN(licenses, Activator.CreateInstance(type) as ThirdPartyNotice, includeExternalDeps, includeBuildDeps); continue; } throw new NotSupportedException($"ThirdPartyNotice type {type.FullName} not supported"); } if (licenses.Count == 0) { return; } string blurb; if (!tpnBlurbs.TryGetValue(licenseType, out blurb)) { throw new InvalidOperationException($"Unknown license type {licenseType}"); } using (StreamWriter sw = Utilities.OpenStreamWriter(outputPath)) { Log.StatusLine($" Generating: {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, outputPath)}", ConsoleColor.Gray); Log.DebugLine($"Full path: {outputPath}"); sw.WriteLine(blurb); sw.WriteLine(); uint i = 0; int pad = licenses.Count >= 10 ? 4 : 3; foreach (var kvp in licenses) { string name = kvp.Key; ThirdPartyNotice tpn = kvp.Value; sw.Write($"{++i}.".PadRight(pad)); sw.WriteLine($"{name} ({tpn.SourceUrl})"); } sw.WriteLine(); foreach (string key in licenses.Keys) { ThirdPartyNotice tpn = licenses [key]; string heading = $"%% {tpn.Name} NOTICES AND INFORMATION BEGIN HERE"; string underline = "=".PadRight(heading.Length, '='); sw.WriteLine(heading); sw.WriteLine(underline); if (tpn.LicenseText != null) { sw.WriteLine(tpn.LicenseText.TrimStart()); } else { sw.WriteLine(FetchTPNLicense(tpn.LicenseFile)); } sw.WriteLine(); sw.WriteLine(underline); sw.WriteLine($"END OF {tpn.Name} NOTICES AND INFORMATION"); sw.WriteLine(); } sw.Flush(); } }
public static List <ExternalGitDependency> GetDependencies(Context context, string externalFilePath) { Log.Instance.StatusLine($" {context.Characters.Bullet} Reading external dependencies from {Utilities.GetRelativePath (BuildPaths.XamarinAndroidSourceRoot, externalFilePath)}"); string[] unparsedExternals = File.ReadAllLines(externalFilePath); var externals = new List <ExternalGitDependency> (unparsedExternals.Length); foreach (string external in unparsedExternals) { Match match = externalRegex.Match(external); if (match != null && match.Success) { if (match.Groups["comment"].Success) { // Ignore matching lines which start with '#'. continue; } var e = new ExternalGitDependency { Branch = match.Groups["branch"].Value, Commit = match.Groups["commit"].Value, Name = match.Groups["repo"].Value, Owner = match.Groups["owner"].Value, }; externals.Add(e); Log.Instance.StatusLine($" {context.Characters.Bullet} {e.Owner}/{e.Name} ({e.Commit})"); } } return(externals); }
void Generate(Context context, StreamWriter sw) { string myPath = Path.Combine(BuildPaths.XAPrepareSourceDir, "Application", "GeneratedMakeRulesFile.cs"); sw.WriteLine("#"); sw.WriteLine($"# Generated by {myPath}"); sw.WriteLine("#"); sw.WriteLine(); WriteVariable("export OS_NAME", context.OS.Type); WriteVariable("export OS_ARCH", context.OS.Architecture); WriteVariable("export OS_ARCH_TRANSLATED", context.OS.ProcessIsTranslated ? "true" : "false"); WriteVariable("PRODUCT_VERSION", context.ProductVersion); WriteVariable("MONO_SOURCE_FULL_PATH", Configurables.Paths.MonoSourceFullPath); // These must remain dynamic since the developer may change branches without re-running `prepare` string getGitBranchScript = Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, Path.Combine(Configurables.Paths.BuildToolsScriptsDir, "get-git-branch.sh")); WriteVariable("GIT_BRANCH", $"$(shell LANG=C \"{getGitBranchScript}\" | tr -d '[[:space:]]' | tr -C a-zA-Z0-9- _)"); WriteVariable("GIT_COMMIT", $"$(shell LANG=C git log --no-color --first-parent -n1 --pretty=format:%h)"); WriteVariable("-num-commits-since-version-change", $"$(shell LANG=C git log {context.BuildInfo.CommitOfLastVersionChange}..HEAD --oneline 2>/dev/null | wc -l | sed 's/ //g')"); WriteVariable("ZIP_EXTENSION", context.OS.ZipExtension); WriteVariable("ZIP_OUTPUT_BASENAME", GetOutputFileName(context, "xamarin.android-oss")); WriteVariable("_TEST_RESULTS_BASENAME", GetOutputFileName(context, "xa-test-results")); WriteVariable("_BUILD_STATUS_BASENAME", GetOutputFileName(context, "xa-build-status")); WriteVariable("ZIP_OUTPUT", "$(ZIP_OUTPUT_BASENAME).$(ZIP_EXTENSION)"); WriteVariable("_BUILD_STATUS_ZIP_OUTPUT", "$(_BUILD_STATUS_BASENAME).$(ZIP_EXTENSION)"); WriteVariable("_TEST_RESULTS_ZIP_OUTPUT", "$(_TEST_RESULTS_BASENAME).$(ZIP_EXTENSION)"); var allApiLevels = new List <string> (); var allPlatformIDs = new List <string> (); var allFrameworks = new List <string> (); var apiLevels = new List <string> (); var stableApiLevels = new List <string> (); var frameworks = new List <string> (); var stableFrameworks = new List <string> (); var platformIds = new List <string> (); foreach (AndroidPlatform ap in BuildAndroidPlatforms.AllPlatforms) { string api = ap.ApiLevel.ToString(); allApiLevels.Add(api); allPlatformIDs.Add(ap.PlatformID); if (!String.IsNullOrEmpty(ap.Framework)) { allFrameworks.Add(ap.Framework); frameworks.Add(ap.Framework); if (ap.Stable) { stableFrameworks.Add(ap.Framework); } } else { allFrameworks.Add("-"); } if (!ap.Supported) { continue; } apiLevels.Add(api); platformIds.Add(ap.PlatformID); if (ap.Stable) { stableApiLevels.Add(api); } } var enabledJitAbis = AbiNames.AllJitAbis.Where(a => context.IsTargetJitAbiEnabled(a)); var enabledHostAbis = AbiNames.AllHostAbis.Where(a => context.IsHostJitAbiEnabled(a)); var enabledAotAbis = AbiNames.AllAotAbis.Where(a => context.IsTargetAotAbiEnabled(a)); WriteVariable("ALL_API_LEVELS", ToValue(allApiLevels)); WriteVariable("ALL_PLATFORM_IDS", ToValue(allPlatformIDs)); WriteVariable("ALL_FRAMEWORKS", ToValue(allFrameworks)); WriteVariable("API_LEVELS", ToValue(apiLevels)); WriteVariable("STABLE_API_LEVELS", ToValue(stableApiLevels)); WriteVariable("FRAMEWORKS", ToValue(frameworks)); WriteVariable("STABLE_FRAMEWORKS", ToValue(stableFrameworks)); WriteVariable("ALL_JIT_ABIS", ToValue(enabledJitAbis.ToList())); WriteVariable("ALL_HOST_ABIS", ToValue(enabledHostAbis.ToList())); WriteVariable("ALL_AOT_ABIS", ToValue(enabledAotAbis.ToList())); WriteVariable("ANDROID_TOOLCHAIN_DIR", context.Properties.GetRequiredValue(KnownProperties.AndroidToolchainDirectory)); if (context.MonoOptions != null && context.MonoOptions.Count > 0) { WriteVariable("MONO_OPTIONS", ToValue(context.MonoOptions)); sw.WriteLine("export MONO_OPTIONS"); } sw.WriteLine("_MSBUILD_ARGS = \\"); sw.WriteLine($"\t/p:{KnownProperties.AndroidSupportedTargetJitAbis}={context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedTargetJitAbis)} \\"); sw.WriteLine($"\t/p:{KnownProperties.AndroidSupportedHostJitAbis}={context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedHostJitAbis)} \\"); sw.WriteLine($"\t/p:{KnownProperties.AndroidSupportedTargetAotAbis}={context.Properties.GetRequiredValue (KnownProperties.AndroidSupportedTargetAotAbis)}"); OutputOSVariables(context, sw); WriteListVariable("_BUNDLE_ZIPS_INCLUDE", Configurables.Defaults.BundleZipsInclude); WriteListVariable("_BUNDLE_ZIPS_EXCLUDE", Configurables.Defaults.BundleZipsExclude); WriteListVariable("_TEST_RESULTS_BUNDLE_INCLUDE", Configurables.Defaults.TestResultsBundleInclude); WriteListVariable("_TEST_RESULTS_BUNDLE_EXCLUDE", Configurables.Defaults.TestResultsBundleExclude); WriteListVariable("_BUILD_STATUS_BUNDLE_INCLUDE", Configurables.Defaults.BuildStatusBundleInclude); WriteListVariable("_BUILD_STATUS_BUNDLE_INCLUDE", Configurables.Defaults.BuildStatusBundleIncludeConditional, true); WriteListVariable("_BUILD_STATUS_BUNDLE_EXCLUDE", Configurables.Defaults.BuildStatusBundleExclude); sw.WriteLine(); sw.WriteLine(".PHONY: framework-assemblies"); sw.WriteLine("framework-assemblies:"); string prevVersion = "v1.0"; string monoFrameworksRoot = Path.Combine("bin", "$(CONFIGURATION)", context.Properties.GetRequiredValue(KnownProperties.XABinRelativeInstallPrefix), Configurables.Paths.MonoAndroidFrameworksSubDir); for (int i = 0; i < apiLevels.Count; i++) { string curVersion = frameworks [i]; string apiLevel = apiLevels [i]; string platformId = platformIds [i]; string redistFile = Path.Combine(monoFrameworksRoot, curVersion, "RedistList", "FrameworkList.xml"); WriteRuleLine($"grep -q {prevVersion} {redistFile}; \\"); WriteRuleLine("if [ $$? -ne 0 ] ; then \\"); WriteRuleLine($"\trm -f {redistFile}; \\"); WriteRuleLine("fi; \\"); WriteRuleLine("$(call MSBUILD_BINLOG,Mono.Android,$(_SLN_BUILD)) src/Mono.Android/Mono.Android.csproj \\"); WriteRuleLine("\t/p:Configuration=$(CONFIGURATION) $(_MSBUILD_ARGS) \\"); WriteRuleLine($"\t/p:AndroidApiLevel={apiLevel} /p:AndroidPlatformId={platformId} /p:AndroidFrameworkVersion={curVersion} \\"); WriteRuleLine($"\t/p:AndroidPreviousFrameworkVersion={prevVersion} || exit 1;"); prevVersion = curVersion; } string firstApiLevel = apiLevels [0]; string firstPlatformId = platformIds [0]; string firstFramework = frameworks [0]; string latestStableFramework = stableFrameworks [stableFrameworks.Count - 1]; WriteMSBuildCall( fileToRemovePath: Path.Combine(monoFrameworksRoot, "v1.0", "Xamarin.Android.NUnitLite.dll"), projectPath: "src/Xamarin.Android.NUnitLite/Xamarin.Android.NUnitLite.csproj" ); WriteMSBuildCall( fileToRemovePath: $"{monoFrameworksRoot}/{latestStableFramework}/Mono.Android.Export.*", projectPath: "src/Mono.Android.Export/Mono.Android.Export.csproj" ); WriteMSBuildCall( fileToRemovePath: $"{monoFrameworksRoot}/{latestStableFramework}/OpenTK-1.0.*", projectPath: "src/OpenTK-1.0/OpenTK.csproj" ); sw.WriteLine(); if (context.RuleGenerators == null || context.RuleGenerators.Count == 0) { return; } foreach (RuleGenerator rg in context.RuleGenerators) { if (rg == null) { continue; } rg(this, sw); } void WriteMSBuildCall(string fileToRemovePath, string projectPath) { WriteRuleLine($"rm -f {fileToRemovePath}"); WriteRuleLine($"$(call MSBUILD_BINLOG,NUnitLite,$(_SLN_BUILD)) $(MSBUILD_FLAGS) {projectPath} \\"); WriteRuleLine("\t/p:Configuration=$(CONFIGURATION) $(_MSBUILD_ARGS) \\"); WriteRuleLine($"\t/p:AndroidApiLevel={firstApiLevel} /p:AndroidPlatformId={firstPlatformId} \\"); WriteRuleLine($"\t/p:AndroidFrameworkVersion={firstFramework} || exit 1;"); } string ToValue(ICollection <string> list, string?separator = null) { return(String.Join(separator ?? " ", list)); } void WriteRuleLine(string line) { sw.Write('\t'); sw.WriteLine(line); } void WriteVariable(string name, string value) { sw.WriteLine($"{name} = {value}"); } void WriteListVariable(string name, ICollection <string> list, bool conditional = false) { if (list.Count == 0) { return; } if (!conditional) { sw.Write($"{name} ="); } foreach (string i in list) { string item = i.Trim(); if (String.IsNullOrEmpty(item)) { continue; } if (conditional) { sw.WriteLine($"ifneq ($(wildcard {item}),)"); sw.WriteLine($"{name} += {item}"); sw.WriteLine("endif"); continue; } sw.WriteLine(" \\"); sw.Write($"\t{item}"); } if (!conditional) { sw.WriteLine(); } } }
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 = Path.Combine(Configurables.Paths.BundleArchivePath); 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. 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.Bundle_InstallDir}"); Utilities.MoveDirectoryContentsRecursively(tempDir, Configurables.Paths.BundleInstallDir, resetFileTimestamp: true); } finally { Utilities.DeleteDirectorySilent(tempDir); } return(true); }
protected override async Task <bool> Execute(Context context) { List <ExternalGitDependency> externalDependencies = ExternalGitDependency.GetDependencies(context, Configurables.Paths.ExternalGitDepsFilePath); bool failed = false; Log.StatusLine(); Log.StatusLine("Updating external repositories"); var git = new GitRunner(context) { EchoCmdAndArguments = false }; foreach (ExternalGitDependency egd in externalDependencies) { Log.StatusLine($" {context.Characters.Bullet} {egd.Name}"); if (egd.Owner == "mono" && egd.Name == "mono") { var genFilesStep = new Step_GenerateFiles(false, true); var monogitPropsFile = genFilesStep.Get_MonoGitHash_props(context); Log.Status("Generating "); Log.Status(Utilities.GetRelativePath(BuildPaths.XamarinAndroidSourceRoot, monogitPropsFile.OutputPath), ConsoleColor.White); monogitPropsFile.Generate(context); continue; } string destDir = Path.Combine(Configurables.Paths.ExternalGitDepsDestDir, egd.Name); if (!Directory.Exists(destDir)) { var egdUrl = await GetGitHubURL(egd, git); Log.StatusLine($" {context.Characters.Link} cloning from {egd.Owner}/{egd.Name}"); if (!await git.Clone(egdUrl, destDir)) { Log.ErrorLine($"Failed to clone {egd.Name}"); failed = true; continue; } } Log.StatusLine($" {context.Characters.Link} fetching changes from {egd.Owner}/{egd.Name}"); if (!await git.Fetch(destDir)) { Log.ErrorLine($"Failed to fetch changes for {egd.Name}"); failed = true; continue; } Log.StatusLine($" {context.Characters.Bullet} checking out commit {egd.Commit}"); if (!await git.CheckoutCommit(destDir, egd.Commit)) { Log.ErrorLine($"Failed to checkout commit {egd.Commit} for {egd.Name}"); failed = true; continue; } // // Commented out for now because we only have monodroid in .external and its submodules are updated // elsewhere and there's no need to duplicate the (time-consuming) work. However, it might be a good // idea to re-enable this code for the benefit of future .external additions (and, possibly, monodroid // itself after its integration code is updated to not initialize submodules) // // string gitModules = Path.Combine (destDir, ".gitmodules"); // if (!Utilities.FileExists (gitModules)) // continue; // Log.StatusLine ($" {context.Characters.Bullet} updating submodules"); // if (!await git.SubmoduleUpdate (destDir)) { // Log.ErrorLine ($"Failed to update submodules for {egd.Name}"); // failed = true; // } } return(!failed); }