Skip to content

Commit 8d99ba5

Browse files
committed
Make incremental build in VS copy output files
Fixes #2306
1 parent 4c8c86b commit 8d99ba5

5 files changed

Lines changed: 113 additions & 1 deletion

File tree

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ Copyright (c) .NET Foundation. All rights reserved.
7474
$(PrepareForRunDependsOn)
7575
</PrepareForRunDependsOn>
7676

77+
<GetCopyToOutputDirectoryItemsDependsOn>
78+
_RazorGetCopyToOutputDirectoryItems;
79+
$(GetCopyToOutputDirectoryItems)
80+
</GetCopyToOutputDirectoryItemsDependsOn>
81+
7782
</PropertyGroup>
7883

7984
<!--
@@ -266,6 +271,9 @@ Copyright (c) .NET Foundation. All rights reserved.
266271
<!--
267272
Gathers input source files for code generation. This is a separate target so that we can avoid
268273
lots of work when there are no inputs for code generation.
274+
275+
NOTE: This target is called as part of an incremental build scenario in VS. Do not perform any work
276+
outside of calculating RazorGenerate items in this target.
269277
-->
270278
<Target Name="ResolveRazorGenerateInputs">
271279
<!--
@@ -384,7 +392,7 @@ Copyright (c) .NET Foundation. All rights reserved.
384392
-->
385393
<Target
386394
Name="_RazorGetCopyToOutputDirectoryItems"
387-
BeforeTargets="GetCopyToOutputDirectoryItems"
395+
DependsOnTargets="ResolveRazorGenerateInputs"
388396
Condition="'$(ResolvedRazorCompileToolset)'=='RazorSdk' and '$(RazorCompileOnBuild)'=='true'">
389397

390398
<!--

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ public static void BuildOutputContainsLine(MSBuildResult result, string match)
100100
throw new BuildOutputMissingException(result, match);
101101
}
102102

103+
public static void BuildOutputDoesNotContainLine(MSBuildResult result, string match)
104+
{
105+
if (result == null)
106+
{
107+
throw new ArgumentNullException(nameof(result));
108+
}
109+
110+
if (match == null)
111+
{
112+
throw new ArgumentNullException(nameof(match));
113+
}
114+
115+
// We don't really need to search line by line, I'm doing this so that it's possible/easy to debug.
116+
var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
117+
for (var i = 0; i < lines.Length; i++)
118+
{
119+
var line = lines[i].Trim();
120+
if (line == match)
121+
{
122+
throw new BuildOutputContainsLineException(result, match);
123+
}
124+
}
125+
}
126+
103127
public static void FileContains(MSBuildResult result, string filePath, string match)
104128
{
105129
if (result == null)
@@ -432,6 +456,19 @@ public BuildOutputMissingException(MSBuildResult result, string match)
432456
protected override string Heading => $"Build did not contain the line: '{Match}'.";
433457
}
434458

