Exemple #1
0
 public JitRunner(BuildOptions options)
     : base(options, new string[] { options.CoreRootDirectory.FullName }.Concat(options.ReferencePaths()))
 {
 }
Exemple #2
0
 public CpaotRunner(BuildOptions options, IEnumerable <string> referencePaths)
     : base(options, options.CpaotDirectory.FullName, referencePaths)
 {
 }
Exemple #3
0
        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);
                }
                else if ((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));
        }
Exemple #4
0
 public CrossgenRunner(BuildOptions options, IEnumerable <string> referencePaths)
     : base(options, referencePaths)
 {
 }
Exemple #5
0
        /// <summary>
        /// Utility mode that allows compilation of a set of assemblies using their existing Crossgen response files.
        /// This is currently useful for workloads like Bing which have a large complicated web of binaries in different folders
        /// with potentially different sets of reference paths used for different assemblies.
        /// </summary>
        public static int CompileFromCrossgenRsp(BuildOptions options)
        {
            if (options.CrossgenResponseFile == null && options.InputDirectory == null)
            {
                Console.Error.WriteLine("Specify --response-file or --input-directory containing multiple response files.");
                return(1);
            }

            if (options.OutputDirectory == null)
            {
                if (options.InputDirectory != null)
                {
                    options.OutputDirectory = options.InputDirectory;
                }
                else
                {
                    options.OutputDirectory = new DirectoryInfo(Path.GetDirectoryName(options.CrossgenResponseFile.FullName));
                }
            }
            else if (options.InputDirectory != null && options.OutputDirectory.IsParentOf(options.InputDirectory))
            {
                Console.Error.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);
            }

            // This command does not work in the context of an app, just a loose set of rsp files so don't execute anything we compile
            options.NoJit = true;
            options.NoEtw = true;

            //
            // Determine whether we're compiling a single .rsp or a folder of them
            //
            var responseFiles = new List <string>();

            if (options.CrossgenResponseFile != null)
            {
                responseFiles.Add(options.CrossgenResponseFile.FullName);
            }
            else
            {
                responseFiles = Directory.EnumerateFiles(options.InputDirectory.FullName, "*.rsp", SearchOption.TopDirectoryOnly).ToList();
            }

            Dictionary <string, string> pathReplacements = new Dictionary <string, string>();

            if ((options.RewriteOldPath == null) != (options.RewriteNewPath == null))
            {
                Console.Error.WriteLine("Error: --rewrite-old-path and --rewrite-new-path must both be specified if either is used.");
                return(1);
            }

            if (options.RewriteOldPath != null && options.RewriteNewPath != null)
            {
                if (options.RewriteOldPath.Length != options.RewriteNewPath.Length)
                {
                    Console.Error.WriteLine("Error: --rewrite-old-path and --rewrite-new-path were specified a different number of times.");
                    return(1);
                }

                for (int i = 0; i < options.RewriteNewPath.Length; i++)
                {
                    pathReplacements.Add(options.RewriteOldPath[i].FullName, options.RewriteNewPath[i].FullName);
                    Console.WriteLine($"Re-writing path {options.RewriteOldPath[i].FullName} as {options.RewriteNewPath[i].FullName}");
                }
            }

            bool success             = true;
            int  compilationFailures = 0;
            int  totalCompilations   = 0;

            // Collect all the compilations first
            foreach (var inputRsp in responseFiles)
            {
                var crossgenArguments = CrossgenArguments.ParseFromResponseFile(inputRsp)
                                        .ReplacePaths(pathReplacements);

                Console.WriteLine($"{inputRsp} -> {crossgenArguments.InputFile}");
                var compilerRunners = options.CompilerRunners(false, crossgenArguments.ReferencePaths);

                string responseFileOuputPath = Path.Combine(options.OutputDirectory.FullName, Path.GetFileNameWithoutExtension(inputRsp));
                responseFileOuputPath.RecreateDirectory();

                List <ProcessInfo> fileCompilations = new List <ProcessInfo>();
                foreach (CompilerRunner runner in compilerRunners)
                {
                    var compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, responseFileOuputPath, crossgenArguments.InputFile));
                    fileCompilations.Add(compilationProcess);
                }

                ParallelRunner.Run(fileCompilations, options.DegreeOfParallelism);
                totalCompilations++;

                foreach (var compilationProcess in fileCompilations)
                {
                    if (!compilationProcess.Succeeded)
                    {
                        success = false;
                        compilationFailures++;

                        Console.WriteLine($"Failed compiling {compilationProcess.Parameters.InputFileName}");
                    }
                }
            }

            Console.WriteLine("Rsp Compilation Results");
            Console.WriteLine($"Total compilations: {totalCompilations}");
            Console.WriteLine($"Compilation failures: {compilationFailures}");

            return(success ? 0 : 1);
        }
