public static BuildFolder FromDirectory(string inputDirectory, IEnumerable <CompilerRunner> compilerRunners, string outputRoot, BuildOptions options) { List <string> compilationInputFiles = new List <string>(); List <string> passThroughFiles = new List <string>(); List <string> mainExecutables = new List <string>(); List <string> executionScripts = new List <string>(); string scriptExtension = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".cmd" : ".sh"); // Copy unmanaged files (runtime, native dependencies, resources, etc) foreach (string file in Directory.EnumerateFiles(inputDirectory, options.InputFileSearchString ?? "*")) { bool isManagedAssembly = ComputeManagedAssemblies.IsManaged(file); if (isManagedAssembly) { compilationInputFiles.Add(file); } if ((!isManagedAssembly || options.Composite) && (Path.GetExtension(file) != ".pdb") && (Path.GetExtension(file) != ".ilk")) // exclude .pdb and .ilk files that are large and not needed in the target folder { passThroughFiles.Add(file); } string ext = Path.GetExtension(file); if (ext.Equals(".exe", StringComparison.OrdinalIgnoreCase)) { mainExecutables.Add(file); } else if (ext.Equals(scriptExtension, StringComparison.OrdinalIgnoreCase)) { executionScripts.Add(file); } } if (compilationInputFiles.Count == 0) { return(null); } foreach (CompilerRunner runner in compilerRunners) { string runnerOutputPath = runner.GetOutputPath(outputRoot); if (!options.Exe) { runnerOutputPath.RecreateDirectory(); foreach (string file in passThroughFiles) { File.Copy(file, Path.Combine(runnerOutputPath, Path.GetFileName(file))); } } } return(new BuildFolder(compilationInputFiles, mainExecutables, executionScripts, compilerRunners, inputDirectory, outputRoot, options)); }
public static BuildFolder FromDirectory(string inputDirectory, IEnumerable <CompilerRunner> compilerRunners, string outputRoot, BuildOptions options) { List <string> compilationInputFiles = new List <string>(); List <string> passThroughFiles = new List <string>(); List <string> mainExecutables = new List <string>(); List <string> executionScripts = new List <string>(); // Copy unmanaged files (runtime, native dependencies, resources, etc) foreach (string file in Directory.EnumerateFiles(inputDirectory)) { bool isManagedAssembly = ComputeManagedAssemblies.IsManaged(file); if (isManagedAssembly) { compilationInputFiles.Add(file); } else { passThroughFiles.Add(file); } string ext = Path.GetExtension(file); if (ext.Equals(".exe", StringComparison.OrdinalIgnoreCase)) { mainExecutables.Add(file); } else if (ext.Equals(".cmd", StringComparison.OrdinalIgnoreCase)) { executionScripts.Add(file); } } if (compilationInputFiles.Count == 0) { return(null); } foreach (CompilerRunner runner in compilerRunners) { string runnerOutputPath = runner.GetOutputPath(outputRoot); runnerOutputPath.RecreateDirectory(); foreach (string file in passThroughFiles) { File.Copy(file, Path.Combine(runnerOutputPath, Path.GetFileName(file))); } } return(new BuildFolder(compilationInputFiles, mainExecutables, executionScripts, compilerRunners, outputRoot, options)); }
public static int CompileDirectory( DirectoryInfo inputDirectory, DirectoryInfo outputDirectory, DirectoryInfo crossgenDirectory, DirectoryInfo cpaotDirectory, DirectoryInfo[] referencePath) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); if (inputDirectory == null) { Console.WriteLine("--input-directory is a required argument."); return(1); } if (outputDirectory == null) { outputDirectory = inputDirectory; } if (outputDirectory.IsParentOf(inputDirectory)) { Console.WriteLine("Error: Input and output folders must be distinct, and the output directory (which gets deleted) better not be a parent of the input directory."); return(1); } List <string> referencePaths = referencePath?.Select(x => x.ToString())?.ToList(); string coreRunPath = null; foreach (string path in referencePaths) { string candidatePath = Path.Combine(path, "CoreRun.exe"); if (File.Exists(candidatePath)) { coreRunPath = candidatePath; break; } } if (coreRunPath == null) { Console.Error.WriteLine("CoreRun.exe not found in reference folders, execution won't run"); } List <CompilerRunner> runners = new List <CompilerRunner>(); if (cpaotDirectory != null) { runners.Add(new CpaotRunner(cpaotDirectory.ToString(), inputDirectory.ToString(), outputDirectory.ToString(), referencePaths)); } if (crossgenDirectory != null) { runners.Add(new CrossgenRunner(crossgenDirectory.ToString(), inputDirectory.ToString(), outputDirectory.ToString(), referencePaths)); } List <string> compilationInputFiles = new List <string>(); List <string> passThroughFiles = new List <string>(); string mainExecutable = null; // Copy unmanaged files (runtime, native dependencies, resources, etc) foreach (string file in Directory.EnumerateFiles(inputDirectory.FullName)) { bool isManagedAssembly = ComputeManagedAssemblies.IsManaged(file); if (isManagedAssembly) { compilationInputFiles.Add(file); } else { passThroughFiles.Add(file); } if (Path.GetExtension(file).Equals(".exe", StringComparison.OrdinalIgnoreCase)) { mainExecutable = file; } } foreach (CompilerRunner runner in runners) { string runnerOutputPath = runner.GetOutputPath(); runnerOutputPath.RecreateDirectory(); foreach (string file in passThroughFiles) { File.Copy(file, Path.Combine(runnerOutputPath, Path.GetFileName(file))); } } List <ProcessInfo> compilationsToRun = new List <ProcessInfo>(); Application application = new Application(compilationInputFiles, mainExecutable, runners, coreRunPath); foreach (ProcessInfo[] compilation in application.Compilations) { foreach (CompilerRunner runner in runners) { compilationsToRun.Add(compilation[(int)runner.Index]); } } compilationsToRun.Sort((a, b) => b.CompilationCostHeuristic.CompareTo(a.CompilationCostHeuristic)); ParallelRunner.Run(compilationsToRun); bool success = true; List <KeyValuePair <string, string> > failedCompilationsPerBuilder = new List <KeyValuePair <string, string> >(); int successfulCompileCount = 0; foreach (ProcessInfo[] compilation in application.Compilations) { string file = null; string failedBuilders = null; foreach (CompilerRunner runner in runners) { ProcessInfo runnerProcess = compilation[(int)runner.Index]; if (!runnerProcess.Succeeded) { File.Copy(runnerProcess.InputFileName, runnerProcess.OutputFileName); if (file == null) { file = runnerProcess.InputFileName; failedBuilders = runner.CompilerName; } else { failedBuilders += "; " + runner.CompilerName; } } } if (file != null) { failedCompilationsPerBuilder.Add(new KeyValuePair <string, string>(file, failedBuilders)); success = false; } else { successfulCompileCount++; } } Console.WriteLine($"Compiled {successfulCompileCount} / {successfulCompileCount + failedCompilationsPerBuilder.Count} assemblies in {stopwatch.ElapsedMilliseconds} msecs."); if (failedCompilationsPerBuilder.Count > 0) { Console.WriteLine($"Failed to compile {failedCompilationsPerBuilder.Count} assemblies:"); foreach (KeyValuePair <string, string> assemblyBuilders in failedCompilationsPerBuilder) { string assemblySpec = assemblyBuilders.Key; if (runners.Count > 1) { assemblySpec += " (" + assemblyBuilders.Value + ")"; } Console.WriteLine(assemblySpec); } } if (coreRunPath != null) { List <ProcessInfo> executionsToRun = new List <ProcessInfo>(); foreach (CompilerRunner runner in runners) { bool compilationsSucceeded = application.Compilations.All(comp => comp[(int)runner.Index].Succeeded); if (compilationsSucceeded) { ProcessInfo executionProcess = application.Execution[(int)runner.Index]; if (executionProcess != null) { executionsToRun.Add(executionProcess); } } } ParallelRunner.Run(executionsToRun); } return(success ? 0 : 1); }
public static BuildFolder FromDirectory(string inputDirectory, IEnumerable <CompilerRunner> compilerRunners, string outputRoot, BuildOptions options) { List <string> compilationInputFiles = new List <string>(); HashSet <string> passThroughFiles = new HashSet <string>(); List <string> mainExecutables = new List <string>(); List <string> executionScripts = new List <string>(); string scriptExtension = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".cmd" : ".sh"); // Copy unmanaged files (runtime, native dependencies, resources, etc) foreach (string file in Directory.EnumerateFiles(inputDirectory, options.InputFileSearchString ?? "*")) { bool isManagedAssembly = ComputeManagedAssemblies.IsManaged(file); if (isManagedAssembly) { compilationInputFiles.Add(file); } if ((!isManagedAssembly || options.Composite) && (Path.GetExtension(file) != ".pdb") && (Path.GetExtension(file) != ".ilk")) // exclude .pdb and .ilk files that are large and not needed in the target folder { passThroughFiles.Add(file); } string ext = Path.GetExtension(file); if (ext.Equals(".exe", StringComparison.OrdinalIgnoreCase)) { mainExecutables.Add(file); } else if (ext.Equals(scriptExtension, StringComparison.OrdinalIgnoreCase)) { executionScripts.Add(file); } } if (compilationInputFiles.Count == 0) { return(null); } if (options.Composite && !(options.Framework || options.UseFramework)) { // In composite mode we copy the native runtime to the app folder and pretend that is CORE_ROOT, // otherwise CoreRun picks up the original MSIL versions of framework assemblies from CORE_ROOT // instead of the rewritten ones next to the app. foreach (string exe in s_runtimeExecutables) { passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, exe.AppendOSExeSuffix())); } string libraryPrefix = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib"); foreach (string lib in s_runtimeLibraries) { passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, (libraryPrefix + lib).AppendOSDllSuffix())); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { foreach (string lib in s_runtimeWindowsOnlyLibraries) { passThroughFiles.Add(Path.Combine(options.CoreRootDirectory.FullName, lib.AppendOSDllSuffix())); } } else { // Several native lib*.so / dylib are needed by the runtime foreach (string nativeLib in Directory.EnumerateFiles(options.CoreRootDirectory.FullName, "lib*".AppendOSDllSuffix())) { passThroughFiles.Add(nativeLib); } } } foreach (CompilerRunner runner in compilerRunners) { string runnerOutputPath = runner.GetOutputPath(outputRoot); if (!options.Exe) { runnerOutputPath.RecreateDirectory(); foreach (string file in passThroughFiles) { File.Copy(file, Path.Combine(runnerOutputPath, Path.GetFileName(file))); } } } return(new BuildFolder(compilationInputFiles, mainExecutables, executionScripts, compilerRunners, inputDirectory, outputRoot, options)); }
public static int CompileDirectory(DirectoryInfo toolDirectory, DirectoryInfo inputDirectory, DirectoryInfo outputDirectory, bool crossgen, bool cpaot, DirectoryInfo[] referencePath) { if (toolDirectory == null) { Console.WriteLine("--tool-directory is a required argument."); return(1); } if (inputDirectory == null) { Console.WriteLine("--input-directory is a required argument."); return(1); } if (outputDirectory == null) { Console.WriteLine("--output-directory is a required argument."); return(1); } if (OutputPathIsParentOfInputPath(inputDirectory, outputDirectory)) { Console.WriteLine("Error: Input and output folders must be distinct, and the output directory (which gets deleted) better not be a parent of the input directory."); return(1); } CompilerRunner runner; if (cpaot) { runner = new CpaotRunner(toolDirectory.ToString(), inputDirectory.ToString(), outputDirectory.ToString(), referencePath?.Select(x => x.ToString())?.ToList()); } else { runner = new CrossgenRunner(toolDirectory.ToString(), inputDirectory.ToString(), outputDirectory.ToString(), referencePath?.Select(x => x.ToString())?.ToList()); } if (outputDirectory.Exists) { try { outputDirectory.Delete(recursive: true); } catch (Exception ex) when( ex is UnauthorizedAccessException || ex is DirectoryNotFoundException || ex is IOException ) { Console.WriteLine($"Error: Could not delete output folder {outputDirectory.FullName}. {ex.Message}"); return(1); } } outputDirectory.Create(); bool success = true; // Copy unmanaged files (runtime, native dependencies, resources, etc) foreach (string file in Directory.EnumerateFiles(inputDirectory.FullName)) { if (ComputeManagedAssemblies.IsManaged(file)) { // Compile managed code if (!runner.CompileAssembly(file)) { success = false; // On compile failure, pass through the input IL assembly so the output is still usable File.Copy(file, Path.Combine(outputDirectory.FullName, Path.GetFileName(file))); } } else { // Copy through all other files File.Copy(file, Path.Combine(outputDirectory.FullName, Path.GetFileName(file))); } } return(success ? 0 : 1); }
public static int CompileDirectory(DirectoryInfo toolDirectory, DirectoryInfo inputDirectory, DirectoryInfo outputDirectory, bool crossgen, bool cpaot, DirectoryInfo[] referencePath) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); if (toolDirectory == null) { Console.WriteLine("--tool-directory is a required argument."); return(1); } if (inputDirectory == null) { Console.WriteLine("--input-directory is a required argument."); return(1); } if (outputDirectory == null) { outputDirectory = inputDirectory; } if (OutputPathIsParentOfInputPath(inputDirectory, outputDirectory)) { Console.WriteLine("Error: Input and output folders must be distinct, and the output directory (which gets deleted) better not be a parent of the input directory."); return(1); } CompilerRunner runner; if (cpaot) { runner = new CpaotRunner(toolDirectory.ToString(), inputDirectory.ToString(), outputDirectory.ToString(), referencePath?.Select(x => x.ToString())?.ToList()); } else { runner = new CrossgenRunner(toolDirectory.ToString(), inputDirectory.ToString(), outputDirectory.ToString(), referencePath?.Select(x => x.ToString())?.ToList()); } string runnerOutputPath = runner.GetOutputPath(); if (Directory.Exists(runnerOutputPath)) { try { Directory.Delete(runnerOutputPath, recursive: true); } catch (Exception ex) when( ex is UnauthorizedAccessException || ex is DirectoryNotFoundException || ex is IOException ) { Console.WriteLine($"Error: Could not delete output folder {runnerOutputPath}. {ex.Message}"); return(1); } } Directory.CreateDirectory(runnerOutputPath); List <ProcessInfo> compilationsToRun = new List <ProcessInfo>(); // Copy unmanaged files (runtime, native dependencies, resources, etc) foreach (string file in Directory.EnumerateFiles(inputDirectory.FullName)) { if (ComputeManagedAssemblies.IsManaged(file)) { ProcessInfo compilationToRun = runner.CompilationProcess(file); compilationToRun.InputFileName = file; compilationsToRun.Add(compilationToRun); } else { // Copy through all other files File.Copy(file, Path.Combine(runnerOutputPath, Path.GetFileName(file))); } } ParallelRunner.Run(compilationsToRun); bool success = true; List <string> failedCompilationAssemblies = new List <string>(); int successfulCompileCount = 0; foreach (ProcessInfo processInfo in compilationsToRun) { if (processInfo.Succeeded) { successfulCompileCount++; } else { File.Copy(processInfo.InputFileName, Path.Combine(runnerOutputPath, Path.GetFileName(processInfo.InputFileName))); failedCompilationAssemblies.Add(processInfo.InputFileName); } } Console.WriteLine($"Compiled {successfulCompileCount}/{successfulCompileCount + failedCompilationAssemblies.Count} assemblies in {stopwatch.ElapsedMilliseconds} msecs."); if (failedCompilationAssemblies.Count > 0) { Console.WriteLine($"Failed to compile {failedCompilationAssemblies.Count} assemblies:"); foreach (var assembly in failedCompilationAssemblies) { Console.WriteLine(assembly); } } return(success ? 0 : 1); }