Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions src/Tasks.UnitTests/RegressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.IO;
using System.Threading;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests;
Expand Down Expand Up @@ -102,5 +103,97 @@ public void IsWellKnownAttributeValuePreserved()
MockLogger logger = new MockLogger(_output);
ObjectModelHelpers.BuildTempProjectFileExpectSuccess("Myapp.proj", logger);
}

/// <summary>
/// Test for https://github.com/dotnet/msbuild/issues/13478.
/// </summary>
[Fact]
public void CopyUpToDateMarkerTracksImplementationAssemblyWrites()
{
ObjectModelHelpers.DeleteTempProjectDirectory();
CreateCopyMarkerTestProject(produceReferenceAssembly: true);

MockLogger logger = new MockLogger(_output);

ObjectModelHelpers.BuildTempProjectFileExpectSuccess("MarkerTest.csproj", logger);

string markerPath = Path.Combine(ObjectModelHelpers.TempProjectDir, "obj", "Debug", "MarkerTest.csproj.Up2Date");
Assert.True(File.Exists(markerPath), $"Expected marker to exist at {markerPath}");
Comment thread
AlesProkop marked this conversation as resolved.
Resolved
DateTime markerAfterFirstBuild = File.GetLastWriteTimeUtc(markerPath);

ObjectModelHelpers.BuildTempProjectFileExpectSuccess("MarkerTest.csproj", logger);

DateTime markerAfterNoOpBuild = File.GetLastWriteTimeUtc(markerPath);
Assert.Equal(markerAfterFirstBuild, markerAfterNoOpBuild);
Comment thread
AlesProkop marked this conversation as resolved.
Resolved

string intermediateRefAssemblyPath = Path.Combine(ObjectModelHelpers.TempProjectDir, "obj", "Debug", "refint", "MarkerTest.dll");
Assert.True(File.Exists(intermediateRefAssemblyPath), $"Expected intermediate reference assembly to exist at {intermediateRefAssemblyPath}");
Comment thread
AlesProkop marked this conversation as resolved.
Resolved

Thread.Sleep(TimeSpan.FromSeconds(2));
File.WriteAllText(intermediateRefAssemblyPath, "Reference output changed");
Comment thread
AlesProkop marked this conversation as resolved.
Resolved

ObjectModelHelpers.BuildTempProjectFileExpectSuccess("MarkerTest.csproj", logger);

DateTime markerAfterReferenceAssemblyOnlyChange = File.GetLastWriteTimeUtc(markerPath);
Assert.Equal(markerAfterNoOpBuild, markerAfterReferenceAssemblyOnlyChange);
Comment thread
AlesProkop marked this conversation as resolved.
Resolved

Thread.Sleep(TimeSpan.FromSeconds(2));
Comment thread
AlesProkop marked this conversation as resolved.
Resolved
File.WriteAllText(Path.Combine(ObjectModelHelpers.TempProjectDir, "input.txt"), "changed");

ObjectModelHelpers.BuildTempProjectFileExpectSuccess("MarkerTest.csproj", logger);

DateTime markerAfterImplementationChange = File.GetLastWriteTimeUtc(markerPath);
Assert.True(
markerAfterImplementationChange > markerAfterReferenceAssemblyOnlyChange,
$"Expected marker to advance from {markerAfterReferenceAssemblyOnlyChange:O}, but it was {markerAfterImplementationChange:O}.");
Comment thread
AlesProkop marked this conversation as resolved.
Resolved
}

/// <summary>
/// Test for https://github.com/dotnet/msbuild/issues/13478.
/// </summary>
[Fact]
public void CopyUpToDateMarkerIsNotCreatedForMainAssemblyWritesWhenReferenceAssembliesAreNotProduced()
{
ObjectModelHelpers.DeleteTempProjectDirectory();
CreateCopyMarkerTestProject(produceReferenceAssembly: false);

MockLogger logger = new MockLogger(_output);

ObjectModelHelpers.BuildTempProjectFileExpectSuccess("MarkerTest.csproj", logger);

string markerPath = Path.Combine(ObjectModelHelpers.TempProjectDir, "obj", "Debug", "MarkerTest.csproj.Up2Date");
Assert.False(File.Exists(markerPath), $"Did not expect marker to exist at {markerPath}");
}