Exemple #6
0
 public CompilerRunner(BuildOptions options, string compilerFolder, IEnumerable <string> referenceFolders)
 {
     _options          = options;
     _compilerPath     = compilerFolder;
     _referenceFolders = referenceFolders;
 }
Exemple #7
0
        public static int CompileSubtree(BuildOptions options)
        {
            if (options.InputDirectory == null)
            {
                Console.WriteLine("--input-directory is a required argument.");
                return(1);
            }

            if (options.CoreRootDirectory == null)
            {
                Console.Error.WriteLine("--core-root-directory (--cr) is a required argument.");
                return(1);
            }

            if (options.OutputDirectory == null)
            {
                options.OutputDirectory = options.InputDirectory;
            }

            if (options.OutputDirectory.IsParentOf(options.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);
            }

            IEnumerable <CompilerRunner> runners = options.CompilerRunners(isFramework: false);

            if (!options.Exe)
            {
                PathExtensions.DeleteOutputFolders(options.OutputDirectory.FullName, options.CoreRootDirectory.FullName, runners, recursive: true);
            }

            string[] directories = LocateSubtree(options.InputDirectory.FullName, options.CoreRootDirectory.FullName).ToArray();

            ConcurrentBag <BuildFolder> folders = new ConcurrentBag <BuildFolder>();
            int relativePathOffset = options.InputDirectory.FullName.Length;

            if (relativePathOffset > 0 && options.InputDirectory.FullName[relativePathOffset - 1] != Path.DirectorySeparatorChar)
            {
                relativePathOffset++;
            }

            int folderCount      = 0;
            int compilationCount = 0;
            int executionCount   = 0;

            Parallel.ForEach(directories, (string directory) =>
            {
                string outputDirectoryPerFolder = options.OutputDirectory.FullName;
                if (directory.Length > relativePathOffset)
                {
                    outputDirectoryPerFolder = Path.Combine(outputDirectoryPerFolder, directory.Substring(relativePathOffset));
                }
                try
                {
                    BuildFolder folder = BuildFolder.FromDirectory(directory.ToString(), runners, outputDirectoryPerFolder, options);
                    if (folder != null)
                    {
                        folders.Add(folder);
                        Interlocked.Add(ref compilationCount, folder.Compilations.Count);
                        Interlocked.Add(ref executionCount, folder.Executions.Count);
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("Error scanning folder {0}: {1}", directory, ex.Message);
                }
                int currentCount = Interlocked.Increment(ref folderCount);
                if (currentCount % 100 == 0)
                {
                    StringBuilder lineReport = new StringBuilder();
                    lineReport.Append($@"Found {folders.Count} folders to build ");
                    lineReport.Append($@"({compilationCount} compilations, ");
                    if (!options.NoExe)
                    {
                        lineReport.Append($@"{executionCount} executions, ");
                    }
                    lineReport.Append($@"{currentCount} / {directories.Length} folders scanned)");
                    Console.WriteLine(lineReport.ToString());
                }
            });
            Console.Write($@"Found {folders.Count} folders to build ({compilationCount} compilations, ");
            if (!options.NoExe)
            {
                Console.Write($@"{executionCount} executions, ");
            }
            Console.WriteLine($@"{directories.Length} folders scanned)");

            BuildFolderSet folderSet = new BuildFolderSet(folders, runners, options);
            bool           success   = folderSet.Build();

            folderSet.WriteLogs();

            if (!options.NoCleanup)
            {
                PathExtensions.DeleteOutputFolders(options.OutputDirectory.FullName, options.CoreRootDirectory.FullName, runners, recursive: true);
            }

            return(success ? 0 : 1);
        }
Exemple #8
0
        public BuildFolder(
            List <string> compilationInputFiles,
            List <string> mainExecutables,
            List <string> executionScripts,
            IEnumerable <CompilerRunner> compilerRunners,
            string inputFolder,
            string outputFolder,
            BuildOptions options)
        {
            _compilationInputFiles = compilationInputFiles;
            _mainExecutables       = mainExecutables;
            _executionScripts      = executionScripts;
            _inputFolder           = inputFolder;
            _outputFolder          = outputFolder;

            _compilations = new List <ProcessInfo[]>();
            _executions   = new List <ProcessInfo[]>();

            foreach (string file in _compilationInputFiles)
            {
                ProcessInfo[] fileCompilations = new ProcessInfo[(int)CompilerIndex.Count];
                foreach (CompilerRunner runner in compilerRunners)
                {
                    ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, _outputFolder, file));
                    fileCompilations[(int)runner.Index] = compilationProcess;
                }
                _compilations.Add(fileCompilations);
            }

            if (!options.NoExe)
            {
                HashSet <string> scriptedExecutables = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                foreach (string script in _executionScripts ?? Enumerable.Empty <string>())
                {
                    ProcessInfo[] scriptExecutions = new ProcessInfo[(int)CompilerIndex.Count];
                    _executions.Add(scriptExecutions);
                    scriptedExecutables.Add(Path.ChangeExtension(script, ".exe"));

                    foreach (CompilerRunner runner in compilerRunners)
                    {
                        HashSet <string> modules = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                        HashSet <string> folders = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                        modules.Add(runner.GetOutputFileName(_outputFolder, script));
                        modules.UnionWith(_compilationInputFiles);
                        modules.UnionWith(_compilationInputFiles.Select(file => runner.GetOutputFileName(_outputFolder, file)));
                        folders.Add(Path.GetDirectoryName(script));
                        folders.UnionWith(runner.ReferenceFolders);

                        scriptExecutions[(int)runner.Index] = new ProcessInfo(new ScriptExecutionProcessConstructor(runner, _outputFolder, script, modules, folders));
                    }
                }

                if (options.CoreRootDirectory != null)
                {
                    foreach (string mainExe in _mainExecutables ?? Enumerable.Empty <string>())
                    {
                        if (scriptedExecutables.Contains(mainExe))
                        {
                            // Skip direct exe launch assuming it was run by the corresponding cmd script
                            continue;
                        }

                        ProcessInfo[] appExecutions = new ProcessInfo[(int)CompilerIndex.Count];
                        _executions.Add(appExecutions);
                        foreach (CompilerRunner runner in compilerRunners)
                        {
                            HashSet <string> modules = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                            HashSet <string> folders = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                            modules.Add(mainExe);
                            modules.Add(runner.GetOutputFileName(_outputFolder, mainExe));
                            modules.UnionWith(_compilationInputFiles);
                            modules.UnionWith(_compilationInputFiles.Select(file => runner.GetOutputFileName(_outputFolder, file)));
                            folders.Add(Path.GetDirectoryName(mainExe));
                            folders.UnionWith(runner.ReferenceFolders);

                            appExecutions[(int)runner.Index] = new ProcessInfo(new AppExecutionProcessConstructor(runner, _outputFolder, mainExe, modules, folders));
                        }
                    }
                }
            }
        }
