Adds support for Razor compilation at build-time
This PR adds two new tools as well as a tasks project. None of these projects produce a package and they ship as part of Microsoft.AspNetCore.Razor.Design. For now this is a 'fat' package that contains all of the dependencies, but we plan to strip them out in the future. The support for compilation at build-time will start as **off** by default. The immediate goal here is to get this to flow through the build so that we can test it as part of the inner loop effort. We will enable this feature by default once we've done more thorough testing. Since this is mostly a code dump, I plan to address blocking and minor feedback only. If there are design issues that are non-critical, I will open follow up items. The next step will be to start adding more detailed tests.
This commit is contained in:
parent
18ce7f07ac
commit
a3fef5eeaa
|
|
@ -7,6 +7,7 @@
|
|||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/msbuild/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/roslyn/api/v3/index.json;
|
||||
https://vside.myget.org/F/vssdk/api/v3/index.json;
|
||||
https://vside.myget.org/F/vsmac/api/v3/index.json
|
||||
|
|
|
|||
|
|
@ -1,9 +1,109 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project>
|
||||
|
||||
<!-- Using explicit SDK imports here because the default way conflicts with the AfterBuild target -->
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains MSBuild support for Razor.</Description>
|
||||
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
|
||||
|
||||
<!--
|
||||
Using netcoreapp2.0 here is a workaround for https://github.com/Microsoft/msbuild/issues/2661
|
||||
|
||||
We need to use a P2P reference to build some other projects that need to target netcoreapp2.0
|
||||
and even though we don't actually want to reference the output, MSBuild will not allow it.
|
||||
-->
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
||||
<!-- This project doesn't have any code, so don't include it in the .nupkg -->
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Building this package is somewhat complicated because we need to Build or Publish some other projects
|
||||
that have different TFM's including one with multiple TFMs.
|
||||
|
||||
</Project>
|
||||
We then need to include the output of those projects in our output directory (where it will be used
|
||||
by tests) and in the nukpg.
|
||||
-->
|
||||
<ItemGroup>
|
||||
|
||||
<!-- These are just normal MSBuild files that we want to include in the package -->
|
||||
<Content Include="build\**\*.props" PackagePath="build\"/>
|
||||
<Content Include="build\**\*.targets" PackagePath="build\"/>
|
||||
<Content Include="buildMultiTargeting\*.props" PackagePath="buildMultiTargeting\"/>
|
||||
<Content Include="buildMultiTargeting\*.targets" PackagePath="buildMultiTargeting\"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- This is the tasks project that needs to be included in the package. -->
|
||||
<ItemGroup>
|
||||
<TaskProject Include="..\Microsoft.AspNetCore.Razor.Tasks\Microsoft.AspNetCore.Razor.Tasks.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- These are tools that need to be included in the package. -->
|
||||
<ItemGroup>
|
||||
<ToolProject Include="..\Microsoft.AspNetCore.Razor.GenerateTool\Microsoft.AspNetCore.Razor.GenerateTool.csproj"/>
|
||||
<ToolProject Include="..\Microsoft.AspNetCore.Razor.TagHelperTool\Microsoft.AspNetCore.Razor.TagHelperTool.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Using explicit SDK imports here because the default way conflicts with the AfterBuild target -->
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);_BuildDependencyProjects</GenerateNuspecDependsOn>
|
||||
<BuildDependsOn>_BuildDependencyProjects;$(BuildDependsOn)</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_BuildDependencyProjects">
|
||||
<!--
|
||||
The Microsoft.AspNetCore.Razor.Tasks package needs to support both net46 and netstandard2.0 for desktop vs
|
||||
coreclr MSBuild - so we have to build it twice.
|
||||
|
||||
We're careful here to avoid setting properties when building the other projects. This can create problems
|
||||
with concurrency.
|
||||
|
||||
First, build the project, then copy it to the ouput directory, then add it as packable content.
|
||||
-->
|
||||
<MSBuild Projects="@(TaskProject)"/>
|
||||
|
||||
<MSBuild
|
||||
Projects="@(TaskProject)"
|
||||
Properties="TargetFramework=net46"
|
||||
Targets="GetTargetPath">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNet46"/>
|
||||
</MSBuild>
|
||||
|
||||
<MSBuild
|
||||
Projects="@(TaskProject)"
|
||||
Properties="TargetFramework=netstandard2.0"
|
||||
Targets="GetTargetPath">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="TaskAssemblyNetStandard"/>
|
||||
</MSBuild>
|
||||
|
||||
<Copy SourceFiles="@(TaskAssemblyNet46)" DestinationFolder="$(OutputPath)\tasks\net46\">
|
||||
<Output TaskParameter="CopiedFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
<Copy SourceFiles="@(TaskAssemblyNetStandard)" DestinationFolder="$(OutputPath)\tasks\netstandard2.0\">
|
||||
<Output TaskParameter="CopiedFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="@(TaskAssemblyNet46)" PackagePath="tasks\net46\" Pack="true"/>
|
||||
<None Include="@(TaskAssemblyNetStandard)" PackagePath="tasks\netstandard2.0\" Pack="true"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
Next we need to build the netcoreapp2.0 tools. In this case we need to do a publish, because we need
|
||||
all of the output to put in the package.
|
||||
-->
|
||||
<RemoveDir Directories="tools\"/>
|
||||
<MSBuild Projects="@(ToolProject)"/>
|
||||
<MSBuild
|
||||
Projects="@(ToolProject)"
|
||||
Properties="PublishDir=$(MSBuildProjectDirectory)\$(OutputPath)tools\"
|
||||
Targets="Publish"/>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(OutputPath)tools\**\*" Exclude="$(OutputPath)tools\**\*.xml;$(OutputPath)tools\**\*.pdb" PackagePath="tools\" Pack="true"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<Project>
|
||||
<!--
|
||||
Properties supporting Razor MSBuild integration
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<RazorGenerateDependsOn></RazorGenerateDependsOn>
|
||||
<RazorCompileDependsOn></RazorCompileDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<Project>
|
||||
<!--
|
||||
Targets supporting Razor MSBuild integration
|
||||
-->
|
||||
|
||||
<Target Name="RazorGenerate" DependsOnTargets="$(RazorGenerateDependsOn)">
|
||||
</Target>
|
||||
|
||||
<Target Name="RazorCompile" DependsOnTargets="$(RazorCompileDependsOn)">
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<Project TreatAsLocalProperty="TaskFolder;TaskAssembly">
|
||||
<!--
|
||||
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>_RazorResolveTagHelpers;RazorCoreGenerate</RazorGenerateDependsOn>
|
||||
<RazorCompileDependsOn>_RazorResolveTagHelpers;RazorCoreGenerate;RazorCoreCompile</RazorCompileDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Razor also attaches itself by default to some of the standard .NET targets. Uses these properties to
|
||||
configure this behaviour.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<RazorCompileOnBuild Condition="'$(RazorCompileOnBuild)'==''">false</RazorCompileOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Override this to hijack the tasks and targets. Used by tests. -->
|
||||
<_RazorMSBuildRoot Condition="'$(_RazorMSBuildRoot)'==''">$(MSBuildThisFileDirectory)..\..\</_RazorMSBuildRoot>
|
||||
|
||||
<TaskFolder Condition=" '$(MSBuildRuntimeType)' == 'Core' ">netstandard2.0</TaskFolder>
|
||||
<TaskFolder Condition=" '$(MSBuildRuntimeType)' != 'Core' ">net46</TaskFolder>
|
||||
<TaskAssembly>$(_RazorMSBuildRoot)\tasks\$(TaskFolder)\Microsoft.AspNetCore.Razor.Tasks.dll</TaskAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.RazorGenerate" AssemblyFile="$(TaskAssembly)" />
|
||||
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.RazorTagHelper" AssemblyFile="$(TaskAssembly)" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
<Project>
|
||||
<!--
|
||||
Targets supporting Razor MSBuild integration
|
||||
-->
|
||||
<Target Name="RazorGenerate" DependsOnTargets="$(RazorGenerateDependsOn)">
|
||||
</Target>
|
||||
|
||||
<Target Name="RazorCompile" DependsOnTargets="$(RazorCompileDependsOn)">
|
||||
</Target>
|
||||
|
||||
<PropertyGroup Condition="'$(RazorCompileOnBuild)'=='true'">
|
||||
<BuildDependsOn>$(BuildDependsOn);RazorCompile</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Default values for properties that affect Razor MSBuild behavior.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<!-- Output directory used for generated files -->
|
||||
<RazorGenerateOutputPath Condition="'$(RazorGenerateOutputPath)'==''">$(IntermediateOutputPath)Razor\</RazorGenerateOutputPath>
|
||||
|
||||
<!-- File name (without extension) of the assembly produced by Razor -->
|
||||
<RazorTargetName Condition="'$(RazorTargetName)'==''">$(TargetName).PrecompiledViews</RazorTargetName>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- 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 creating the final compiled Razor dll -->
|
||||
<_RazorIntermediateAssembly>$(IntermediateOutputPath)$(RazorTargetName).dll</_RazorIntermediateAssembly>
|
||||
<_RazorIntermediatePdb>$(IntermediateOutputPath)$(RazorTargetName).pdb</_RazorIntermediatePdb>
|
||||
|
||||
<!-- Used to locate our tools -->
|
||||
<_RazorGenerateToolAssembly>$(_RazorMSBuildRoot)tools\Microsoft.AspNetCore.Razor.GenerateTool.dll</_RazorGenerateToolAssembly>
|
||||
<_RazorTagHelperToolAssembly>$(_RazorMSBuildRoot)tools\Microsoft.AspNetCore.Razor.TagHelperTool.dll</_RazorTagHelperToolAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Gathers input assemblies for Tag Helper discovery and compilation. Add items to @(ReferencePath)
|
||||
-->
|
||||
<Target
|
||||
Name="RazorResolveAssemblyReferences"
|
||||
DependsOnTargets="ResolveReferences">
|
||||
<ItemGroup>
|
||||
<RazorReferencePath Include="@(ReferencePath)"/>
|
||||
<RazorReferencePath Include="$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(TargetName)$(TargetExt)'))"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="_RazorResolveTagHelpers"
|
||||
DependsOnTargets="CoreCompile;RazorResolveAssemblyReferences"
|
||||
Inputs="$(MSBuildAllProjects);@(RazorReferencePath)"
|
||||
Outputs="$(_RazorTagHelperInputCache)">
|
||||
|
||||
<!--
|
||||
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)"
|
||||
Assemblies="@(RazorReferencePath)"
|
||||
TagHelperManifest="$(_RazorTagHelperOutputCache)">
|
||||
<Output
|
||||
TaskParameter="TagHelperManifest"
|
||||
ItemName="FileWrites"/>
|
||||
</RazorTagHelper>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_RazorResolveSourceFiles">
|
||||
<ItemGroup>
|
||||
<RazorCompile Include="@(Content)" Condition="'%(Content.Extension)'=='.cshtml'" />
|
||||
<_RazorGenerated Include="@(RazorCompile->'$(RazorGenerateOutputPath)%(RelativeDir)%(Filename).cs')">
|
||||
<Source>%(Identity)</Source>
|
||||
</_RazorGenerated>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="RazorCoreGenerate"
|
||||
DependsOnTargets="_RazorResolveSourceFiles;_RazorResolveTagHelpers"
|
||||
Inputs="$(MSBuildAllProjects);@(RazorCompile);$(_RazorTagHelperOutputCache)"
|
||||
Outputs="@(_RazorGenerated)">
|
||||
|
||||
<RemoveDir
|
||||
Directories="$(RazorGenerateOutputPath)"
|
||||
Condition = "Exists('$(RazorGenerateOutputPath)')"/>
|
||||
|
||||
<MakeDir
|
||||
Directories="%(_RazorGenerated.RelativeDir)"
|
||||
Condition="!Exists('%(_RazorGenerated.RelativeDir)')" />
|
||||
|
||||
<RazorGenerate
|
||||
Debug="$(_RazorDebugGenerateCodeTask)"
|
||||
DebugTool="$(_RazorDebugGenerateCodeTool)"
|
||||
ToolAssembly="$(_RazorGenerateToolAssembly)"
|
||||
Sources="@(RazorCompile)"
|
||||
ProjectRoot="$(MSBuildProjectDirectory)"
|
||||
TagHelperManifest="$(_RazorTagHelperOutputCache)"
|
||||
OutputPath="$(RazorGenerateOutputPath)" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="@(_RazorGenerated)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
What follows here was copied and modified from the XamlPreCompile target in
|
||||
Microsoft.CSharp.CurrentVersion.targets
|
||||
|
||||
The XamlPreCompile target must remain identical to
|
||||
the CoreCompile target in Microsoft.CSharp.Core.targets.
|
||||
Any updates to one must be made to the other.
|
||||
-->
|
||||
<Target
|
||||
Name="RazorCoreCompile"
|
||||
Inputs="$(MSBuildAllProjects);
|
||||
@(_RazorGenerated);
|
||||
@(_CoreCompileResourceInputs);
|
||||
$(ApplicationIcon);
|
||||
$(AssemblyOriginatorKeyFile);
|
||||
@(RazorReferencePath);"
|
||||
|
||||
Outputs="$(_RazorIntermediateAssembly)"
|
||||
Returns=""
|
||||
DependsOnTargets="_RazorResolveTagHelpers;RazorCoreGenerate">
|
||||
|
||||
<!-- 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,
|
||||
so the compiler warning would be redundant. -->
|
||||
<PropertyGroup Condition="('$(TargetFrameworkVersion)' != 'v1.0') and ('$(TargetFrameworkVersion)' != 'v1.1')">
|
||||
<NoWarn>$(NoWarn);1701;1702</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- To match historical behavior, when inside VS11+ disable the warning from csc.exe indicating that no sources were passed in-->
|
||||
<NoWarn Condition=" '$(BuildingInsideVisualStudio)' == 'true' and '$(VisualStudioVersion)' != '' and '$(VisualStudioVersion)' > '10.0' ">$(NoWarn);2008</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetingClr2Framework)'=='true'">
|
||||
<ReferencePath>
|
||||
<EmbedInteropTypes/>
|
||||
</ReferencePath>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- If the user has specified AppConfigForCompiler, we'll use it. If they have not, but they set UseAppConfigForCompiler,
|
||||
then we'll use AppConfig -->
|
||||
<AppConfigForCompiler Condition="'$(AppConfigForCompiler)' == '' and '$(UseAppConfigForCompiler)' == 'true'">$(AppConfig)</AppConfigForCompiler>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Prefer32Bit was introduced in .NET 4.5. Set it to false if we are targeting 4.0 -->
|
||||
<PropertyGroup Condition="('$(TargetFrameworkVersion)' == 'v4.0')">
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(UseSharedCompilation)' == ''">
|
||||
<UseSharedCompilation>true</UseSharedCompilation>
|
||||
</PropertyGroup>
|
||||
|
||||
<Csc
|
||||
AllowUnsafeBlocks="$(AllowUnsafeBlocks)"
|
||||
ApplicationConfiguration="$(AppConfigForCompiler)"
|
||||
BaseAddress="$(BaseAddress)"
|
||||
CheckForOverflowUnderflow="$(CheckForOverflowUnderflow)"
|
||||
CodePage="$(CodePage)"
|
||||
DebugType="$(DebugType)"
|
||||
DefineConstants="$(DefineConstants)"
|
||||
DelaySign="$(DelaySign)"
|
||||
DisabledWarnings="$(NoWarn)"
|
||||
EmitDebugInformation="$(DebugSymbols)"
|
||||
EnvironmentVariables="$(CscEnvironment)"
|
||||
ErrorEndLocation="$(ErrorEndLocation)"
|
||||
ErrorLog="$(ErrorLog)"
|
||||
ErrorReport="$(ErrorReport)"
|
||||
FileAlignment="$(FileAlignment)"
|
||||
GenerateFullPaths="$(GenerateFullPaths)"
|
||||
HighEntropyVA="$(HighEntropyVA)"
|
||||
KeyContainer="$(KeyContainerName)"
|
||||
KeyFile="$(KeyOriginatorFile)"
|
||||
LangVersion="$(LangVersion)"
|
||||
NoConfig="true"
|
||||
NoLogo="$(NoLogo)"
|
||||
NoStandardLib="$(NoCompilerStandardLib)"
|
||||
NoWin32Manifest="$(NoWin32Manifest)"
|
||||
Optimize="$(Optimize)"
|
||||
OutputAssembly="$(_RazorIntermediateAssembly)"
|
||||
PdbFile="$(_RazorIntermediatePdb)"
|
||||
Platform="$(PlatformTarget)"
|
||||
Prefer32Bit="$(Prefer32Bit)"
|
||||
PreferredUILang="$(PreferredUILang)"
|
||||
References="@(RazorReferencePath)"
|
||||
ReportAnalyzer="$(ReportAnalyzer)"
|
||||
ResponseFiles="$(CompilerResponseFile)"
|
||||
Sources="@(_RazorGenerated)"
|
||||
SubsystemVersion="$(SubsystemVersion)"
|
||||
TargetType="Library"
|
||||
ToolExe="$(CscToolExe)"
|
||||
ToolPath="$(CscToolPath)"
|
||||
TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
|
||||
UseHostCompilerIfAvailable="$(UseHostCompilerIfAvailable)"
|
||||
UseSharedCompilation="$(UseSharedCompilation)"
|
||||
Utf8Output="$(Utf8Output)"
|
||||
VsSessionGuid="$(VsSessionGuid)"
|
||||
WarningLevel="$(WarningLevel)"
|
||||
WarningsAsErrors="$(WarningsAsErrors)"
|
||||
WarningsNotAsErrors="$(WarningsNotAsErrors)"
|
||||
Win32Icon="$(ApplicationIcon)"
|
||||
Win32Manifest="$(Win32Manifest)"
|
||||
Win32Resource="$(Win32Resource)">
|
||||
<Output
|
||||
TaskParameter="OutputAssembly"
|
||||
ItemName="FileWrites" />
|
||||
</Csc>
|
||||
|
||||
<!-- Output the PDB and COPY of things to FileWrites -->
|
||||
<Message Importance="High" Text="$(_RazorIntermediateAssembly) -> $(OutDir)$(RazorTargetName)" />
|
||||
<Copy
|
||||
SourceFiles="$(_RazorIntermediateAssembly)"
|
||||
DestinationFolder="$(OutDir)"
|
||||
SkipUnchangedFiles="true"/>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
<Project>
|
||||
<Import Project="..\build\Microsoft.AspNetCore.Razor.Design.props" />
|
||||
<Import Project="..\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props" />
|
||||
</Project>
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
<Project>
|
||||
<Import Project="..\build\Microsoft.AspNetCore.Razor.Design.targets" />
|
||||
<Import Project="..\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.targets" />
|
||||
</Project>
|
||||
|
|
@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.Razor.GenerateTool
|
|||
Parallel.For(0, outputs.Length, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, i =>
|
||||
{
|
||||
var source = sources[i];
|
||||
|
||||
|
||||
var csharpDocument = templateEngine.GenerateCode(source.ViewEnginePath);
|
||||
outputs[i] = new OutputItem(source, csharpDocument);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
|
|
@ -17,6 +18,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
public static void FileExists(MSBuildResult result, string filePath)
|
||||
{
|
||||
NotNull(result);
|
||||
NotNull(filePath);
|
||||
|
||||
if (!File.Exists(Path.Combine(result.Project.DirectoryPath, filePath)))
|
||||
{
|
||||
throw new FileMissingException(result, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
private class BuildFailedException : Xunit.Sdk.XunitException
|
||||
{
|
||||
public BuildFailedException(MSBuildResult result)
|
||||
|
|
@ -42,5 +54,36 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FileMissingException : Xunit.Sdk.XunitException
|
||||
{
|
||||
public FileMissingException(MSBuildResult result, string filePath)
|
||||
{
|
||||
Result = result;
|
||||
FilePath = filePath;
|
||||
}
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public MSBuildResult Result { get; }
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
var message = new StringBuilder();
|
||||
message.Append($"File: '{FilePath}' was not found.");
|
||||
message.Append(Result.FileName);
|
||||
message.Append(" ");
|
||||
message.Append(Result.Arguments);
|
||||
message.AppendLine();
|
||||
message.AppendLine();
|
||||
message.Append(Result.Output);
|
||||
return message.ToString();
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,9 +12,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("SimpleMvc")]
|
||||
public async Task CleanProject_RunBuild()
|
||||
{
|
||||
var result = await DotnetMSBuild("Restore;Build"); // Equivalent to dotnet build
|
||||
var result = await DotnetMSBuild("Restore;Build", "/p:RazorCompileOnBuild=true");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
Assert.FileExists(result, @"bin/Debug/netcoreapp2.0/SimpleMvc.dll");
|
||||
Assert.FileExists(result, @"bin/Debug/netcoreapp2.0/SimpleMvc.PrecompiledViews.dll");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
#endif
|
||||
}
|
||||
|
||||
internal Task<MSBuildResult> DotnetMSBuild(string target)
|
||||
internal Task<MSBuildResult> DotnetMSBuild(string target, string args = null, bool debug = false)
|
||||
{
|
||||
return MSBuildProcessManager.RunProcessAsync($"/t:{target}", Project.DirectoryPath);
|
||||
var timeout = debug ? (TimeSpan?)Timeout.InfiniteTimeSpan : null;
|
||||
return MSBuildProcessManager.RunProcessAsync(Project, $"/t:{target} {args}", timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
{
|
||||
internal static class MSBuildProcessManager
|
||||
{
|
||||
public static Task<MSBuildResult> RunProcessAsync(string arguments, string workingDirectory, TimeSpan? timeout = null)
|
||||
public static Task<MSBuildResult> RunProcessAsync(ProjectDirectory project, string arguments, TimeSpan? timeout = null)
|
||||
{
|
||||
timeout = timeout ?? TimeSpan.FromSeconds(30);
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
{
|
||||
FileName = "dotnet",
|
||||
Arguments = "msbuild " + arguments,
|
||||
WorkingDirectory = workingDirectory,
|
||||
WorkingDirectory = project.DirectoryPath,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
void Process_Exited(object sender, EventArgs e)
|
||||
{
|
||||
var result = new MSBuildResult(process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, output.ToString());
|
||||
var result = new MSBuildResult(project, process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, output.ToString());
|
||||
completionSource.SetResult(result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,20 +5,23 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
{
|
||||
internal class MSBuildResult
|
||||
{
|
||||
public MSBuildResult(string fileName, string arguments, int exitCode, string output)
|
||||
public MSBuildResult(ProjectDirectory project, string fileName, string arguments, int exitCode, string output)
|
||||
{
|
||||
Project = project;
|
||||
FileName = fileName;
|
||||
Arguments = arguments;
|
||||
ExitCode = exitCode;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public ProjectDirectory Project { get; }
|
||||
|
||||
public string Arguments { get; }
|
||||
|
||||
public string FileName { get; }
|
||||
|
||||
public int ExitCode { get; }
|
||||
|
||||
|
||||
public string Output { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
CopyDirectory(new DirectoryInfo(projectRoot), new DirectoryInfo(destinationPath));
|
||||
|
||||
foreach (var project in Directory.EnumerateFiles(destinationPath, "*.csproj"))
|
||||
{
|
||||
RewriteCsproj(projectRoot, project);
|
||||
}
|
||||
CreateDirectoryProps(projectRoot, destinationPath);
|
||||
CreateDirectoryTargets(destinationPath);
|
||||
|
||||
return new ProjectDirectory(destinationPath);
|
||||
}
|
||||
|
|
@ -71,13 +69,35 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
void RewriteCsproj(string originalProjectRoot, string filePath)
|
||||
void CreateDirectoryProps(string originalProjectRoot, string projectRoot)
|
||||
{
|
||||
// We need to replace $(OriginalProjectRoot) with the path to the original directory
|
||||
// that way relative references will resolve.
|
||||
var text = File.ReadAllText(filePath);
|
||||
text = text.Replace("$(OriginalProjectRoot)", originalProjectRoot);
|
||||
File.WriteAllText(filePath, text);
|
||||
#if DEBUG
|
||||
var configuration = "Debug";
|
||||
#elif RELEASE
|
||||
var configuration = "Release";
|
||||
#else
|
||||
#error Unknown Configuration
|
||||
#endif
|
||||
var text = $@"
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<OriginalProjectRoot>{originalProjectRoot}</OriginalProjectRoot>
|
||||
<_RazorMSBuildRoot>$(OriginalProjectRoot)\..\..\..\src\Microsoft.AspNetCore.Razor.Design\bin\{configuration}\netstandard2.0\</_RazorMSBuildRoot>
|
||||
</PropertyGroup>
|
||||
<Import Project=""$(OriginalProjectRoot)\..\..\..\src\Microsoft.AspNetCore.Razor.Design\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props""/>
|
||||
</Project>
|
||||
";
|
||||
File.WriteAllText(Path.Combine(projectRoot, "Directory.Build.props"), text);
|
||||
}
|
||||
|
||||
void CreateDirectoryTargets(string projectRoot)
|
||||
{
|
||||
var text = $@"
|
||||
<Project>
|
||||
<Import Project=""$(OriginalProjectRoot)\..\..\..\src\Microsoft.AspNetCore.Razor.Design\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.targets""/>
|
||||
</Project>
|
||||
";
|
||||
File.WriteAllText(Path.Combine(projectRoot, "Directory.Build.targets"), text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||
<!--
|
||||
There's not much value in multi-targeting here, this doesn't run much .NET code, it tests MSBuild.
|
||||
|
||||
This is also a partial workaround for https://github.com/Microsoft/msbuild/issues/2661 - this project
|
||||
has netcoreapp2.0 dependencies that need to be built first.
|
||||
-->
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);TestFiles\**</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -18,4 +23,11 @@
|
|||
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- We don't need anything in this assembly, we just want to make sure it's built -->
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Razor.Design\Microsoft.AspNetCore.Razor.Design.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor
|
||||
{
|
||||
public abstract class RazorPage : RazorPageBase
|
||||
|
|
@ -16,5 +19,30 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
public override void EnsureRenderedBodyOrSections()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual IHtmlContent RenderBody()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public HtmlString RenderSection(string name)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public HtmlString RenderSection(string name, bool required)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<HtmlString> RenderSectionAsync(string name)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<HtmlString> RenderSectionAsync(string name, bool required)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ namespace SimpleMvc
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Just make sure we have a reference to the MvcShim
|
||||
var t = typeof(Microsoft.AspNetCore.Mvc.IActionResult);
|
||||
System.Console.WriteLine(t.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- In test scenarios $(OriginalProjectRoot) is defined in a generated Directory.Build.props file -->
|
||||
<ProjectReference Include="$(OriginalProjectRoot)\..\..\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.csproj"/>
|
||||
<ProjectReference Include="$(OriginalProjectRoot)\..\..\..\src\Microsoft.AspNetCore.Razor.Runtime\Microsoft.AspNetCore.Razor.Runtime.csproj"/>
|
||||
</ItemGroup>
|
||||
|
|
|
|||
Loading…
Reference in New Issue