Split up Razor SDK logic (#1934)

* Split up Razor SDK logic

Splitting the fragile parts of code generation into its own file. We're
possibly separating the Razor SDK into a part that ships in the dotnet
SDK and part that ships in a nupkg with the compiler.

This means defining more of a fixed lifecycle in the main file, and
treating our actual work as more like extensibility.
This commit is contained in:
Ryan Nowak 2018-01-17 12:52:17 -08:00 committed by GitHub
parent eb107092d9
commit 627696677c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 197 additions and 134 deletions

View File

@ -0,0 +1,126 @@
<Project>
<!--
Targets used for Razor SDK code generation. Support for the RazorCoreGenerate target.
-->
<!--
Consider these properties to be private to this targets file. The main Razor SDK should define all of the properties
that we use to pass data back and forth.
-->
<PropertyGroup>
<!-- Used for tag helper discovery -->
<_RazorTagHelperInputCache>$(IntermediateOutputPath)$(TargetName).TagHelpers.input.cache</_RazorTagHelperInputCache>
<_RazorTagHelperOutputCache>$(IntermediateOutputPath)$(TargetName).TagHelpers.output.cache</_RazorTagHelperOutputCache>
<!-- Used to locate our tools -->
<_RazorGenerateToolAssembly>$(_RazorMSBuildRoot)tools\Microsoft.AspNetCore.Razor.GenerateTool.dll</_RazorGenerateToolAssembly>
<_RazorTagHelperToolAssembly>$(_RazorMSBuildRoot)tools\Microsoft.AspNetCore.Razor.TagHelperTool.dll</_RazorTagHelperToolAssembly>
<!-- Used to hash file inputs for RazorGenerate -->
<_RazorGenerateInputsHash></_RazorGenerateInputsHash>
<_RazorGenerateInputsHashFile>$(IntermediateOutputPath)$(MSBuildProjectName).RazorCoreGenerate.cache</_RazorGenerateInputsHashFile>
</PropertyGroup>
<!--
This target will only be called when we have some .cshtml files that are going to participate in code generation.
This is part of the chain of targets that are called once we've actually committed to generating code.
-->
<Target
Name="_HashRazorGenerateInputs"
AfterTargets="ResolveRazorGenerateInputs"
Condition="'@(RazorGenerate)'!=''">
<Hash ItemsToHash="@(RazorGenerate)">
<Output TaskParameter="HashResult" PropertyName="_RazorGenerateInputsHash" />
</Hash>
<MakeDir
Directories="$(IntermediateOutputPath)"
Condition="!Exists('$(IntermediateOutputPath)')" />
<WriteLinesToFile
Lines="$(_RazorGenerateInputsHash)"
File="$(_RazorGenerateInputsHashFile)"
Overwrite="True"
WriteOnlyWhenDifferent="True" />
<ItemGroup>
<FileWrites Include="$(_RazorGenerateInputsHashFile)" />
</ItemGroup>
</Target>
<Target
Name="ResolveTagHelperRazorGenerateInputs"
DependsOnTargets="Compile"
Inputs="$(MSBuildAllProjects);@(RazorReferencePath)"
Outputs="$(_RazorTagHelperInputCache)"
Condition="'@(RazorGenerate)'!=''">
<!--
We're manipulating our output directly here because we want to separate the actual up-to-date check
of RazorCoreGenerate from the output of this target. Many times the set of tag helpers doesn't change
so we don't need to regenerate the code.
-->
<Touch
Files="$(_RazorTagHelperInputCache)"
AlwaysCreate="true">
<Output
TaskParameter="TouchedFiles"
ItemName="FileWrites" />
</Touch>
<RazorTagHelper
Debug="$(_RazorDebugTagHelperTask)"
DebugTool="$(_RazorDebugTagHelperTool)"
ToolAssembly="$(_RazorTagHelperToolAssembly)"
ServerAssembly="$(_RazorBuildServerAssembly)"
Assemblies="@(RazorReferencePath)"
TagHelperManifest="$(_RazorTagHelperOutputCache)">
<Output
TaskParameter="TagHelperManifest"
ItemName="FileWrites"/>
</RazorTagHelper>
</Target>
<Target Name="_ResolveRazorGenerateOutputs" AfterTargets="PrepareForRazorGenerate">
<ItemGroup>
<_RazorGenerateOutput Include="%(RazorGenerate.GeneratedOutput)" Condition="'%(RazorGenerate.GeneratedOutput)'!=''"/>
</ItemGroup>
</Target>
<Target
Name="RazorCoreGenerate"
Inputs="$(MSBuildAllProjects);$(_RazorGenerateInputsHashFile);$(_RazorTagHelperOutputCache);@(RazorGenerate)"
Outputs="@(_RazorGenerateOutput)"
Condition="'@(RazorGenerate)'!= ''">
<RemoveDir
Directories="$(RazorGenerateOutputPath)"
Condition = "Exists('$(RazorGenerateOutputPath)')"/>
<MakeDir
Directories="%(_RazorGenerateOutput.RelativeDir)"
Condition="!Exists('%(_RazorGenerateOutput.RelativeDir)')" />
<RazorGenerate
Debug="$(_RazorDebugGenerateCodeTask)"
DebugTool="$(_RazorDebugGenerateCodeTool)"
ToolAssembly="$(_RazorGenerateToolAssembly)"
Sources="@(RazorGenerate)"
ProjectRoot="$(MSBuildProjectDirectory)"
TagHelperManifest="$(_RazorTagHelperOutputCache)"
OutputPath="$(RazorGenerateOutputPath)" />
<ItemGroup>
<FileWrites Include="@(_RazorGenerateOutput)" />
</ItemGroup>
</Target>
<Target Name="_ResolveGeneratedRazorCompileInputs" BeforeTargets="ResolveRazorCompileInputs">
<ItemGroup>
<RazorCompile Include="@(_RazorGenerateOutput)" />
</ItemGroup>
</Target>
</Project>

View File

@ -11,7 +11,7 @@
embedded files and resources, these are already present in the application's assembly.
Changes:
Name="RazorCoreCompile" and DependsOnTarget="RazorCoreGenerate"
Name="RazorCoreCompile"
Replace @(Compile) with @(RazorCompile)
Replace @(_DebugSymbolsIntermediatePath) with @(_RazorDebugSymbolsIntermediatePath)
@ -47,7 +47,6 @@
Outputs="@(RazorIntermediateAssembly);
@(_RazorDebugSymbolsIntermediatePath);
$(NonExistentFile)"
DependsOnTargets="RazorCoreGenerate"
Condition="'@(RazorCompile)'!=''">
<!-- These two compiler warnings are raised when a reference is bound to a different version
than specified in the assembly reference version number. MSBuild raises the same warning in this case,

View File

@ -3,18 +3,6 @@
Properties and tasks supporting Razor MSBuild integration
-->
<!--
Razor defines two primary targets:
'RazorGenerate' - which updates generated code
'RazorCompile' - compiles an assembly from generated code
Use these properties to attach behavior to the corresponding target.
-->
<PropertyGroup>
<RazorGenerateDependsOn>RazorResolveGenerateInputs;RazorCoreGenerate</RazorGenerateDependsOn>
<RazorCompileDependsOn>RazorGenerate;RazorCoreCompile</RazorCompileDependsOn>
</PropertyGroup>
<!--
Razor also attaches itself by default to some of the standard .NET targets. Uses these properties to
configure this behaviour.

View File

@ -1,4 +1,9 @@
<Project>
<!--
Targets supporting Razor MSBuild integration. Contain support for generating C# code using Razor
and including the generated code in the project lifecycle, including compiling, publishing and producing
nuget packages.
-->
<!--
This is a hook to import a set of targets before the Razor targets. By default this is used by MvcPrecompilation
@ -6,20 +11,34 @@
-->
<Import Project="$(CustomBeforeRazorSdkTargets)" Condition="'$(CustomBeforeRazorSdkTargets)' != '' and Exists('$(CustomBeforeRazorSdkTargets)')"/>
<!--
Targets supporting Razor MSBuild integration
<!--
Razor defines two primary targets:
'RazorGenerate' - which updates generated code
'RazorCompile' - compiles an assembly from generated code
Use these properties and targets to attach behavior to the corresponding phase.
-->
<Import Project="Microsoft.AspNetCore.Razor.Design.Compilation.targets" />
<PropertyGroup>
<PrepareForRazorGenerateDependsOn>
ResolveRazorGenerateInputs;
ResolveAssemblyReferenceRazorGenerateInputs;
ResolveTagHelperRazorGenerateInputs
</PrepareForRazorGenerateDependsOn>
<Target Name="RazorGenerate" DependsOnTargets="$(RazorGenerateDependsOn)">
</Target>
<RazorGenerateDependsOn>
PrepareForRazorGenerate;
RazorCoreGenerate
</RazorGenerateDependsOn>
<PrepareForRazorCompileDependsOn>
RazorGenerate;
ResolveRazorCompileInputs;
</PrepareForRazorCompileDependsOn>
<Target Name="RazorCompile" DependsOnTargets="$(RazorCompileDependsOn)">
</Target>
<PropertyGroup Condition="'$(RazorCompileOnBuild)'=='true'">
<PrepareForRunDependsOn>RazorCompile;$(PrepareForRunDependsOn);_RazorCopyFilesToOutputDirectory</PrepareForRunDependsOn>
<GetCopyToOutputDirectoryItemsDependsOn>$(GetCopyToOutputDirectoryItemsDependsOn);_RazorGetCopyToOutputDirectoryItems</GetCopyToOutputDirectoryItemsDependsOn>
<RazorCompileDependsOn>
PrepareForRazorCompile;
RazorCoreCompile
</RazorCompileDependsOn>
</PropertyGroup>
<!--
@ -56,14 +75,6 @@
<!-- Implementation details here... -->
<PropertyGroup>
<!-- Used for tag helper discovery -->
<_RazorTagHelperInputCache>$(IntermediateOutputPath)$(TargetName).TagHelpers.input.cache</_RazorTagHelperInputCache>
<_RazorTagHelperOutputCache>$(IntermediateOutputPath)$(TargetName).TagHelpers.output.cache</_RazorTagHelperOutputCache>
<!-- Used to locate our tools -->
<_RazorGenerateToolAssembly>$(_RazorMSBuildRoot)tools\Microsoft.AspNetCore.Razor.GenerateTool.dll</_RazorGenerateToolAssembly>
<_RazorTagHelperToolAssembly>$(_RazorMSBuildRoot)tools\Microsoft.AspNetCore.Razor.TagHelperTool.dll</_RazorTagHelperToolAssembly>
<!-- Similar to https://github.com/Microsoft/msbuild/blob/908cc9ccd4961441628f68e37a148183a87bb067/src/Tasks/Microsoft.Common.CurrentVersion.targets#L146-L153 -->
<_RazorDebugSymbolsProduced>false</_RazorDebugSymbolsProduced>
<_RazorDebugSymbolsProduced Condition="'$(DebugSymbols)'=='true'">true</_RazorDebugSymbolsProduced>
@ -81,48 +92,45 @@
</ItemGroup>
<!--
Gathers input source files for code generation. This is a separate target so that we can avoid
lots of work when there are no inputs for code generation.
These are the targets that generate code using Razor, separated for the main file for ease of maintenance.
Notice there are plenty of Condition="'@(RazorGenerate)'!=''" to avoid running more expensive targets.
Most targets related to Razor code generation are defined there.
-->
<Target Name="RazorResolveGenerateInputs">
<ItemGroup>
<RazorGenerate Include="@(Content)" Condition="'%(Content.Extension)'=='.cshtml'" />
<_RazorGenerateOutput Include="@(RazorGenerate->'$(RazorGenerateOutputPath)%(RelativeDir)%(Filename).cs')" />
</ItemGroup>
<Import Project="Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets" />
<!--
These are the targets that actually do compilation using CSC, separated for the main file for ease of maintenance.
RazorCoreCompile should be defined there.
-->
<Import Project="Microsoft.AspNetCore.Razor.Design.Compilation.targets" />
<Target Name="PrepareForRazorGenerate" DependsOnTargets="$(PrepareForRazorGenerateDependsOn)">
</Target>
<Target Name="RazorGenerate" DependsOnTargets="$(RazorGenerateDependsOn)">
</Target>
<Target Name="PrepareForRazorCompile" DependsOnTargets="$(PrepareForRazorCompileDependsOn)">
</Target>
<Target Name="RazorCompile" DependsOnTargets="$(RazorCompileDependsOn)">
</Target>
<PropertyGroup Condition="'$(RazorCompileOnBuild)'=='true'">
<PrepareForRunDependsOn>RazorCompile;$(PrepareForRunDependsOn);_RazorCopyFilesToOutputDirectory</PrepareForRunDependsOn>
<GetCopyToOutputDirectoryItemsDependsOn>$(GetCopyToOutputDirectoryItemsDependsOn);_RazorGetCopyToOutputDirectoryItems</GetCopyToOutputDirectoryItemsDependsOn>
</PropertyGroup>
<!--
This target will only be called when we have some .cshtml files that are going to participate in code generation.
This is part of the chain of targets that are called once we've actually committed to generating code.
Gathers input source files for code generation. This is a separate target so that we can avoid
lots of work when there are no inputs for code generation.
-->
<Target
Name="_ResolveRazorCoreGenerateInputs"
DependsOnTargets="RazorResolveGenerateInputs"
Condition="'@(RazorGenerate)'!=''">
<PropertyGroup>
<_RazorGenerateHashFile>$(IntermediateOutputPath)$(MSBuildProjectName).RazorCoreGenerate.cache</_RazorGenerateHashFile>
</PropertyGroup>
<Hash ItemsToHash="@(RazorGenerate)" Condition="'@(RazorGenerate)'!=''">
<Output TaskParameter="HashResult" PropertyName="_RazorGenerateHash" />
</Hash>
<MakeDir
Directories="$(IntermediateOutputPath)"
Condition="!Exists('$(IntermediateOutputPath)')" />
<WriteLinesToFile
Lines="$(_RazorGenerateHash)"
File="$(_RazorGenerateHashFile)"
Overwrite="True"
WriteOnlyWhenDifferent="True" />
<Target Name="ResolveRazorGenerateInputs">
<ItemGroup>
<FileWrites Include="$(_RazorGenerateHashFile)" />
<RazorGenerate Include="@(Content)" Condition="'%(Content.Extension)'=='.cshtml'">
<GeneratedOutput>$(RazorGenerateOutputPath)%(RelativeDir)%(Filename).cs</GeneratedOutput>
</RazorGenerate>
</ItemGroup>
</Target>
@ -130,7 +138,7 @@
Gathers input assemblies for Tag Helper discovery and compilation. Add items to @(ReferencePath)
-->
<Target
Name="_RazorResolveReferences"
Name="ResolveAssemblyReferenceRazorGenerateInputs"
DependsOnTargets="ResolveReferences">
<ItemGroup>
<RazorReferencePath Include="@(ReferencePath)"/>
@ -138,73 +146,15 @@
</ItemGroup>
</Target>
<Target
Name="_RazorResolveTagHelpers"
DependsOnTargets="Compile;_RazorResolveReferences"
Inputs="$(MSBuildAllProjects);@(RazorReferencePath)"
Outputs="$(_RazorTagHelperInputCache)"
Condition="'@(RazorGenerate)'!=''">
<!--
We're manipulating our output directly here because we want to separate the actual up-to-date check
of RazorCoreGenerate from the output of this target. Many times the set of tag helpers doesn't change
so we don't need to regenerate the code.
-->
<Touch
Files="$(_RazorTagHelperInputCache)"
AlwaysCreate="true">
<Output
TaskParameter="TouchedFiles"
ItemName="FileWrites" />
</Touch>
<RazorTagHelper
Debug="$(_RazorDebugTagHelperTask)"
DebugTool="$(_RazorDebugTagHelperTool)"
ToolAssembly="$(_RazorTagHelperToolAssembly)"
ServerAssembly="$(_RazorBuildServerAssembly)"
Assemblies="@(RazorReferencePath)"
TagHelperManifest="$(_RazorTagHelperOutputCache)">
<Output
TaskParameter="TagHelperManifest"
ItemName="FileWrites"/>
</RazorTagHelper>
<!--
Gathers inputs to the RazorCoreCompile target into the @(RazorCompile) itemgroup.
This is marker target so that the code generation targets can attach.
-->
<Target Name="ResolveRazorCompileInputs">
</Target>
<Target
Name="RazorCoreGenerate"
DependsOnTargets="_ResolveRazorCoreGenerateInputs;_RazorResolveTagHelpers"
Inputs="$(MSBuildAllProjects);$(_RazorGenerateHashFile);$(_RazorTagHelperOutputCache);@(RazorGenerate)"
Outputs="@(_RazorGenerateOutput)"
Condition="'@(RazorGenerate)'!= ''">
<RemoveDir
Directories="$(RazorGenerateOutputPath)"
Condition = "Exists('$(RazorGenerateOutputPath)')"/>
<MakeDir
Directories="%(_RazorGenerateOutput.RelativeDir)"
Condition="!Exists('%(_RazorGenerateOutput.RelativeDir)')" />
<RazorGenerate
Debug="$(_RazorDebugGenerateCodeTask)"
DebugTool="$(_RazorDebugGenerateCodeTool)"
ToolAssembly="$(_RazorGenerateToolAssembly)"
Sources="@(RazorGenerate)"
ProjectRoot="$(MSBuildProjectDirectory)"
TagHelperManifest="$(_RazorTagHelperOutputCache)"
OutputPath="$(RazorGenerateOutputPath)" />
<ItemGroup>
<FileWrites Include="@(_RazorGenerateOutput)" />
<!-- These items are used by RazorCoreCompile -->
<RazorCompile Include="@(_RazorGenerateOutput)" />
</ItemGroup>
</Target>
<!--
<!--
This target is called after PrepareForPublish when RazorCompileOnBuild=true so that we can hook into publish.
This target just hooks up other targets since Publish and PrepareForPublish don't have a DependsOnTargets
property we can use.
@ -220,7 +170,7 @@
-->
<Target
Name="_RazorAddBuiltProjectOutputGroupOutput"
DependsOnTargets="RazorResolveGenerateInputs"
DependsOnTargets="ResolveRazorGenerateInputs"
BeforeTargets="BuiltProjectOutputGroup">
<ItemGroup Condition="'@(RazorGenerate)'!= '' and '$(RazorCompileOnBuild)' == 'true'">