Exemple #9
0
        public BuildFolder(
            List <string> compilationInputFiles,
            List <string> mainExecutables,
            List <string> executionScripts,
            IEnumerable <CompilerRunner> compilerRunners,
            string inputFolder,
            string outputFolder,
            BuildOptions options)
        {
            _compilationInputFiles = compilationInputFiles;
            _mainExecutables       = mainExecutables;
            _executionScripts      = executionScripts;
            _inputFolder           = inputFolder;
            _outputFolder          = outputFolder;

            _compilations = new List <ProcessInfo[]>();
            _executions   = new List <ProcessInfo[]>();

            if (options.Composite)
            {
                ProcessInfo[] fileCompilations = new ProcessInfo[(int)CompilerIndex.Count];
                foreach (CompilerRunner runner in compilerRunners)
                {
                    string      outputFile         = runner.GetOutputFileName(_outputFolder, "composite-r2r.dll");
                    ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, outputFile, _compilationInputFiles));
                    fileCompilations[(int)runner.Index] = compilationProcess;
                }
                _compilations.Add(fileCompilations);
            }
            else
            {
                foreach (string file in _compilationInputFiles)
                {
                    ProcessInfo[] fileCompilations = new ProcessInfo[(int)CompilerIndex.Count];
                    foreach (CompilerRunner runner in compilerRunners)
                    {
                        string      outputFile         = runner.GetOutputFileName(_outputFolder, file);
                        ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, outputFile, new string[] { file }));
                        fileCompilations[(int)runner.Index] = compilationProcess;
                    }
                    _compilations.Add(fileCompilations);
                }
            }

            if (!options.NoExe)
            {
                foreach (string script in _executionScripts ?? Enumerable.Empty <string>())
                {
                    ProcessInfo[] scriptExecutions = new ProcessInfo[(int)CompilerIndex.Count];
                    _executions.Add(scriptExecutions);

                    foreach (CompilerRunner runner in compilerRunners)
                    {
                        HashSet <string> modules = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                        HashSet <string> folders = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                        modules.Add(runner.GetOutputFileName(_outputFolder, script));
                        modules.UnionWith(_compilationInputFiles);
                        modules.UnionWith(_compilationInputFiles.Select(file => runner.GetOutputFileName(_outputFolder, file)));
                        folders.Add(Path.GetDirectoryName(script));
                        folders.UnionWith(runner.ReferenceFolders);

                        scriptExecutions[(int)runner.Index] = new ProcessInfo(new ScriptExecutionProcessConstructor(runner, _outputFolder, script, modules, folders));
                    }
                }
            }
        }
