コード例 #1
0
        public static int CompileFramework(BuildOptions options)
        {
            if (options.CoreRootDirectory == null)
            {
                Console.Error.WriteLine("--core-root-directory (--cr) is a required argument.");
                return(1);
            }

            string logsFolder = Path.Combine(options.CoreRootDirectory.FullName, "logs");

            Directory.CreateDirectory(logsFolder);
            options.OutputDirectory = new DirectoryInfo(logsFolder);
            options.Framework       = true;
            options.NoJit           = true;
            options.NoEtw           = true;
            options.NoExe           = true;

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

            BuildFolderSet folderSet = new BuildFolderSet(Array.Empty <BuildFolder>(), runners, options);
            bool           success   = folderSet.Build();

            folderSet.WriteLogs();

            return(success ? 0 : 1);
        }
コード例 #2
0
        public static int CompileDirectory(BuildOptions options)
        {
            if (options.InputDirectory == null)
            {
                Console.Error.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.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);
            }

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

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

            BuildFolder folder = BuildFolder.FromDirectory(options.InputDirectory.FullName, runners, options.OutputDirectory.FullName, options);

            if (folder == null)
            {
                Console.Error.WriteLine($"No managed app found in {options.InputDirectory.FullName}");
            }

            BuildFolderSet folderSet = new BuildFolderSet(new BuildFolder[] { folder }, 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);
        }
コード例 #3
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);
        }
コード例 #4
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\net5.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);
            }
        }
コード例 #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.CoreRootDirectory == null)
            {
                Console.Error.WriteLine("--core-root-directory (--cr) is a required argument.");
                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, new string[] { 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.OutputFileName}");
                    }
                }
            }

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

            return(success ? 0 : 1);
        }