private static void CreateCopyMarkerTestProject(bool produceReferenceAssembly)
{
ObjectModelHelpers.CreateFileInTempProjectDirectory("input.txt", "initial");
ObjectModelHelpers.CreateFileInTempProjectDirectory("MarkerTest.csproj", $@"
<Project DefaultTargets=""Build"" xmlns=""msbuildnamespace"" ToolsVersion=""msbuilddefaulttoolsversion"">
<Import Project=""$(MSBuildToolsPath)\Microsoft.Common.props"" />

<PropertyGroup>
<AssemblyName>MarkerTest</AssemblyName>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>{MSBuildConstants.StandardTestTargetFrameworkVersion}</TargetFrameworkVersion>
<ProduceReferenceAssembly>{produceReferenceAssembly.ToString().ToLowerInvariant()}</ProduceReferenceAssembly>
</PropertyGroup>
Comment thread
AlesProkop marked this conversation as resolved.
Resolved

<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />

<Target Name=""CoreCompile""
Inputs=""input.txt""
Outputs=""@(IntermediateAssembly)"">
<MakeDir Directories=""@(IntermediateAssembly->'%(RootDir)%(Directory)');@(IntermediateRefAssembly->'%(RootDir)%(Directory)')"" />
<WriteLinesToFile File=""@(IntermediateAssembly)""
Lines=""Implementation output""
Overwrite=""true"" />
<WriteLinesToFile File=""@(IntermediateRefAssembly)""
Lines=""Reference output""
Overwrite=""true""
Condition=""'@(IntermediateRefAssembly)' != '' and !Exists('@(IntermediateRefAssembly)')"" />
</Target>
</Project>");
}
}
}
17 changes: 17 additions & 0 deletions src/Tasks/Microsoft.Common.CurrentVersion.targets
Original file line number Diff line number Diff line change
Expand Up @@ -4913,6 +4913,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<CopyBuildOutputToOutputDirectory Condition="'$(CopyBuildOutputToOutputDirectory)'==''">true</CopyBuildOutputToOutputDirectory>
<CopyOutputSymbolsToOutputDirectory Condition="'$(CopyOutputSymbolsToOutputDirectory)'==''">true</CopyOutputSymbolsToOutputDirectory>
<CopyDocumentationFileToOutputDirectory Condition="'$(CopyDocumentationFileToOutputDirectory)'==''">true</CopyDocumentationFileToOutputDirectory>
<_WroteMainAssemblyToOutputDirectory>false</_WroteMainAssemblyToOutputDirectory>
Comment thread
AlesProkop marked this conversation as resolved.
Resolved
</PropertyGroup>

<!-- Copy the build product (.dll or .exe). -->
Expand All @@ -4931,6 +4932,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.

<Output TaskParameter="DestinationFiles" ItemName="MainAssembly"/>
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
<Output TaskParameter="WroteAtLeastOneFile" PropertyName="_WroteMainAssemblyToOutputDirectory"/>

</Copy>

Expand All @@ -4948,6 +4950,21 @@ Copyright (C) Microsoft Corporation. All rights reserved.

<Message Importance="High" Text="$(MSBuildProjectName) -&gt; @(MainAssembly->'%(FullPath)')" Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)'!='true'" />

<!--
If this project produces reference assemblies and its implementation assembly changed,
subsequent builds of projects that depend on it may need to copy the updated implementation.
Touch the marker considered by those projects' up-to-date checks. This is separate from
_CopyFilesMarkedCopyLocal so implementation-only changes can advance the marker even when
no copy-local references were copied.
Comment thread
AlesProkop marked this conversation as resolved.
Resolved
-->
<Touch Files="@(CopyUpToDateMarker)"
AlwaysCreate="true"
Condition="'$(ProduceReferenceAssembly)' == 'true' and '$(_WroteMainAssemblyToOutputDirectory)' == 'true'" />

<ItemGroup Condition="'$(ProduceReferenceAssembly)' == 'true'">
<FileWrites Include="@(CopyUpToDateMarker)" />
</ItemGroup>

<!-- Copy the additional modules. -->
<Copy
SourceFiles="@(AddModules)"
Expand Down
Loading