Skip to content

Commit

Permalink
Embed source file from CodeTaskFactory and RoslynCodeTaskFactory in b…
Browse files Browse the repository at this point in the history
…inlog (#9746)

*Embed compilation file from CodeTaskFactory and RoslynCodeTaskFactory in binlog
  • Loading branch information
surayya-MS committed Mar 20, 2024
1 parent cd64b7b commit a95f582
Show file tree
Hide file tree
Showing 17 changed files with 479 additions and 3 deletions.
3 changes: 3 additions & 0 deletions src/Build.UnitTests/BackEnd/NodePackets_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void VerifyEventType()
ResponseFileUsedEventArgs responseFileUsed = new("path");
UninitializedPropertyReadEventArgs uninitializedPropertyRead = new("prop", "message", "help", "sender", MessageImportance.Normal);
EnvironmentVariableReadEventArgs environmentVariableRead = new("env", "message", "help", "sender", MessageImportance.Normal);
GeneratedFileUsedEventArgs generatedFileUsed = new GeneratedFileUsedEventArgs("path", "some content");

VerifyLoggingPacket(buildFinished, LoggingEventType.BuildFinishedEvent);
VerifyLoggingPacket(buildStarted, LoggingEventType.BuildStartedEvent);
Expand Down Expand Up @@ -106,6 +107,7 @@ public void VerifyEventType()
VerifyLoggingPacket(responseFileUsed, LoggingEventType.ResponseFileUsedEvent);
VerifyLoggingPacket(uninitializedPropertyRead, LoggingEventType.UninitializedPropertyRead);
VerifyLoggingPacket(environmentVariableRead, LoggingEventType.EnvironmentVariableReadEvent);
VerifyLoggingPacket(generatedFileUsed, LoggingEventType.GeneratedFileUsedEvent);
}

private static BuildEventContext CreateBuildEventContext()
Expand Down Expand Up @@ -307,6 +309,7 @@ public void TestTranslation()
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new GeneratedFileUsedEventArgs("path", "some content"),
};
foreach (BuildEventArgs arg in testArgs)
{
Expand Down
9 changes: 9 additions & 0 deletions src/Build.UnitTests/BuildEventArgsSerialization_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,15 @@ public void RoundtripResponseFileUsedEventArgs()
e => e.ResponseFilePath);
}

[Fact]
public void RoundtripGeneratedFileUsedEventArgs()
{
var args = new GeneratedFileUsedEventArgs("MSBuild.rsp", "");
Roundtrip(args,
e => e.FilePath,
e => e.Content);
}

[Fact]
public void RoundtripCriticalBuildMessageEventArgs()
{
Expand Down
4 changes: 3 additions & 1 deletion src/Build/Instance/TaskFactoryLoggingHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ internal bool IsEventSerializable(BuildEventArgs e)
#pragma warning disable SYSLIB0050
// Types which are not serializable and are not IExtendedBuildEventArgs as
// those always implement custom serialization by WriteToStream and CreateFromStream.
if (!e.GetType().GetTypeInfo().IsSerializable && e is not IExtendedBuildEventArgs)
if (!e.GetType().GetTypeInfo().IsSerializable &&
e is not IExtendedBuildEventArgs &&
e is not GeneratedFileUsedEventArgs)
#pragma warning restore SYSLIB0050
{
_loggingContext.LogWarning(null, new BuildEventFileInfo(string.Empty), "ExpectedEventToBeSerializable", e.GetType().Name);
Expand Down
1 change: 1 addition & 0 deletions src/Build/Logging/BinaryLogger/BinaryLogRecordKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public enum BinaryLogRecordKind
String,
TaskParameter,
ResponseFileUsed,
GeneratedFileUsed,
AssemblyLoad,
}
}
9 changes: 8 additions & 1 deletion src/Build/Logging/BinaryLogger/BinaryLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,16 @@ public sealed class BinaryLogger : ILogger
// - Making ProjectStartedEventArgs, ProjectEvaluationFinishedEventArgs, AssemblyLoadBuildEventArgs equal
// between de/serialization roundtrips.
// - Adding serialized events lengths - to support forward compatible reading
// version 19:
// - new record kind: GeneratedFileUsedEventArgs

// This should be never changed.
// The minimum version of the binary log reader that can read log of above version.
internal const int ForwardCompatibilityMinimalVersion = 18;

// The current version of the binary log representation.
// Changes with each update of the binary log format.
internal const int FileFormatVersion = 18;
internal const int FileFormatVersion = 19;

