Skip to content

Commit 05c84f0

Browse files
committed
Ensure Views dll are copied during P2P builds
FastUpToDateCheck in VS doesn't account for changes solely to .Views.dll. This causes referencing projects to be treated as up to date even though a referenced project rebuilt. Touch the marker file to cause referenced projects to rebuild. Fixes aspnet/Razor#2306 to cause it to treat
1 parent 8d99ba5 commit 05c84f0

4 files changed

Lines changed: 72 additions & 3 deletions

File tree

src/Microsoft.NET.Sdk.Razor/build/netstandard2.0/Sdk.Razor.CurrentVersion.targets

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,24 @@ Copyright (c) .NET Foundation. All rights reserved.
185185
<RazorIntermediateAssembly Condition="'$(RazorIntermediateAssembly)'==''" Include="$(IntermediateOutputPath)$(RazorTargetName).dll" />
186186
<!-- Used in Compilation.targets -->
187187
<_RazorDebugSymbolsIntermediatePath Condition="'$(_RazorDebugSymbolsProduced)'=='true'" Include="$(IntermediateOutputPath)$(RazorTargetName).pdb" />
188-
<!-- Add all cshtml files to UpToDateCheckInput - a collection used by the IDE's project system to determine if a project needs to be rebuilt -->
188+
</ItemGroup>
189+
190+
<ItemGroup>
191+
<!--
192+
Add all cshtml files to UpToDateCheckInput - a collection of files used by FastUpToDateCheck to determine
193+
if any of the the project inputs have changed.
194+
-->
189195
<UpToDateCheckInput Condition="'$(RazorCompileOnBuild)'=='true'" Include="@(Content->WithMetadataValue('Extension', '.cshtml'))" />
196+
197+
<!--
198+
Add Razor output files to UpToDateCheckBuilt - a collection of files used by FastUpToDateCheck to determine
199+
if any of the project's outputs have changed.
200+
-->
201+
<UpToDateCheckBuilt Include="@(RazorIntermediateAssembly)"
202+
Condition="'$(RazorCompileOnBuild)'=='true' AND '@(Content->WithMetadataValue('Extension', '.cshtml'))' != ''" />
190203
</ItemGroup>
191204

205+
192206
<!--
193207
These are the targets that generate code using Razor, separated from the main file for ease of maintenance.
194208
Most targets related to Razor code generation are defined there.
@@ -487,6 +501,15 @@ Copyright (c) .NET Foundation. All rights reserved.
487501

488502
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
489503
</Copy>
504+
505+
<!--
506+
FastUpToDate check in VS does not consider the Views dll when determining if referencing projects need to be rebuilt.
507+
We'll touch a marker file that is used during as input for up to date check. Based on
508+
https://github.com/Microsoft/msbuild/blob/637f06e31ef46892faeb40044899a62a15b77f79/src/Tasks/Microsoft.Common.CurrentVersion.targets#L4364-L4368
509+
-->
510+
<Touch Files="@(CopyUpToDateMarker)" AlwaysCreate="true" Condition="'@(_RazorAssembly)' != ''">
511+
<Output TaskParameter="TouchedFiles" ItemName="FileWrites" />
512+
</Touch>
490513

491514
</Target>
492515

