Пример #1
0
        static Tester()
        {
            TesterPath   = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
            TestCasePath = Path.Combine(TesterPath, "../../../../TestCases");
#if DEBUG
            testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Debug/net6.0-windows");
#else
            testRunnerBasePath = Path.Combine(TesterPath, "../../../../../ICSharpCode.Decompiler.TestRunner/bin/Release/net6.0-windows");
#endif
            packagesPropsFile   = Path.Combine(TesterPath, "../../../../../packages.props");
            roslynLatestVersion = XDocument.Load(packagesPropsFile).XPathSelectElement("//RoslynVersion").Value;
            roslynToolset       = new RoslynToolset();
            vswhereToolset      = new VsWhereToolset();
        }
Пример #2
0
        public static async Task <CompilerResults> CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
        {
            List <string> sourceFileNames = new List <string> {
                sourceFileName
            };

            foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
            {
                sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
            }
            bool targetNet40 = (flags & CompilerOptions.TargetNet40) != 0;
            bool useRoslyn   = (flags & CompilerOptions.UseRoslynMask) != 0;

            if (useRoslyn && !targetNet40)
            {
                sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
            }

            var preprocessorSymbols = GetPreprocessorSymbols(flags);

            if ((flags & CompilerOptions.UseMcsMask) == 0)
            {
                CompilerResults results = new CompilerResults();
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();

                var(roslynVersion, languageVersion) = (flags & CompilerOptions.UseRoslynMask) switch {
                    0 => ("legacy", "5"),
                    CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "6"),
                    CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
                    CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest"),
                    _ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
                };

                var cscPath = roslynToolset.GetCSharpCompiler(roslynVersion);

                string libPath;
                IEnumerable <string> references;
                if (useRoslyn && !targetNet40)
                {
                    libPath    = "\"" + coreRefAsmPath + "\"";
                    references = coreDefaultReferences.Select(r => "-r:\"" + Path.Combine(coreRefAsmPath, r) + "\"");
                }
                else
                {
                    libPath    = "\"" + RefAsmPath + "\",\"" + Path.Combine(RefAsmPath, "Facades") + "\"";
                    references = defaultReferences.Select(r => "-r:\"" + Path.Combine(RefAsmPath, r) + "\"");
                }
                if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
                {
                    references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
                }
                string otherOptions = $"-noconfig " +
                                      $"-langversion:{languageVersion} " +
                                      $"-unsafe -o{(flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ")}";

                // note: the /shared switch is undocumented. It allows us to use the VBCSCompiler.exe compiler
                // server to speed up testing
                if (roslynVersion != "legacy")
                {
                    otherOptions += "/shared ";
                    if (!targetNet40 && Version.Parse(RoslynToolset.SanitizeVersion(roslynVersion)).Major > 2)
                    {
                        if (flags.HasFlag(CompilerOptions.NullableEnable))
                        {
                            otherOptions += "/nullable+ ";
                        }
                        else
                        {
                            otherOptions += "/nullable- ";
                        }
                    }
                }

                if (flags.HasFlag(CompilerOptions.Library))
                {
                    otherOptions += "-t:library ";
                }
                else
                {
                    otherOptions += "-t:exe ";
                }

                if (flags.HasFlag(CompilerOptions.GeneratePdb))
                {
                    otherOptions += "-debug:full ";
                }
                else
                {
                    otherOptions += "-debug- ";
                }

                if (flags.HasFlag(CompilerOptions.Force32Bit))
                {
                    otherOptions += "-platform:x86 ";
                }
                else
                {
                    otherOptions += "-platform:anycpu ";
                }
                if (preprocessorSymbols.Count > 0)
                {
                    otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
                }

                var command = Cli.Wrap(cscPath)
                              .WithArguments($"{otherOptions} -lib:{libPath} {string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
                              .WithValidation(CommandResultValidation.None);
                Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");

                var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);

                Console.WriteLine("output: " + result.StandardOutput);
                Console.WriteLine("errors: " + result.StandardError);
                Assert.AreEqual(0, result.ExitCode, "csc failed");

                return(results);
            }
            else
            {
                CompilerResults results = new CompilerResults();
                results.PathToAssembly = outputFileName ?? Path.GetTempFileName();
                string testBasePath = RoundtripAssembly.TestDir;
                if (!Directory.Exists(testBasePath))
                {
                    Assert.Ignore($"Compilation with mcs ignored: test directory '{testBasePath}' needs to be checked out separately." + Environment.NewLine +
                                  $"git clone https://github.com/icsharpcode/ILSpy-tests \"{testBasePath}\"");
                }
                string mcsPath = (flags & CompilerOptions.UseMcsMask) switch {
                    CompilerOptions.UseMcs5_23 => Path.Combine(testBasePath, @"mcs\5.23\bin\mcs.bat"),
                    _ => Path.Combine(testBasePath, @"mcs\2.6.4\bin\gmcs.bat")
                };
                string otherOptions = " -unsafe -o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- ");

                if (flags.HasFlag(CompilerOptions.Library))
                {
                    otherOptions += "-t:library ";
                }
                else
                {
                    otherOptions += "-t:exe ";
                }

                if (flags.HasFlag(CompilerOptions.UseDebug))
                {
                    otherOptions += "-g ";
                }

                if (flags.HasFlag(CompilerOptions.Force32Bit))
                {
                    otherOptions += "-platform:x86 ";
                }
                else
                {
                    otherOptions += "-platform:anycpu ";
                }
                if (preprocessorSymbols.Count > 0)
                {
                    otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
                }

                var command = Cli.Wrap(mcsPath)
                              .WithArguments($"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
                              .WithValidation(CommandResultValidation.None);
                Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");

                var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);

                Console.WriteLine("output: " + result.StandardOutput);
                Console.WriteLine("errors: " + result.StandardError);
                Assert.AreEqual(0, result.ExitCode, "mcs failed");

                return(results);
            }
        }