// The minimum version of the binary log reader that can read log of above version.
// This should be changed only when the binary log format is changed in a way that would prevent it from being
Expand Down Expand Up @@ -364,6 +366,11 @@ private void CollectImports(BuildEventArgs e)
{
projectImportsCollector.AddFile(responseFileArgs.ResponseFilePath);
}
else if (e is GeneratedFileUsedEventArgs generatedFileUsedEventArgs && generatedFileUsedEventArgs.FilePath != null)
{
string fullPath = Path.GetFullPath(generatedFileUsedEventArgs.FilePath);
projectImportsCollector.AddFileFromMemory(fullPath, generatedFileUsedEventArgs.Content);
}
}

/// <summary>
Expand Down
18 changes: 18 additions & 0 deletions src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ void HandleError(FormatErrorMessage msgFactory, bool noThrow, ReaderErrorType re
BinaryLogRecordKind.TargetSkipped => ReadTargetSkippedEventArgs(),
BinaryLogRecordKind.EnvironmentVariableRead => ReadEnvironmentVariableReadEventArgs(),
BinaryLogRecordKind.ResponseFileUsed => ReadResponseFileUsedEventArgs(),
BinaryLogRecordKind.GeneratedFileUsed => ReadGeneratedFileUsedEventArgs(),
BinaryLogRecordKind.PropertyReassignment => ReadPropertyReassignmentEventArgs(),
BinaryLogRecordKind.UninitializedPropertyRead => ReadUninitializedPropertyReadEventArgs(),
BinaryLogRecordKind.PropertyInitialValueSet => ReadPropertyInitialValueSetEventArgs(),
Expand Down Expand Up @@ -1112,6 +1113,23 @@ private BuildEventArgs ReadResponseFileUsedEventArgs()
return e;
}

private BuildEventArgs ReadGeneratedFileUsedEventArgs()
{
var fields = ReadBuildEventArgsFields();

string? filePath = ReadDeduplicatedString();
string? content = ReadDeduplicatedString();

if (filePath != null && content != null)
{
var e = new GeneratedFileUsedEventArgs(filePath, content);
SetCommonFields(e, fields);
return e;
}

return new GeneratedFileUsedEventArgs();
}

private BuildEventArgs ReadPropertyReassignmentEventArgs()
{
var fields = ReadBuildEventArgsFields(readImportance: true);
Expand Down
8 changes: 8 additions & 0 deletions src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ private BinaryLogRecordKind Write(BuildMessageEventArgs e)
switch (e)
{
case ResponseFileUsedEventArgs responseFileUsed: return Write(responseFileUsed);
case GeneratedFileUsedEventArgs generatedFileUsed: return Write(generatedFileUsed);
case TaskParameterEventArgs taskParameter: return Write(taskParameter);
case ProjectImportedEventArgs projectImported: return Write(projectImported);
case TargetSkippedEventArgs targetSkipped: return Write(targetSkipped);
Expand Down Expand Up @@ -556,6 +557,13 @@ private BinaryLogRecordKind Write(ResponseFileUsedEventArgs e)
WriteDeduplicatedString(e.ResponseFilePath);
return BinaryLogRecordKind.ResponseFileUsed;
}
private BinaryLogRecordKind Write(GeneratedFileUsedEventArgs e)
{
WriteMessageFields(e);
WriteDeduplicatedString(e.FilePath);
WriteDeduplicatedString(e.Content);
return BinaryLogRecordKind.GeneratedFileUsed;
}
private BinaryLogRecordKind Write(TaskCommandLineEventArgs e)
{
WriteMessageFields(e, writeMessage: false, writeImportance: true);
Expand Down
38 changes: 38 additions & 0 deletions src/Framework.UnitTests/GeneratedFileUsedEventArgs_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Shouldly;
using Xunit;

namespace Microsoft.Build.Framework.UnitTests
{
public class GeneratedFileUsedEventArgs_Tests
{
[Fact]
public void SerializationDeserializationTest()
{
string filePath = "path";
string content = "content";
GeneratedFileUsedEventArgs arg = new(filePath, content);

using MemoryStream stream = new MemoryStream();
using BinaryWriter bw = new BinaryWriter(stream);
arg.WriteToStream(bw);

stream.Position = 0;
using BinaryReader br = new BinaryReader(stream);
GeneratedFileUsedEventArgs argDeserialized = new();
int packetVersion = (Environment.Version.Major * 10) + Environment.Version.Minor;
argDeserialized.CreateFromStream(br, packetVersion);

argDeserialized.FilePath.ShouldBe(filePath);
argDeserialized.Content.ShouldBe(content);
}
}
}
58 changes: 58 additions & 0 deletions src/Framework/GeneratedFileUsedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;

namespace Microsoft.Build.Framework
{
/// <summary>
/// Arguments for the generated file used event
/// </summary>
public class GeneratedFileUsedEventArgs : BuildMessageEventArgs
{
public GeneratedFileUsedEventArgs()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="GeneratedFileUsedEventArgs"/> class.
/// </summary>
///
public GeneratedFileUsedEventArgs(string filePath, string content)
: base("", null, null, MessageImportance.Low)
{
FilePath = filePath;
Content = content;
}

/// <summary>
/// The file path relative to the current project.
/// </summary>
public string? FilePath { set; get; }

/// <summary>
/// The content of the file.
/// </summary>
public string? Content { set; get; }

internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);

if (FilePath != null && Content != null)
{
writer.Write(FilePath);
writer.Write(Content);
}
}

internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);

FilePath = reader.ReadString();
Content = reader.ReadString();
}
}
}
13 changes: 12 additions & 1 deletion src/Shared/LogMessagePacketBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ internal enum LoggingEventType : int
/// Event is <see cref="ExtendedCriticalBuildMessageEventArgs"/>
/// </summary>
ExtendedCriticalBuildMessageEvent = 33,