459+
private class BuildOutputContainsLineException : MSBuildXunitException
460+
{
461+
public BuildOutputContainsLineException(MSBuildResult result, string match)
462+
: base(result)
463+
{
464+
Match = match;
465+
}
466+
467+
public string Match { get; }
468+
469+
protected override string Heading => $"Build output contains the line: '{Match}'.";
470+
}
471+
435472
private class FileContentFoundException : MSBuildXunitException
436473
{
437474
public FileContentFoundException(MSBuildResult result, string filePath, string content, string match)

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,42 @@ async Task VerifyError()
136136
Assert.FileDoesNotExist(result, IntermediateOutputPath, "Razor", "Views", "Home", "Index.cshtml.g.cs");
137137
}
138138
}
139+
140+
[Fact]
141+
[InitializeTestProject("AppWithP2PReference", additionalProjects: "ClassLibrary")]
142+
public async Task IncrementalBuild_WithP2P_WorksWhenBuildProjectReferencesIsDisabled()
143+
{
144+
// Simulates building the same way VS does by setting BuildProjectReferences=false.
145+
// With this flag, the only target called is GetCopyToOutputDirectoryItems on the referenced project.
146+
// We need to ensure that we continue providing Razor binaries and symbols as files to be copied over.
147+
var result = await DotnetMSBuild(target: default);
148+
149+
Assert.BuildPassed(result);
150+
151+
Assert.FileExists(result, OutputPath, "AppWithP2PReference.dll");
152+
Assert.FileExists(result, OutputPath, "AppWithP2PReference.Views.dll");
153+
Assert.FileExists(result, OutputPath, "ClassLibrary.dll");
154+
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.dll");
155+
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.pdb");
156+
157+
result = await DotnetMSBuild(target: "Clean", "/p:BuildProjectReferences=false", suppressRestore: true);
158+
Assert.BuildPassed(result);
159+
160+
Assert.FileDoesNotExist(result, OutputPath, "AppWithP2PReference.dll");
161+
Assert.FileDoesNotExist(result, OutputPath, "AppWithP2PReference.Views.dll");
162+
Assert.FileDoesNotExist(result, OutputPath, "ClassLibrary.dll");
163+
Assert.FileDoesNotExist(result, OutputPath, "ClassLibrary.Views.dll");
164+
Assert.FileDoesNotExist(result, OutputPath, "ClassLibrary.Views.pdb");
165+
166+
// dotnet msbuild /p:BuildProjectReferences=false
167+
result = await DotnetMSBuild(target: default, "/p:BuildProjectReferences=false", suppressRestore: true);
168+
169+
Assert.BuildPassed(result);
170+
Assert.FileExists(result, OutputPath, "AppWithP2PReference.dll");
171+
Assert.FileExists(result, OutputPath, "AppWithP2PReference.Views.dll");
172+
Assert.FileExists(result, OutputPath, "ClassLibrary.dll");
173+
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.dll");
174+
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.pdb");
175+
}
139176
}
140177
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,31 @@ public async Task RazorSdk_UsesUseSharedCompilationToSetDefaultValueOfUseRazorBu
4545
Assert.BuildPassed(result);
4646
Assert.BuildOutputContainsLine(result, "UseRazorBuildServer: false");
4747
}
48+
49+
[Fact]
50+
[InitializeTestProject("ClassLibrary")]
51+
public async Task GetCopyToOutputDirectoryItems_WhenNoFileIsPresent_ReturnsEmptySequence()
52+
{
53+
var result = await DotnetMSBuild(target: default);
54+
55+
Assert.BuildPassed(result);
56+
57+
Assert.FileExists(result, OutputPath, "ClassLibrary.dll");
58+
Assert.FileExists(result, OutputPath, "ClassLibrary.Views.dll");
59+
60+
result = await DotnetMSBuild(target: "GetCopyToOutputDirectoryItems", "/t:_IntrospectGetCopyToOutputDirectoryItems /p:BuildProjectReferences=false", suppressRestore: true);
61+
Assert.BuildPassed(result);
62+
Assert.BuildOutputContainsLine(result, "AllItemsFullPathWithTargetPath: ClassLibrary.Views.dll");
63+
Assert.BuildOutputContainsLine(result, "AllItemsFullPathWithTargetPath: ClassLibrary.Views.pdb");
64+
65+
// Remove all views from the class library
66+
Directory.Delete(Path.Combine(Project.DirectoryPath, "Views"), recursive: true);
67+
68+
// dotnet msbuild /p:BuildProjectReferences=false
69+
result = await DotnetMSBuild(target: "GetCopyToOutputDirectoryItems", "/t:_IntrospectGetCopyToOutputDirectoryItems /p:BuildProjectReferences=false", suppressRestore: true);
70+
71+
Assert.BuildOutputDoesNotContainLine(result, "AllItemsFullPathWithTargetPath: ClassLibrary.Views.dll");
72+
Assert.BuildOutputDoesNotContainLine(result, "AllItemsFullPathWithTargetPath: ClassLibrary.Views.pdb");
73+
}
4874
}
4975
}

test/testapps/RazorTest.Introspection.targets

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@
1818
<Target Name="_IntrospectUseRazorBuildServer">
1919
<Message Text="UseRazorBuildServer: $(UseRazorBuildServer)" Importance="High" />
2020
</Target>
21+
22+
<Target Name="_IntrospectGetCopyToOutputDirectoryItems">
23+
<Message Text="AllItemsFullPathWithTargetPath: %(AllItemsFullPathWithTargetPath.TargetPath)" Importance="High" />
24+
</Target>
2125
</Project>

0 commit comments

Comments
 (0)