test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.IO;
67
using System.Linq;
@@ -173,5 +174,46 @@ public async Task IncrementalBuild_WithP2P_WorksWhenBuildProjectReferencesIsDisa
173174
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.dll");
174175
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.pdb");
175176
}
177+
178+
[Fact]
179+
[InitializeTestProject("ClassLibrary")]
180+
public async Task Build_TouchesUpToDateMarkerFile()
181+
{
182+
var classLibraryDll = Path.Combine(IntermediateOutputPath, "ClassLibrary.dll");
183+
var classLibraryViewsDll = Path.Combine(IntermediateOutputPath, "ClassLibrary.Views.dll");
184+
var markerFile = Path.Combine(IntermediateOutputPath, "ClassLibrary.csproj.CopyComplete");
185+
186+
var result = await DotnetMSBuild("Build");
187+
Assert.BuildPassed(result);
188+
189+
Assert.FileExists(result, classLibraryDll);
190+
Assert.FileExists(result, classLibraryViewsDll);
191+
Assert.FileExists(result, markerFile);
192+
193+
// Gather thumbprints before incremental build.
194+
var classLibraryThumbPrint = GetThumbPrint(classLibraryDll);
195+
var classLibraryViewsThumbPrint = GetThumbPrint(classLibraryViewsDll);
196+
var markerFileThumbPrint = GetThumbPrint(markerFile);
197+
198+
result = await DotnetMSBuild("Build");
199+
Assert.BuildPassed(result);
200+
201+
// Verify thumbprint file is unchanged between true incremental builds
202+
Assert.Equal(classLibraryThumbPrint, GetThumbPrint(classLibraryDll));
203+
Assert.Equal(classLibraryViewsThumbPrint, GetThumbPrint(classLibraryViewsDll));
204+
// In practice, this should remain unchanged. However, since our tests reference
205+
// binaries from other projects, this file gets updated by Microsoft.Common.targets
206+
Assert.NotEqual(markerFileThumbPrint, GetThumbPrint(markerFile));
207+
208+
// Change a cshtml file and verify ClassLibrary.Views.dll and marker file are updated
209+
File.AppendAllText(Path.Combine(Project.DirectoryPath, "Views", "_ViewImports.cshtml"), Environment.NewLine);
210+
211+
result = await DotnetMSBuild("Build");
212+
Assert.BuildPassed(result);
213+
214+
Assert.Equal(classLibraryThumbPrint, GetThumbPrint(classLibraryDll));
215+
Assert.NotEqual(classLibraryViewsThumbPrint, GetThumbPrint(classLibraryViewsDll));
216+
Assert.NotEqual(markerFileThumbPrint, GetThumbPrint(markerFile));
217+
}
176218
}
177219
}

test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIntrospectionTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ public BuildIntrospectionTest(BuildServerTestFixture buildServer)
1818
[InitializeTestProject("SimpleMvc")]
1919
public async Task RazorSdk_AddsCshtmlFilesToUpToDateCheckInput()
2020
{
21-
var result = await DotnetMSBuild("_IntrospectUpToDateCheckInput");
21+
var result = await DotnetMSBuild("_IntrospectUpToDateCheck");
2222

2323
Assert.BuildPassed(result);
2424
Assert.BuildOutputContainsLine(result, $"UpToDateCheckInput: {Path.Combine("Views", "Home", "Index.cshtml")}");
2525
Assert.BuildOutputContainsLine(result, $"UpToDateCheckInput: {Path.Combine("Views", "_ViewStart.cshtml")}");
26+
Assert.BuildOutputContainsLine(result, $"UpToDateCheckBuilt: {Path.Combine(IntermediateOutputPath, "SimpleMvc.Views.dll")}");
2627
}
2728

2829
[Fact]

test/testapps/RazorTest.Introspection.targets

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
<Message Text="CompileResource: %(_RazorCoreCompileResourceInputs.Identity) %(_RazorCoreCompileResourceInputs.LogicalName)" Importance="High" />
88
</Target>
99

10-
<Target Name="_IntrospectUpToDateCheckInput">
10+
<Target Name="_IntrospectUpToDateCheck">
1111
<Message Text="UpToDateCheckInput: %(UpToDateCheckInput.Identity)" Importance="High" />
12+
<Message Text="No UpToDateCheckInput input found" Importance="High" Condition="'@(UpToDateCheckInput->Count)' == '0'" />
13+
<Message Text="UpToDateCheckBuilt: %(UpToDateCheckBuilt.Identity)" Importance="High" />
14+
<Message Text="No UpToDateCheckBuilt input found" Importance="High" Condition="'@(UpToDateCheckBuilt->Count)' == '0'" />
1215
</Target>
1316

1417
<Target Name="_IntrospectRazorCompileItems">

0 commit comments

Comments
 (0)