/// <summary>
/// Event is a <see cref="GeneratedFileUsedEventArgs"/>
/// </summary>
GeneratedFileUsedEvent = 34,
}
#endregion

Expand Down Expand Up @@ -589,7 +594,8 @@ private BuildEventArgs GetBuildEventArgFromId()
LoggingEventType.TaskFinishedEvent => new TaskFinishedEventArgs(null, null, null, null, null, false),
LoggingEventType.TaskCommandLineEvent => new TaskCommandLineEventArgs(null, null, MessageImportance.Normal),
LoggingEventType.EnvironmentVariableReadEvent => new EnvironmentVariableReadEventArgs(),
LoggingEventType.ResponseFileUsedEvent => new ResponseFileUsedEventArgs(null),
LoggingEventType.ResponseFileUsedEvent => new ResponseFileUsedEventArgs(null),

#if !TASKHOST // MSBuildTaskHost is targeting Microsoft.Build.Framework.dll 3.5
LoggingEventType.AssemblyLoadEvent => new AssemblyLoadBuildEventArgs(),
LoggingEventType.TaskParameterEvent => new TaskParameterEventArgs(0, null, null, true, default),
Expand All @@ -610,6 +616,7 @@ private BuildEventArgs GetBuildEventArgFromId()
LoggingEventType.PropertyInitialValueSet => new PropertyInitialValueSetEventArgs(),
LoggingEventType.PropertyReassignment => new PropertyReassignmentEventArgs(),
LoggingEventType.UninitializedPropertyRead => new UninitializedPropertyReadEventArgs(),
LoggingEventType.GeneratedFileUsedEvent => new GeneratedFileUsedEventArgs(),
#endif
_ => throw new InternalErrorException("Should not get to the default of GetBuildEventArgFromId ID: " + _eventType)
};
Expand Down Expand Up @@ -721,6 +728,10 @@ private LoggingEventType GetLoggingEventId(BuildEventArgs eventArg)
{
return LoggingEventType.UninitializedPropertyRead;
}
else if (eventType == typeof(GeneratedFileUsedEventArgs))
{
return LoggingEventType.GeneratedFileUsedEvent;
}
#endif
else if (eventType == typeof(TargetStartedEventArgs))
{
Expand Down
15 changes: 15 additions & 0 deletions src/Shared/TaskLoggingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,21 @@ public void LogMessageFromResources(MessageImportance importance, string message
#endif
}

/// <summary>
/// Logs a file generated from the given data.
/// </summary>
/// <param name="filePath">The file path relative to the currecnt project.</param>
/// <param name="content">The content of the file.</param>
public void LogIncludeGeneratedFile(string filePath, string content)
{
ErrorUtilities.VerifyThrowArgumentNull(filePath, nameof(filePath));
ErrorUtilities.VerifyThrowArgumentNull(content, nameof(content));

var e = new GeneratedFileUsedEventArgs(filePath, content);

BuildEngine.LogMessageEvent(e);
}

/// <summary>
/// Flatten the inner exception message
/// </summary>
Expand Down
Loading

0 comments on commit a95f582

Please sign in to comment.