Skip to content

Commit 2b01314

Browse files
Don't emit duplicate src files to binlog in CodeTaskFactory (#11965)
1 parent 601428b commit 2b01314

File tree

2 files changed

+80
-4
lines changed

2 files changed

+80
-4
lines changed

src/Tasks.UnitTests/CodeTaskFactoryTests.cs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ namespace Microsoft.Build.UnitTests
1616
#if FEATURE_CODETASKFACTORY
1717

1818
using System.CodeDom.Compiler;
19+
using System.IO.Compression;
20+
using Microsoft.Build.Logging;
1921
using Microsoft.Build.Tasks.UnitTests;
22+
using Shouldly;
2023

2124
public sealed class CodeTaskFactoryTests
2225
{
@@ -1200,6 +1203,79 @@ public void EmbedsGeneratedFileInBinlogWhenFailsToCompile()
12001203
CodeTaskFactoryEmbeddedFileInBinlogTestHelper.BuildAndCheckForEmbeddedFileInBinlog(
12011204
FactoryType.CodeTaskFactory, "HelloTask", taskXml, false);
12021205
}
1206+
1207+
[Fact]
1208+
public void ShouldEmitSingleGeneratedFileIntoBinlog()
1209+
{
1210+
using var env = TestEnvironment.Create();
1211+
1212+
// Define task XML for Import.targets
1213+
string taskXml = @"
1214+
<Project>
1215+
<UsingTask
1216+
TaskName=""CustomTask""
1217+
TaskFactory=""CodeTaskFactory""
1218+
AssemblyFile=""$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll"">
1219+
<ParameterGroup>
1220+
<InputParameter ParameterType=""System.String"" />
1221+
<OutputParameter ParameterType=""System.String"" Output=""True"" />
1222+
</ParameterGroup>
1223+
<Task>
1224+
<Using Namespace=""System"" />
1225+
<Code Type=""Fragment"" Language=""cs"">
1226+
<![CDATA[
1227+
Console.WriteLine(this.InputParameter);
1228+
this.OutputParameter = ""Hello "" + this.InputParameter;
1229+
]]>
1230+
</Code>
1231+
</Task>
1232+
</UsingTask>
1233+
</Project>";
1234+
1235+
TransientTestFile importTargetsFile = env.CreateFile("Import.targets", taskXml);
1236+
1237+
// Define Another.proj content
1238+
string anotherContent = $@"<Project>
1239+
<Import Project=""{importTargetsFile.Path}"" />
1240+
<Target Name=""AnotherTarget"">
1241+
<CustomTask InputParameter=""Foo"">
1242+
<Output PropertyName=""TaskOutput"" TaskParameter=""OutputParameter"" />
1243+
</CustomTask>
1244+
<Message Text=""Output: $(TaskOutput)"" />
1245+
</Target>
1246+
</Project>";
1247+
1248+
TransientTestFile anotherProjFile = env.CreateFile("Another.proj", anotherContent);
1249+
1250+
// Define main.csproj content
1251+
string projectFileContent = $@"<Project>
1252+
<Import Project=""{importTargetsFile.Path}"" />
1253+
<Target Name=""Build"">
1254+
<MSBuild Projects=""{anotherProjFile.Path}"" Targets=""AnotherTarget"" />
1255+
<CustomTask InputParameter=""Bar"" />
1256+
</Target>
1257+
</Project>";
1258+
1259+
TransientTestFile binlog = env.ExpectFile(".binlog");
1260+
1261+
var binaryLogger = new BinaryLogger()
1262+
{
1263+
Parameters = $"LogFile={binlog.Path}",
1264+
CollectProjectImports = BinaryLogger.ProjectImportsCollectionMode.ZipFile,
1265+
};
1266+
1267+
Helpers.BuildProjectWithNewOMAndBinaryLogger(projectFileContent, binaryLogger, out bool result, out string projectDirectory);
1268+
1269+
Assert.True(result);
1270+
1271+
string projectImportsZipPath = Path.ChangeExtension(binlog.Path, ".ProjectImports.zip");
1272+
using var fileStream = new FileStream(projectImportsZipPath, FileMode.Open);
1273+
using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
1274+
1275+
// check to make sure that only 1 tmp file is created
1276+
var tmpFiles = zipArchive.Entries.Where(zE => zE.Name.EndsWith("CustomTask-compilation-file.tmp")).ToList();
1277+
tmpFiles.Count.ShouldBe(1, $"Expected exactly one file ending with 'CustomTask-compilation-file.tmp' in ProjectImports.zip, but found {tmpFiles.Count}.");
1278+
}
12031279
}
12041280
#else
12051281
public sealed class CodeTaskFactoryTests

src/Tasks/CodeTaskFactory.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -791,16 +791,16 @@ private Assembly CompileInMemoryAssembly()
791791
// Our code generation is complete, grab the source from the builder ready for compilation
792792
string fullCode = codeBuilder.ToString();
793793

794-
// Embed generated file in the binlog
795-
string fileNameInBinlog = $"{Guid.NewGuid()}-{_nameOfTask}-compilation-file.tmp";
796-
_log.LogIncludeGeneratedFile(fileNameInBinlog, fullCode);
797-
798794
var fullSpec = new FullTaskSpecification(finalReferencedAssemblies, fullCode);
799795
if (!s_compiledTaskCache.TryGetValue(fullSpec, out Assembly existingAssembly))
800796
{
801797
// Invokes compilation.
802798
CompilerResults compilerResults = provider.CompileAssemblyFromSource(compilerParameters, fullCode);
803799

800+
// Embed generated file in the binlog
801+
string fileNameInBinlog = $"{Guid.NewGuid()}-{_nameOfTask}-compilation-file.tmp";
802+
_log.LogIncludeGeneratedFile(fileNameInBinlog, fullCode);
803+
804804
string outputPath = null;
805805
if (compilerResults.Errors.Count > 0 || Environment.GetEnvironmentVariable("MSBUILDLOGCODETASKFACTORYOUTPUT") != null)
806806
{

0 commit comments

Comments
 (0)