diff --git a/.vscode/settings.json b/.vscode/settings.json index 2bf467f..f1ad1a5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,10 +11,13 @@ "Complogs", "cryptodir", "cryptokeyfile", + "inmemory", "jaredpar", "msbuild", "Mvid", "NETCOREAPP", + "netstandard", + "ondisk", "Relogger", "ruleset", "Xunit" diff --git a/src/Basic.CompilerLog.UnitTests/BinaryLogUtilTests.cs b/src/Basic.CompilerLog.UnitTests/BinaryLogUtilTests.cs index a9fc6fc..cfc82c1 100644 --- a/src/Basic.CompilerLog.UnitTests/BinaryLogUtilTests.cs +++ b/src/Basic.CompilerLog.UnitTests/BinaryLogUtilTests.cs @@ -21,13 +21,14 @@ namespace Basic.CompilerLog.UnitTests; public sealed class BinaryLogUtilTests { [Theory] - [InlineData("dotnet exec csc.dll a.cs", "a.cs")] - [InlineData("dotnet not what we expect a.cs", "")] - [InlineData("csc.exe a.cs b.cs", "a.cs b.cs")] - public void SkipCompilerExecutableTests(string args, string expected) + [InlineData("dotnet exec csc.dll a.cs", "csc.dll", "a.cs")] + [InlineData("dotnet not what we expect a.cs", null, "")] + [InlineData("csc.exe a.cs b.cs", "csc.exe", "a.cs b.cs")] + public void ParseCompilerAndArguments(string inputArgs, string? expectedCompilerFilePath, string expectedArgs) { - var realArgs = BinaryLogUtil.SkipCompilerExecutable(ToArray(args), "csc.exe", "csc.dll"); - Assert.Equal(ToArray(expected), realArgs); + var (actualCompilerFilePath, actualArgs) = BinaryLogUtil.ParseCompilerAndArguments(ToArray(inputArgs), "csc.exe", "csc.dll"); + Assert.Equal(ToArray(expectedArgs), actualArgs); + Assert.Equal(expectedCompilerFilePath, actualCompilerFilePath); static string[] ToArray(string arg) => arg.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries); } } diff --git a/src/Basic.CompilerLog.UnitTests/CompilerLogBuilderTests.cs b/src/Basic.CompilerLog.UnitTests/CompilerLogBuilderTests.cs index 541c923..6fed6ee 100644 --- a/src/Basic.CompilerLog.UnitTests/CompilerLogBuilderTests.cs +++ b/src/Basic.CompilerLog.UnitTests/CompilerLogBuilderTests.cs @@ -24,12 +24,33 @@ public void AddMissingFile() var compilerCall = BinaryLogUtil.ReadAllCompilerCalls(binlogStream, new()).First(x => x.IsCSharp); compilerCall = new CompilerCall( + compilerCall.CompilerFilePath, compilerCall.ProjectFilePath, CompilerCallKind.Regular, compilerCall.TargetFramework, isCSharp: true, new Lazy(() => ["/sourcelink:does-not-exist.txt"]), null); + Assert.Throws(() => builder.Add(compilerCall)); + } + + [Fact] + public void AddWithMissingCompilerFilePath() + { + using var stream = new MemoryStream(); + using var builder = new CompilerLogBuilder(stream, new()); + using var binlogStream = new FileStream(Fixture.ConsoleWithDiagnosticsBinaryLogPath, FileMode.Open, FileAccess.Read, FileShare.Read); + + var compilerCall = BinaryLogUtil.ReadAllCompilerCalls(binlogStream, new()).First(x => x.IsCSharp); + var args = compilerCall.GetArguments(); + compilerCall = new CompilerCall( + compilerFilePath: null, + compilerCall.ProjectFilePath, + CompilerCallKind.Regular, + compilerCall.TargetFramework, + isCSharp: true, + new Lazy(() => args), + null); builder.Add(compilerCall); } diff --git a/src/Basic.CompilerLog.UnitTests/CompilerLogReaderExTests.cs b/src/Basic.CompilerLog.UnitTests/CompilerLogReaderExTests.cs index 442685c..1e86d88 100644 --- a/src/Basic.CompilerLog.UnitTests/CompilerLogReaderExTests.cs +++ b/src/Basic.CompilerLog.UnitTests/CompilerLogReaderExTests.cs @@ -65,6 +65,7 @@ private CompilerLogReader ConvertConsoleArgs(Func func, Comp { var args = func(x.GetArguments()); return new CompilerCall( + x.CompilerFilePath, x.ProjectFilePath, x.Kind, x.TargetFramework, diff --git a/src/Basic.CompilerLog.UnitTests/ProgramTests.cs b/src/Basic.CompilerLog.UnitTests/ProgramTests.cs index ebb43aa..35df78a 100644 --- a/src/Basic.CompilerLog.UnitTests/ProgramTests.cs +++ b/src/Basic.CompilerLog.UnitTests/ProgramTests.cs @@ -1,16 +1,21 @@ #if NETCOREAPP using Basic.CompilerLog.Util; +using Basic.CompilerLog.Util.Serialize; +using MessagePack; using Microsoft.Build.Logging.StructuredLogger; using Microsoft.CodeAnalysis.CSharp; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; +using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; @@ -490,6 +495,40 @@ public void ReplayHelp() Assert.StartsWith("complog replay [OPTIONS]", output); } + [Fact] + public void ReplayNewCompiler() + { + string logFilePath = CreateBadLog(); + var (exitCode, output) = RunCompLogEx($"replay {logFilePath}"); + Assert.Equal(Constants.ExitSuccess, exitCode); + Assert.Contains("Compiler in log is newer than complog: 99.99.99.99 >", output); + + string CreateBadLog() + { + var logFilePath = Path.Combine(RootDirectory, "mutated.complog"); + CompilerLogUtil.ConvertBinaryLog( + Fixture.SolutionBinaryLogPath, + logFilePath, + cc => cc.ProjectFileName == "console.csproj"); + MutateArchive(logFilePath); + return logFilePath; + } + + static void MutateArchive(string complogFilePath) + { + using var fileStream = new FileStream(complogFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Update, leaveOpen: true); + using var entryStream = zipArchive.OpenEntryOrThrow(CommonUtil.GetCompilerEntryName(0)); + var infoPack = MessagePackSerializer.Deserialize(entryStream, CommonUtil.SerializerOptions); + infoPack.CompilerAssemblyName = Regex.Replace( + infoPack.CompilerAssemblyName!, + @"\d+\.\d+\.\d+\.\d+", + "99.99.99.99"); + entryStream.Position = 0; + MessagePackSerializer.Serialize(entryStream, infoPack, CommonUtil.SerializerOptions); + } + } + [Fact] public void ReplayBadOption() { @@ -499,7 +538,7 @@ public void ReplayBadOption() } [Fact] - public void RelpayBadOptionCombination() + public void ReplayBadOptionCombination() { var (exitCode, output) = RunCompLogEx($"replay -o example"); Assert.Equal(Constants.ExitFailure, exitCode); @@ -534,8 +573,23 @@ public void PrintOne() Assert.Contains("classlib.csproj (net7.0)", output); } + [Fact] + public void PrintCompilers() + { + var (exitCode, output) = RunCompLogEx($"print {Fixture.SolutionBinaryLogPath} -c"); + Assert.Equal(Constants.ExitSuccess, exitCode); + + using var reader = CompilerLogReader.Create(Fixture.ConsoleWithDiagnosticsBinaryLogPath); + var tuple = reader.ReadAllCompilerAssemblies().Single(); + Assert.Contains($""" + Compilers + {tuple.CompilerFilePath} + {tuple.AssemblyName} + """, output); + } + /// - /// Engage the code to find files in the specidied directory + /// Engage the code to find files in the specified directory /// [Fact] public void PrintDirectory() diff --git a/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs b/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs index 0667822..766afc9 100644 --- a/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs +++ b/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs @@ -111,6 +111,17 @@ public async Task CommandLineArguments() using var reader = CompilerLogReader.Create(complogPath, options: CompilerLogReaderOptions.None); foreach (var data in reader.ReadAllCompilerCalls()) { + var fileName = Path.GetFileName(complogPath); + if (fileName is "windows-console.complog" || + fileName is "linux-console.complog") + { + Assert.Null(data.CompilerFilePath); + } + else + { + Assert.NotNull(data.CompilerFilePath); + } + Assert.NotEmpty(data.GetArguments()); } } diff --git a/src/Basic.CompilerLog.Util/BinaryLogUtil.cs b/src/Basic.CompilerLog.Util/BinaryLogUtil.cs index c0a4d05..8a58d70 100644 --- a/src/Basic.CompilerLog.Util/BinaryLogUtil.cs +++ b/src/Basic.CompilerLog.Util/BinaryLogUtil.cs @@ -92,22 +92,23 @@ public CompilationTaskData(MSBuildProjectData projectData, int targetId) } var kind = Kind ?? CompilerCallKind.Unknown; - var args = CommandLineParser.SplitCommandLineIntoArguments(CommandLineArguments, removeHashComments: true); - var rawArgs = IsCSharp - ? SkipCompilerExecutable(args, "csc.exe", "csc.dll").ToArray() - : SkipCompilerExecutable(args, "vbc.exe", "vbc.dll").ToArray(); - if (rawArgs.Length == 0) + var rawArgs = CommandLineParser.SplitCommandLineIntoArguments(CommandLineArguments, removeHashComments: true); + var (compilerFilePath, args) = IsCSharp + ? ParseCompilerAndArguments(rawArgs, "csc.exe", "csc.dll") + : ParseCompilerAndArguments(rawArgs, "vbc.exe", "vbc.dll"); + if (args.Length == 0) { diagnosticList.Add($"Project {ProjectFile} ({TargetFramework}): bad argument list"); return null; } return new CompilerCall( + compilerFilePath, ProjectFile, kind, TargetFramework, isCSharp: IsCSharp, - new Lazy(() => rawArgs), + new Lazy(() => args), index: null); } } @@ -292,12 +293,13 @@ void SetTargetFramework(ref string? targetFramework, IEnumerable? rawProperties) /// The argument list is going to include either `dotnet exec csc.dll` or `csc.exe`. Need /// to skip past that to get to the real command line. /// - internal static IEnumerable SkipCompilerExecutable(IEnumerable args, string exeName, string dllName) + internal static (string? CompilerFilePath, string[] Arguments) ParseCompilerAndArguments(IEnumerable args, string exeName, string dllName) { using var e = args.GetEnumerator(); // The path to the executable is not escaped like the other command line arguments. Need // to skip until we see an exec or a path with the exe as the file name. + string? compilerFilePath = null; var found = false; while (e.MoveNext()) { @@ -305,12 +307,14 @@ internal static IEnumerable SkipCompilerExecutable(IEnumerable a { if (e.MoveNext() && PathUtil.Comparer.Equals(Path.GetFileName(e.Current), dllName)) { + compilerFilePath = e.Current; found = true; } break; } else if (e.Current.EndsWith(exeName, PathUtil.Comparison)) { + compilerFilePath = e.Current; found = true; break; } @@ -318,12 +322,15 @@ internal static IEnumerable SkipCompilerExecutable(IEnumerable a if (!found) { - yield break; + return (null, Array.Empty()); } + var list = new List(); while (e.MoveNext()) { - yield return e.Current; + list.Add(e.Current); } + + return (compilerFilePath, list.ToArray()); } } diff --git a/src/Basic.CompilerLog.Util/CompilerCall.cs b/src/Basic.CompilerLog.Util/CompilerCall.cs index fc8c082..317c40c 100644 --- a/src/Basic.CompilerLog.Util/CompilerCall.cs +++ b/src/Basic.CompilerLog.Util/CompilerCall.cs @@ -34,11 +34,17 @@ public enum CompilerCallKind Unknown } +/// +/// Represents a call to the compiler. The file paths and arguments provided here are correct +/// for the machine on which the compiler was run. They cannot be relied on to be correct on +/// machines where a compiler log is rehydrated. +/// public sealed class CompilerCall { private readonly Lazy _lazyArguments; - private readonly Lazy _lazyParsedArgumets; + private readonly Lazy _lazyParsedArguments; + public string? CompilerFilePath { get; } public string ProjectFilePath { get; } public CompilerCallKind Kind { get; } public string? TargetFramework { get; } @@ -50,6 +56,7 @@ public sealed class CompilerCall public string ProjectDirectory => Path.GetDirectoryName(ProjectFilePath)!; internal CompilerCall( + string? compilerFilePath, string projectFilePath, CompilerCallKind kind, string? targetFramework, @@ -57,13 +64,14 @@ internal CompilerCall( Lazy arguments, int? index) { + CompilerFilePath = compilerFilePath; ProjectFilePath = projectFilePath; Kind = kind; TargetFramework = targetFramework; IsCSharp = isCSharp; Index = index; _lazyArguments = arguments; - _lazyParsedArgumets = new Lazy(ParseArgumentsCore); + _lazyParsedArguments = new Lazy(ParseArgumentsCore); } public string GetDiagnosticName() @@ -81,7 +89,7 @@ public string GetDiagnosticName() public string[] GetArguments() => _lazyArguments.Value; - internal CommandLineArguments ParseArguments() => _lazyParsedArgumets.Value; + internal CommandLineArguments ParseArguments() => _lazyParsedArguments.Value; private CommandLineArguments ParseArgumentsCore() { diff --git a/src/Basic.CompilerLog.Util/CompilerLogBuilder.cs b/src/Basic.CompilerLog.Util/CompilerLogBuilder.cs index 1eed36e..3db2425 100644 --- a/src/Basic.CompilerLog.Util/CompilerLogBuilder.cs +++ b/src/Basic.CompilerLog.Util/CompilerLogBuilder.cs @@ -47,6 +47,7 @@ public bool Return(MemoryStream stream) private readonly Dictionary _mvidToRefInfoMap = new(); private readonly Dictionary _assemblyPathToMvidMap = new(PathUtil.Comparer); private readonly HashSet _contentHashMap = new(PathUtil.Comparer); + private readonly Dictionary _compilerAssemblyNameMap = new(PathUtil.Comparer); private readonly DefaultObjectPool _memoryStreamPool = new(new MemoryStreamPoolPolicy(), maximumRetained: 5); private int _compilationCount; @@ -66,38 +67,35 @@ internal CompilerLogBuilder(Stream stream, List diagnostics, int? metada Diagnostics = diagnostics; } - internal bool Add(CompilerCall compilerCall) + /// + /// Adds a compilation into the builder and returns the index of the entry + /// + internal void Add(CompilerCall compilerCall) { - try + var commandLineArguments = compilerCall.ParseArguments(); + var infoPack = new CompilationInfoPack() { - var commandLineArguments = compilerCall.ParseArguments(); - var infoPack = new CompilationInfoPack() - { - ProjectFilePath = compilerCall.ProjectFilePath, - IsCSharp = compilerCall.IsCSharp, - TargetFramework = compilerCall.TargetFramework, - CompilerCallKind = compilerCall.Kind, - CommandLineArgsHash = AddContentMessagePack(compilerCall.GetArguments()), - CompilationDataPackHash = AddCompilationDataPack(commandLineArguments), - }; - - AddCompilationOptions(infoPack, commandLineArguments, compilerCall); - - var entry = ZipArchive.CreateEntry(GetCompilerEntryName(_compilationCount), CompressionLevel.Fastest); - using (var entryStream = entry.Open()) - { - MessagePackSerializer.Serialize(entryStream, infoPack, SerializerOptions); - } - - _compilationCount++; - return true; - } - catch (Exception ex) + CompilerFilePath = compilerCall.CompilerFilePath, + ProjectFilePath = compilerCall.ProjectFilePath, + IsCSharp = compilerCall.IsCSharp, + TargetFramework = compilerCall.TargetFramework, + CompilerCallKind = compilerCall.Kind, + CommandLineArgsHash = AddContentMessagePack(compilerCall.GetArguments()), + CompilationDataPackHash = AddCompilationDataPack(commandLineArguments), + CompilerAssemblyName = AddCompilerAssemblyName(), + }; + + AddCompilationOptions(infoPack, commandLineArguments, compilerCall); + + var index = _compilationCount; + var entry = ZipArchive.CreateEntry(GetCompilerEntryName(index), CompressionLevel.Fastest); + using (var entryStream = entry.Open()) { - Diagnostics.Add($"Error adding {compilerCall.ProjectFilePath}: {ex.Message}"); - return false; + MessagePackSerializer.Serialize(entryStream, infoPack, SerializerOptions); } + _compilationCount++; + string AddCompilationDataPack(CommandLineArguments commandLineArguments) { var dataPack = new CompilationDataPack() @@ -151,6 +149,24 @@ void AddContentIf(CompilationDataPack dataPack, RawContentKind kind, string? fil return Path.Combine(compilerCall.ProjectDirectory, filePath); } + string? AddCompilerAssemblyName() + { + if (compilerCall.CompilerFilePath is null) + { + return null; + } + + if (_compilerAssemblyNameMap.TryGetValue(compilerCall.CompilerFilePath, out var assemblyName)) + { + return assemblyName; + } + + var name = AssemblyName.GetAssemblyName(compilerCall.CompilerFilePath); + assemblyName = name.ToString(); + _compilerAssemblyNameMap[compilerCall.CompilerFilePath] = assemblyName; + return assemblyName; + } + void AddCompilationOptions(CompilationInfoPack infoPack, CommandLineArguments args, CompilerCall compilerCall) { infoPack.EmitOptionsHash = AddContentMessagePack(MessagePackUtil.CreateEmitOptionsPack(args.EmitOptions)); @@ -170,7 +186,6 @@ void AddCompilationOptions(CompilationInfoPack infoPack, CommandLineArguments ar MessagePackUtil.CreateVisualBasicCompilationOptionsPack((VisualBasicCompilationOptions)args.CompilationOptions)); } } - } public void Close() diff --git a/src/Basic.CompilerLog.Util/CompilerLogReader.cs b/src/Basic.CompilerLog.Util/CompilerLogReader.cs index ac86d19..d4064a0 100644 --- a/src/Basic.CompilerLog.Util/CompilerLogReader.cs +++ b/src/Basic.CompilerLog.Util/CompilerLogReader.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic; +using Microsoft.CodeAnalysis.VisualBasic.Syntax; using Microsoft.VisualBasic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; @@ -141,6 +142,7 @@ private CompilationInfoPack ReadCompilationInfo(int index) private CompilerCall ReadCompilerCallCore(int index, CompilationInfoPack pack) { return new CompilerCall( + NormalizePath(pack.CompilerFilePath), NormalizePath(pack.ProjectFilePath), pack.CompilerCallKind, pack.TargetFramework, @@ -220,6 +222,28 @@ public List ReadAllCompilerCalls(Func? predica return list; } + public List<(string CompilerFilePath, AssemblyName AssemblyName)> ReadAllCompilerAssemblies() + { + var list = new List<(string CompilerFilePath, AssemblyName AssemblyName)>(); + var map = new Dictionary(PathUtil.Comparer); + for (int i = 0; i < Count; i++) + { + var pack = GetOrReadCompilationInfo(i); + if (pack.CompilerFilePath is not null && + pack.CompilerAssemblyName is not null && + !map.ContainsKey(pack.CompilerFilePath)) + { + var name = new AssemblyName(pack.CompilerAssemblyName); + map[pack.CompilerFilePath] = name; + } + } + + return map + .OrderBy(x => x.Key, PathUtil.Comparer) + .Select(x => (x.Key, x.Value)) + .ToList(); + } + public (EmitOptions EmitOptions, ParseOptions ParseOptions, CompilationOptions CompilationOptions) ReadCompilerOptions(CompilerCall compilerCall) { var index = GetIndex(compilerCall); diff --git a/src/Basic.CompilerLog.Util/CompilerLogUtil.cs b/src/Basic.CompilerLog.Util/CompilerLogUtil.cs index 9c07d39..a368417 100644 --- a/src/Basic.CompilerLog.Util/CompilerLogUtil.cs +++ b/src/Basic.CompilerLog.Util/CompilerLogUtil.cs @@ -98,12 +98,14 @@ internal static ConvertBinaryLogResult TryConvertBinaryLog(Stream binaryLogStrea { if (predicate(compilerInvocation)) { - if (builder.Add(compilerInvocation)) + try { + builder.Add(compilerInvocation); included.Add(compilerInvocation); } - else + catch (Exception ex) { + diagnostics.Add($"Error adding {compilerInvocation.ProjectFilePath}: {ex.Message}"); success = false; } } diff --git a/src/Basic.CompilerLog.Util/Serialize/MessagePackTypes.cs b/src/Basic.CompilerLog.Util/Serialize/MessagePackTypes.cs index aa27a25..9a1420a 100644 --- a/src/Basic.CompilerLog.Util/Serialize/MessagePackTypes.cs +++ b/src/Basic.CompilerLog.Util/Serialize/MessagePackTypes.cs @@ -225,6 +225,10 @@ public class CompilationInfoPack public string ParseOptionsHash { get; set; } [Key(8)] public string CompilationOptionsHash { get; set; } + [Key(9)] + public string? CompilerFilePath { get; set; } + [Key(10)] + public string? CompilerAssemblyName { get; set; } } [MessagePackObject] diff --git a/src/Basic.CompilerLog/FilterOptionSet.cs b/src/Basic.CompilerLog/FilterOptionSet.cs index 308c9f8..f6ba93d 100644 --- a/src/Basic.CompilerLog/FilterOptionSet.cs +++ b/src/Basic.CompilerLog/FilterOptionSet.cs @@ -33,7 +33,6 @@ internal bool IncludeAnalyzers internal FilterOptionSet(bool analyzers = false) { Add("include", "include all compilation kinds", i => { if (i is not null) IncludeAllKinds = true; }); - Add("targetframework=", "", TargetFrameworks.Add, hidden: true); Add("f|framework=", "include only compilations for the target framework (allows multiple)", TargetFrameworks.Add); Add("p|project=", "include only compilations for the given project (allows multiple)", ProjectNames.Add); Add("n|projectName=", "include only compilations for the project", ProjectNames.Add, hidden: true); diff --git a/src/Basic.CompilerLog/Program.cs b/src/Basic.CompilerLog/Program.cs index b573cb0..2e31d18 100644 --- a/src/Basic.CompilerLog/Program.cs +++ b/src/Basic.CompilerLog/Program.cs @@ -150,7 +150,11 @@ void PrintUsage() int RunPrint(IEnumerable args) { - var options = new FilterOptionSet(); + var compilers = false; + var options = new FilterOptionSet() + { + { "c|compilers", "include compiler summary", c => compilers = c is not null }, + }; try { @@ -165,11 +169,22 @@ int RunPrint(IEnumerable args) using var reader = GetCompilerLogReader(compilerLogStream, leaveOpen: true); var compilerCalls = reader.ReadAllCompilerCalls(options.FilterCompilerCalls); + WriteLine("Projects"); foreach (var compilerCall in compilerCalls) { WriteLine(compilerCall.GetDiagnosticName()); } + if (compilers) + { + WriteLine("Compilers"); + foreach (var tuple in reader.ReadAllCompilerAssemblies()) + { + WriteLine(tuple.CompilerFilePath); + WriteLine(tuple.AssemblyName.ToString()); + } + } + return ExitSuccess; } catch (OptionException e) @@ -424,7 +439,7 @@ int RunReplay(IEnumerable args) } using var compilerLogStream = GetOrCreateCompilerLogStream(extra); - using var reader = GetCompilerLogReader(compilerLogStream, leaveOpen: true, options.Options); + using var reader = GetCompilerLogReader(compilerLogStream, leaveOpen: true, options.Options, checkVersion: true); var compilerCalls = reader.ReadAllCompilerCalls(options.FilterCompilerCalls); var exportUtil = new ExportUtil(reader, includeAnalyzers: options.IncludeAnalyzers); var sdkDirs = SdkUtil.GetSdkDirectories(); @@ -535,7 +550,7 @@ passed after --. return ExitSuccess; } -CompilerLogReader GetCompilerLogReader(Stream compilerLogStream, bool leaveOpen, CompilerLogReaderOptions? options = null) +CompilerLogReader GetCompilerLogReader(Stream compilerLogStream, bool leaveOpen, CompilerLogReaderOptions? options = null, bool checkVersion = false) { var reader = CompilerLogReader.Create(compilerLogStream, options, leaveOpen); if (reader.IsWindowsLog != RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -543,6 +558,18 @@ CompilerLogReader GetCompilerLogReader(Stream compilerLogStream, bool leaveOpen, WriteLine($"Compiler log generated on different operating system"); } + if (checkVersion) + { + var version = typeof(Compilation).Assembly.GetName().Version; + foreach (var tuple in reader.ReadAllCompilerAssemblies()) + { + if (tuple.AssemblyName.Version > version) + { + WriteLine($"Compiler in log is newer than complog: {tuple.AssemblyName.Version} > {version}"); + } + } + } + OnCompilerLogReader(reader); return reader; } diff --git a/src/Scratch/Scratch.cs b/src/Scratch/Scratch.cs index d9ffb6c..bf4bcfe 100644 --- a/src/Scratch/Scratch.cs +++ b/src/Scratch/Scratch.cs @@ -17,9 +17,9 @@ #pragma warning disable 8321 -PrintGeneratedFiles(); +// PrintGeneratedFiles(); -// var filePath = @"c:\users\jaredpar\temp\console\msbuild.binlog"; +var filePath = @"c:\users\jaredpar\temp\console\msbuild.binlog"; // var filePath = @"C:\Users\jaredpar\code\roslyn\artifacts\log\Debug\Build.complog"; // var filePath = @"C:\Users\jaredpar\code\vs-threading\msbuild.binlog"; // var filePath = @"c:\users\jaredpar\temp\Build.complog"; @@ -38,7 +38,8 @@ // Profile(); -ExportScratch(); +PrintCompilers(filePath); +// ExportScratch(); // await WorkspaceScratch(); // RoslynScratch(); // Sarif(); @@ -88,6 +89,16 @@ } */ +void PrintCompilers(string filePath) +{ + using var reader = CompilerLogReader.Create(filePath); + foreach (var info in reader.ReadAllCompilerAssemblies()) + { + Console.WriteLine(info.CompilerFilePath); + Console.WriteLine(info.AssemblyName); + } +} + static void Test(ITypeSymbol symbol) { if (symbol is not INamedTypeSymbol { IsGenericType: true } nt)