Exemple #10
0
        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);
            }

            if (options.Composite)
            {
                // 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()));
                    }
                }
            }

            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));
        }
Exemple #11
0
        public static TestExclusionMap Create(BuildOptions options)
        {
            TestExclusionMap outputMap = new TestExclusionMap();

            if (options.IssuesPath != null)
            {
                Dictionary <string, List <TestExclusion> > exclusionsByCondition = new Dictionary <string, List <TestExclusion> >();

                foreach (FileInfo issuesProject in options.IssuesPath)
                {
                    string    issuesProjectPath = issuesProject.FullName;
                    XDocument issuesXml         = XDocument.Load(issuesProjectPath);
                    foreach (XElement itemGroupElement in issuesXml.Root.Elements(s_xmlNamespace + "ItemGroup"))
                    {
                        string condition = itemGroupElement.Attribute("Condition")?.Value ?? "";
                        List <TestExclusion> exclusions;
                        if (!exclusionsByCondition.TryGetValue(condition, out exclusions))
                        {
                            exclusions = new List <TestExclusion>();
                            exclusionsByCondition.Add(condition, exclusions);
                        }
                        foreach (XElement excludeListElement in itemGroupElement.Elements(s_xmlNamespace + "ExcludeList"))
                        {
                            string testPath = excludeListElement.Attribute("Include")?.Value ?? "";
                            string issueID  = excludeListElement.Element(s_xmlNamespace + "Issue")?.Value ?? "N/A";
                            exclusions.Add(CreateTestExclusion(testPath, issueID));
                        }
                    }
                }

                Project project = new Project();
                project.SetGlobalProperty("XunitTestBinBase", "*");
                project.SetGlobalProperty("BuildArch", "x64");
                // TODO: cross-OS CPAOT
                project.SetGlobalProperty("TargetsWindows", (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "true" : "false"));
                project.SetGlobalProperty("AltJitArch", "x64");
                project.SetGlobalProperty("RunTestViaIlLink", "false");

                ProjectRootElement root = project.Xml;
                root.AddTarget("GetListOfTestCmds");

                ProjectPropertyGroupElement propertyGroup = root.AddPropertyGroup();

                // Generate properties into the project to make it evaluate all conditions found in the targets file
                List <List <TestExclusion> > testExclusionLists = new List <List <TestExclusion> >();
                testExclusionLists.Capacity = exclusionsByCondition.Count;
                foreach (KeyValuePair <string, List <TestExclusion> > kvp in exclusionsByCondition)
                {
                    string propertyName = "Condition_" + testExclusionLists.Count.ToString();
                    bool   emptyKey     = string.IsNullOrEmpty(kvp.Key);
                    propertyGroup.AddProperty(propertyName, emptyKey ? "true" : "false");
                    if (!emptyKey)
                    {
                        propertyGroup.AddProperty(propertyName, "true").Condition = kvp.Key;
                    }
                    testExclusionLists.Add(kvp.Value);
                }

                project.Build();
                for (int exclusionListIndex = 0; exclusionListIndex < testExclusionLists.Count; exclusionListIndex++)
                {
                    string conditionValue = project.GetProperty("Condition_" + exclusionListIndex.ToString()).EvaluatedValue;
                    if (conditionValue.Equals("true", StringComparison.OrdinalIgnoreCase))
                    {
                        foreach (TestExclusion exclusion in testExclusionLists[exclusionListIndex])
                        {
                            outputMap.Add(exclusion);
                        }
                    }
                }
            }

            return(outputMap);
        }
Exemple #12
0
        public static int CompileSubtree(BuildOptions options)
        {
            if (options.InputDirectory == null)
            {
                Console.WriteLine("--input-directory is a required argument.");
                return(1);
            }

            if (options.OutputDirectory == null)
            {
                options.OutputDirectory = options.InputDirectory;
            }

            if (options.OutputDirectory.IsParentOf(options.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);
            }

            IEnumerable <string> referencePaths = options.ReferencePaths();

            IEnumerable <CompilerRunner> runners = options.CompilerRunners();

            PathExtensions.DeleteOutputFolders(options.OutputDirectory.ToString(), recursive: true);

            string[] directories = new string[] { options.InputDirectory.FullName }
            .Concat(
                options.InputDirectory
                .EnumerateDirectories("*", SearchOption.AllDirectories)
                .Select(dirInfo => dirInfo.FullName)
                .Where(path => !Path.GetExtension(path).Equals(".out", StringComparison.OrdinalIgnoreCase)))
            .ToArray();

            List <BuildFolder> folders = new List <BuildFolder>();
            int relativePathOffset     = directories[0].Length + 1;
            int count = 0;

            foreach (string directory in directories)
            {
                string outputDirectoryPerFolder = options.OutputDirectory.FullName;
                if (directory.Length > relativePathOffset)
                {
                    outputDirectoryPerFolder = Path.Combine(outputDirectoryPerFolder, directory.Substring(relativePathOffset));
                }
                try
                {
                    BuildFolder folder = BuildFolder.FromDirectory(directory.ToString(), runners, outputDirectoryPerFolder, options);
                    if (folder != null)
                    {
                        folders.Add(folder);
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("Error scanning folder {0}: {1}", directory, ex.Message);
                }
                if (++count % 100 == 0)
                {
                    Console.WriteLine($@"Found {folders.Count} folders to build ({count} / {directories.Length} folders scanned)");
                }
            }
            Console.WriteLine($@"Found {folders.Count} folders to build ({directories.Length} folders scanned)");

            string timeStamp        = DateTime.Now.ToString("MMdd-hhmm");
            string folderSetLogPath = Path.Combine(options.OutputDirectory.ToString(), "subtree-" + timeStamp + ".log");

            using (BuildFolderSet folderSet = new BuildFolderSet(folders, runners, options, folderSetLogPath))
            {
                bool success = folderSet.Build(runners, folderSetLogPath);

                Dictionary <string, List <ProcessInfo> > compilationFailureBuckets = new Dictionary <string, List <ProcessInfo> >();
                Dictionary <string, List <ProcessInfo> > executionFailureBuckets   = new Dictionary <string, List <ProcessInfo> >();

                string combinedSetLogPath = Path.Combine(options.OutputDirectory.ToString(), "combined-" + timeStamp + ".log");
                using (StreamWriter combinedLog = new StreamWriter(combinedSetLogPath))
                {
                    StreamWriter[] perRunnerLog = new StreamWriter[(int)CompilerIndex.Count];
                    foreach (CompilerRunner runner in runners)
                    {
                        string runnerLogPath = Path.Combine(options.OutputDirectory.ToString(), runner.CompilerName + "-" + timeStamp + ".log");
                        perRunnerLog[(int)runner.Index] = new StreamWriter(runnerLogPath);
                    }

                    foreach (BuildFolder folder in folderSet.BuildFolders)
                    {
                        foreach (ProcessInfo[] compilation in folder.Compilations)
                        {
                            foreach (CompilerRunner runner in runners)
                            {
                                ProcessInfo compilationProcess = compilation[(int)runner.Index];
                                if (compilationProcess != null)
                                {
                                    string log = $"\nCOMPILE {runner.CompilerName}:{compilationProcess.InputFileName}\n" + File.ReadAllText(compilationProcess.LogPath);
                                    perRunnerLog[(int)runner.Index].Write(log);
                                    combinedLog.Write(log);
                                    if (!compilationProcess.Succeeded)
                                    {
                                        string             bucket = AnalyzeCompilationFailure(compilationProcess);
                                        List <ProcessInfo> processes;
                                        if (!compilationFailureBuckets.TryGetValue(bucket, out processes))
                                        {
                                            processes = new List <ProcessInfo>();
                                            compilationFailureBuckets.Add(bucket, processes);
                                        }
                                        processes.Add(compilationProcess);
                                    }
                                }
                            }
                        }
                        foreach (ProcessInfo[] execution in folder.Executions)
                        {
                            foreach (CompilerRunner runner in runners)
                            {
                                ProcessInfo executionProcess = execution[(int)runner.Index];
                                if (executionProcess != null)
                                {
                                    string log = $"\nEXECUTE {runner.CompilerName}:{executionProcess.InputFileName}\n";
                                    try
                                    {
                                        log += File.ReadAllText(executionProcess.LogPath);
                                    }
                                    catch (Exception ex)
                                    {
                                        log += " -> " + ex.Message;
                                    }
                                    perRunnerLog[(int)runner.Index].Write(log);
                                    combinedLog.Write(log);

                                    if (!executionProcess.Succeeded)
                                    {
                                        string             bucket = AnalyzeExecutionFailure(executionProcess);
                                        List <ProcessInfo> processes;
                                        if (!executionFailureBuckets.TryGetValue(bucket, out processes))
                                        {
                                            processes = new List <ProcessInfo>();
                                            executionFailureBuckets.Add(bucket, processes);
                                        }
                                        processes.Add(executionProcess);
                                    }
                                }
                            }
                        }
                    }

                    foreach (CompilerRunner runner in runners)
                    {
                        perRunnerLog[(int)runner.Index].Dispose();
                    }
                }

                string compilationBucketsFile = Path.Combine(options.OutputDirectory.ToString(), "compilation-buckets-" + timeStamp + ".log");
                OutputBuckets(compilationFailureBuckets, compilationBucketsFile);

                string executionBucketsFile = Path.Combine(options.OutputDirectory.ToString(), "execution-buckets-" + timeStamp + ".log");
                OutputBuckets(executionFailureBuckets, executionBucketsFile);

                if (!options.NoCleanup)
                {
                    PathExtensions.DeleteOutputFolders(options.OutputDirectory.ToString(), recursive: true);
                }

                return(success ? 0 : 1);
            }
        }
Exemple #13
0
        public static int CompileNuget(BuildOptions options)
        {
            if (options.CoreRootDirectory == null)
            {
                Console.Error.WriteLine("--core-root-directory (--cr) is a required argument.");
                return(1);
            }

            // We don't want to launch these apps when building the folder set below
            options.NoExe          = true;
            options.NoJit          = true;
            options.InputDirectory = options.OutputDirectory;

            IList <string> packageList = ReadPackageNames(options.PackageList.FullName);

            if (options.OutputDirectory == null)
            {
                Console.Error.WriteLine("--output-directory is a required argument.");
                return(1);
            }

            IEnumerable <string>         referencePaths = options.ReferencePaths();
            IEnumerable <CompilerRunner> runners        = options.CompilerRunners(false);

            if (!options.Exe)
            {
                PathExtensions.DeleteOutputFolders(options.OutputDirectory.FullName, options.CoreRootDirectory.FullName, runners, recursive: false);
            }

            string nugetOutputFolder = Path.Combine(options.OutputDirectory.FullName, "nuget.out");

            Directory.CreateDirectory(nugetOutputFolder);

            var publishedAppFoldersToCompile = new List <BuildFolder>();

            using (StreamWriter nugetLog = File.CreateText(Path.Combine(nugetOutputFolder, "nugetLog.txt")))
            {
                foreach (var package in packageList)
                {
                    nugetLog.WriteLine($"Creating empty app for {package}");

                    // Create an app folder
                    string appFolder = Path.Combine(nugetOutputFolder, $"{package}.TestApp");
                    Directory.CreateDirectory(appFolder);

                    int exitCode = DotnetCli.New(appFolder, "console", nugetLog);
                    if (exitCode != 0)
                    {
                        nugetLog.WriteLine($"dotnet new console for {package} failed with exit code {exitCode}");
                        continue;
                    }

                    exitCode = DotnetCli.AddPackage(appFolder, package, nugetLog);
                    if (exitCode != 0)
                    {
                        nugetLog.WriteLine($"dotnet add package {package} failed with exit code {exitCode}");
                        continue;
                    }

                    exitCode = DotnetCli.Publish(appFolder, nugetLog);
                    if (exitCode != 0)
                    {
                        nugetLog.WriteLine($"dotnet publish failed with exit code {exitCode}");
                        continue;
                    }

                    // This is not a reliable way of building the publish folder
                    string publishFolder = Path.Combine(appFolder, @"artifacts\Debug\netcoreapp5.0\publish");
                    if (!Directory.Exists(publishFolder))
                    {
                        nugetLog.WriteLine($"Could not find folder {publishFolder} containing the published app.");
                        continue;
                    }

                    publishedAppFoldersToCompile.Add(BuildFolder.FromDirectory(publishFolder, runners, appFolder, options));
                }

                BuildFolderSet folderSet = new BuildFolderSet(publishedAppFoldersToCompile, runners, options);
                bool           success   = folderSet.Build();
                folderSet.WriteLogs();

                if (!options.NoCleanup && !options.Exe)
                {
                    PathExtensions.DeleteOutputFolders(options.OutputDirectory.FullName, options.CoreRootDirectory.FullName, runners, recursive: false);
                }

                return(success ? 0 : 1);
            }
        }