Create a Blazor WebAssembly SDK (#24044)
This commit is contained in:
parent
5266918ed2
commit
e822f5f12d
|
|
@ -1427,6 +1427,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Web.Extensions.Tests", "src\Components\Web.Extensions\test\Microsoft.AspNetCore.Components.Web.Extensions.Tests.csproj", "{157605CB-5170-4C1A-980F-4BAE42DB60DE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{FED4267E-E5E4-49C5-98DB-8B3F203596EE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly", "src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj", "{6B2734BF-C61D-4889-ABBF-456A4075D59B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tests", "src\Components\WebAssembly\Sdk\test\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj", "{83371889-9A3E-4D16-AE77-EB4F83BC6374}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests", "src\Components\WebAssembly\Sdk\integrationtests\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj", "{525EBCB4-A870-470B-BC90-845306C337D1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tools", "src\Components\WebAssembly\Sdk\tools\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj", "{175E5CD8-92D4-46BB-882E-3A930D3302D4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -6729,6 +6739,54 @@ Global
|
|||
{157605CB-5170-4C1A-980F-4BAE42DB60DE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{157605CB-5170-4C1A-980F-4BAE42DB60DE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{157605CB-5170-4C1A-980F-4BAE42DB60DE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Release|x64.Build.0 = Release|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374}.Release|x86.Build.0 = Release|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -7444,6 +7502,11 @@ Global
|
|||
{F71FE795-9923-461B-9809-BB1821A276D0} = {60D51C98-2CC0-40DF-B338-44154EFEE2FF}
|
||||
{8294A74F-7DAA-4B69-BC56-7634D93C9693} = {F71FE795-9923-461B-9809-BB1821A276D0}
|
||||
{157605CB-5170-4C1A-980F-4BAE42DB60DE} = {F71FE795-9923-461B-9809-BB1821A276D0}
|
||||
{FED4267E-E5E4-49C5-98DB-8B3F203596EE} = {562D5067-8CD8-4F19-BCBB-873204932C61}
|
||||
{6B2734BF-C61D-4889-ABBF-456A4075D59B} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
{83371889-9A3E-4D16-AE77-EB4F83BC6374} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@
|
|||
@(ProjectToBuild);
|
||||
@(ProjectToExclude);
|
||||
$(RepoRoot)src\Razor\test\testassets\**\*.*proj;
|
||||
$(RepoRoot)src\Components\WebAssembly\Sdk\testassets\**\*.*proj;
|
||||
$(RepoRoot)**\node_modules\**\*;
|
||||
$(RepoRoot)**\bin\**\*;
|
||||
$(RepoRoot)**\obj\**\*;"
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@
|
|||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Web.Extensions" ProjectPath="$(RepoRoot)src\Components\Web.Extensions\src\Microsoft.AspNetCore.Components.Web.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Authentication.WebAssembly.Msal" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.NET.Sdk.BlazorWebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
|
||||
|
|
|
|||
|
|
@ -110,6 +110,9 @@
|
|||
"src\\Components\\WebAssembly\\WebAssembly.Authentication\\test\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Client\\Wasm.Authentication.Client.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Shared\\Wasm.Authentication.Shared.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\src\\Microsoft.NET.Sdk.BlazorWebAssembly.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\test\\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
||||
"src\\JSInterop\\Microsoft.JSInterop\\src\\Microsoft.JSInterop.csproj"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\StandaloneApp\\StandaloneApp.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\src\\Microsoft.NET.Sdk.BlazorWebAssembly.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\test\\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\tools\\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
||||
"src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
|
||||
"src\\Components\\Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj",
|
||||
"src\\Components\\benchmarkapps\\Wasm.Performance\\Driver\\Wasm.Performance.Driver.csproj",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Workaround for https://github.com/dotnet/aspnetcore/issues/5486 which requires the bin and obj directory be in the project directory -->
|
||||
<BaseIntermediateOutputPath />
|
||||
<IntermediateOutputPath />
|
||||
<BaseOutputPath />
|
||||
<OutputPath />
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EnableTypeScriptNuGetTarget>true</EnableTypeScriptNuGetTarget>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<BlazorWebAssemblyJSPath>$(RepoRoot)src\Components\Web.JS\dist\$(Configuration)\blazor.webassembly.js</BlazorWebAssemblyJSPath>
|
||||
<BlazorWebAssemblyJSMapPath>$(BlazorWebAssemblyJSPath).map</BlazorWebAssemblyJSMapPath>
|
||||
|
||||
<_BlazorDevServerPath>$(RepoRoot)src/Components/WebAssembly/DevServer/src/bin/$(Configuration)/$(DefaultNetCoreTargetFramework)/blazor-devserver.dll</_BlazorDevServerPath>
|
||||
<_BlazorDevServerPath>$(ArtifactsDir)/bin/Microsoft.AspNetCore.Components.WebAssembly.DevServer/$(Configuration)/$(DefaultNetCoreTargetFramework)/blazor-devserver.dll</_BlazorDevServerPath>
|
||||
<RunCommand>dotnet</RunCommand>
|
||||
<RunArguments>exec "$(_BlazorDevServerPath)" serve --applicationpath "$(TargetPath)" $(AdditionalRunArguments)</RunArguments>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
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 netcoreapp dependencies that need to be built first.
|
||||
-->
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
|
||||
<!-- Tests do not work on Helix yet -->
|
||||
<BuildHelixPayload>false</BuildHelixPayload>
|
||||
<TestAppsRoot>$(MSBuildProjectDirectory)\..\testassets\</TestAppsRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SharedSourceRoot)MSBuild.Testing\MSBuild.Testing.targets" />
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Build.Utilities.Core" />
|
||||
<Reference Include="Microsoft.Extensions.DependencyModel" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)src\Razor\test\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj" />
|
||||
|
||||
<ProjectReference Include="..\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
||||
</ProjectReference>
|
||||
|
||||
<ProjectReference Include="$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\Microsoft.NET.Sdk.Razor.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\src\BootJsonData.cs" LinkBase="Wasm" />
|
||||
<Compile Include="..\src\AssetsManifestFile.cs" LinkBase="Wasm" />
|
||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="GenerateTestData" BeforeTargets="GetAssemblyAttributes">
|
||||
<Exec Condition="'$(OS)' == 'Windows_NT'" Command=""$(NuGetPackageRoot)vswhere\$(VSWhereVersion)\tools\vswhere.exe" -latest -prerelease -property installationPath -requires Microsoft.Component.MSBuild" ConsoleToMsBuild="true" StandardErrorImportance="high">
|
||||
<Output TaskParameter="ConsoleOutput" PropertyName="_VSInstallDir" />
|
||||
</Exec>
|
||||
<Error Condition="'$(OS)' == 'Windows_NT' and '$(_VSInstallDir)'=='' and '$(Test)' == 'true'" Text="Visual Studio not found on Windows." />
|
||||
|
||||
<PropertyGroup>
|
||||
<_DesktopMSBuildPath Condition="'$(OS)' == 'Windows_NT' and Exists('$(_VSInstallDir)\MSBuild\Current\Bin\msbuild.exe')">$(_VSInstallDir)\MSBuild\Current\Bin\msbuild.exe</_DesktopMSBuildPath>
|
||||
<_DesktopMSBuildPath Condition="'$(OS)' == 'Windows_NT' and Exists('$(_VSInstallDir)\MSBuild\15.0\Bin\msbuild.exe')">$(_VSInstallDir)\MSBuild\15.0\Bin\msbuild.exe</_DesktopMSBuildPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Error Condition="'$(OS)' == 'Windows_NT' and '$(_DesktopMSBuildPath)'=='' and '$(Test)' == 'true'" Text="MSBuild.exe not found on Windows." />
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>DesktopMSBuildPath</_Parameter1>
|
||||
<_Parameter2>$(_DesktopMSBuildPath)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="RestoreTestProjects" BeforeTargets="Restore;Build" Condition="'$(DotNetBuildFromSource)' != 'true'">
|
||||
<MSBuild Projects="..\testassets\RestoreBlazorWasmTestProjects\RestoreBlazorWasmTestProjects.csproj" Targets="Restore" Properties="MicrosoftNetCompilersToolsetPackageVersion=$(MicrosoftNetCompilersToolsetPackageVersion);RepoRoot=$(RepoRoot)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="EnsureLogFolder" AfterTargets="Build">
|
||||
<MakeDir Directories="$([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'log', '$(_BuildConfig)'))" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Razor.Tasks;
|
||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
{
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Tasks;
|
||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Tasks;
|
||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Tasks;
|
||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
|
|
@ -5,7 +5,7 @@ using System.IO;
|
|||
using System.IO.Compression;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Tasks;
|
||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
using static Microsoft.AspNetCore.Razor.Design.IntegrationTests.ServiceWorkerAssert;
|
||||
|
|
@ -608,6 +608,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
assetsManifestPath: "custom-service-worker-assets.js");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_HostedApp_WithRidSpecifiedInCLI_Works()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("blazorhosted-rid", additionalProjects: new[] { "blazorwasm", "razorclasslibrary", });
|
||||
project.RuntimeIdentifier = "linux-x64";
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:RuntimeIdentifier=linux-x64");
|
||||
|
||||
AssertRIDPublishOuput(project, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_HostedApp_WithRid_Works()
|
||||
{
|
||||
|
|
@ -616,6 +627,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
project.RuntimeIdentifier = "linux-x64";
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
|
||||
|
||||
AssertRIDPublishOuput(project, result);
|
||||
}
|
||||
|
||||
private static void AssertRIDPublishOuput(ProjectDirectory project, MSBuildResult result)
|
||||
{
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var publishDirectory = project.PublishOutputDirectory;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"methodDisplay": "method",
|
||||
"shadowCopy": false,
|
||||
"maxParallelThreads": -1
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
public class AssetsManifestFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a version string.
|
||||
/// </summary>
|
||||
public string version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the assets. Keys are URLs; values are base-64-formatted SHA256 content hashes.
|
||||
/// </summary>
|
||||
public AssetsManifestFileEntry[] assets { get; set; }
|
||||
}
|
||||
|
||||
public class AssetsManifestFileEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the asset URL. Normally this will be relative to the application's base href.
|
||||
/// </summary>
|
||||
public string url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file content hash. This should be the base-64-formatted SHA256 value.
|
||||
/// </summary>
|
||||
public string hash { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class BlazorReadSatelliteAssemblyFile : Task
|
||||
{
|
||||
[Output]
|
||||
public ITaskItem[] SatelliteAssembly { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem ReadFile { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var document = XDocument.Load(ReadFile.ItemSpec);
|
||||
SatelliteAssembly = document.Root
|
||||
.Elements()
|
||||
.Select(e =>
|
||||
{
|
||||
// <Assembly Name="..." Culture="..." DestinationSubDirectory="..." />
|
||||
|
||||
var taskItem = new TaskItem(e.Attribute("Name").Value);
|
||||
taskItem.SetMetadata("Culture", e.Attribute("Culture").Value);
|
||||
taskItem.SetMetadata("DestinationSubDirectory", e.Attribute("DestinationSubDirectory").Value);
|
||||
|
||||
return taskItem;
|
||||
}).ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// 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.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class BlazorWriteSatelliteAssemblyFile : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem[] SatelliteAssembly { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem WriteFile { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
using var fileStream = File.Create(WriteFile.ItemSpec);
|
||||
WriteSatelliteAssemblyFile(fileStream);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void WriteSatelliteAssemblyFile(Stream stream)
|
||||
{
|
||||
var root = new XElement("SatelliteAssembly");
|
||||
|
||||
foreach (var item in SatelliteAssembly)
|
||||
{
|
||||
// <Assembly Name="..." Culture="..." DestinationSubDirectory="..." />
|
||||
|
||||
root.Add(new XElement("Assembly",
|
||||
new XAttribute("Name", item.ItemSpec),
|
||||
new XAttribute("Culture", item.GetMetadata("Culture")),
|
||||
new XAttribute("DestinationSubDirectory", item.GetMetadata("DestinationSubDirectory"))));
|
||||
}
|
||||
|
||||
var xmlWriterSettings = new XmlWriterSettings
|
||||
{
|
||||
Indent = true,
|
||||
OmitXmlDeclaration = true
|
||||
};
|
||||
|
||||
using var writer = XmlWriter.Create(stream, xmlWriterSettings);
|
||||
var xDocument = new XDocument(root);
|
||||
|
||||
xDocument.Save(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
/// <summary>
|
||||
/// Defines the structure of a Blazor boot JSON file
|
||||
/// </summary>
|
||||
public class BootJsonData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the assembly with the application entry point
|
||||
/// </summary>
|
||||
public string entryAssembly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the set of resources needed to boot the application. This includes the transitive
|
||||
/// closure of .NET assemblies (including the entrypoint assembly), the dotnet.wasm file,
|
||||
/// and any PDBs to be loaded.
|
||||
///
|
||||
/// Within <see cref="ResourceHashesByNameDictionary"/>, dictionary keys are resource names,
|
||||
/// and values are SHA-256 hashes formatted in prefixed base-64 style (e.g., 'sha256-abcdefg...')
|
||||
/// as used for subresource integrity checking.
|
||||
/// </summary>
|
||||
public ResourcesData resources { get; set; } = new ResourcesData();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines whether to enable caching of the <see cref="resources"/>
|
||||
/// inside a CacheStorage instance within the browser.
|
||||
/// </summary>
|
||||
public bool cacheBootResources { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines if this is a debug build.
|
||||
/// </summary>
|
||||
public bool debugBuild { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines if the linker is enabled.
|
||||
/// </summary>
|
||||
public bool linkerEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Config files for the application
|
||||
/// </summary>
|
||||
public List<string> config { get; set; }
|
||||
}
|
||||
|
||||
public class ResourcesData
|
||||
{
|
||||
/// <summary>
|
||||
/// .NET Wasm runtime resources (dotnet.wasm, dotnet.js) etc.
|
||||
/// </summary>
|
||||
public ResourceHashesByNameDictionary runtime { get; set; } = new ResourceHashesByNameDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// "assembly" (.dll) resources
|
||||
/// </summary>
|
||||
public ResourceHashesByNameDictionary assembly { get; set; } = new ResourceHashesByNameDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// "debug" (.pdb) resources
|
||||
/// </summary>
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public ResourceHashesByNameDictionary pdb { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// localization (.satellite resx) resources
|
||||
/// </summary>
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public Dictionary<string, ResourceHashesByNameDictionary> satelliteResources { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Assembly (.dll) resources that are loaded lazily during runtime
|
||||
/// </summary>
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public ResourceHashesByNameDictionary lazyAssembly { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class BrotliCompress : ToolTask
|
||||
{
|
||||
private static readonly char[] InvalidPathChars = Path.GetInvalidFileNameChars();
|
||||
private string _dotnetPath;
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] FilesToCompress { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] CompressedFiles { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputDirectory { get; set; }
|
||||
|
||||
public string CompressionLevel { get; set; }
|
||||
|
||||
public bool SkipIfOutputIsNewer { get; set; }
|
||||
|
||||
[Required]
|
||||
public string ToolAssembly { get; set; }
|
||||
|
||||
protected override string ToolName => Path.GetDirectoryName(DotNetPath);
|
||||
|
||||
private string DotNetPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_dotnetPath))
|
||||
{
|
||||
return _dotnetPath;
|
||||
}
|
||||
|
||||
_dotnetPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH");
|
||||
if (string.IsNullOrEmpty(_dotnetPath))
|
||||
{
|
||||
throw new InvalidOperationException("DOTNET_HOST_PATH is not set");
|
||||
}
|
||||
|
||||
return _dotnetPath;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GenerateCommandLineCommands() => ToolAssembly;
|
||||
|
||||
protected override string GenerateResponseFileCommands()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
|
||||
builder.AppendLine("brotli");
|
||||
|
||||
if (!string.IsNullOrEmpty(CompressionLevel))
|
||||
{
|
||||
builder.AppendLine("-c");
|
||||
builder.AppendLine(CompressionLevel);
|
||||
}
|
||||
|
||||
CompressedFiles = new ITaskItem[FilesToCompress.Length];
|
||||
|
||||
for (var i = 0; i < FilesToCompress.Length; i++)
|
||||
{
|
||||
var input = FilesToCompress[i];
|
||||
var inputFullPath = input.GetMetadata("FullPath");
|
||||
var relativePath = input.GetMetadata("RelativePath");
|
||||
var outputRelativePath = Path.Combine(OutputDirectory, CalculateTargetPath(inputFullPath, ".br"));
|
||||
var outputFullPath = Path.GetFullPath(outputRelativePath);
|
||||
|
||||
var outputItem = new TaskItem(outputRelativePath);
|
||||
outputItem.SetMetadata("RelativePath", relativePath + ".br");
|
||||
CompressedFiles[i] = outputItem;
|
||||
|
||||
if (SkipIfOutputIsNewer && File.Exists(outputFullPath) && File.GetLastWriteTimeUtc(inputFullPath) < File.GetLastWriteTimeUtc(outputFullPath))
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, $"Skipping compression for '{input.ItemSpec}' because '{outputRelativePath}' is newer than '{input.ItemSpec}'.");
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.AppendLine("-s");
|
||||
builder.AppendLine(inputFullPath);
|
||||
|
||||
builder.AppendLine("-o");
|
||||
builder.AppendLine(outputFullPath);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
internal static string CalculateTargetPath(string relativePath, string extension)
|
||||
{
|
||||
// RelativePath can be long and if used as-is to write the output, might result in long path issues on Windows.
|
||||
// Instead we'll calculate a fixed length path by hashing the input file name. This uses SHA1 similar to the Hash task in MSBuild
|
||||
// since it has no crytographic significance.
|
||||
using var hash = SHA1.Create();
|
||||
var bytes = Encoding.UTF8.GetBytes(relativePath);
|
||||
var hashString = Convert.ToBase64String(hash.ComputeHash(bytes));
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
var c = hashString[i];
|
||||
builder.Append(InvalidPathChars.Contains(c) ? '+' : c);
|
||||
}
|
||||
|
||||
builder.Append(extension);
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
protected override string GenerateFullPathToTool() => DotNetPath;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/CreateRootDescriptorFile.cs
|
||||
public class CreateBlazorTrimmerRootDescriptorFile : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem[] Assemblies { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem TrimmerFile { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var rootDescriptor = CreateRootDescriptorContents();
|
||||
if (File.Exists(TrimmerFile.ItemSpec))
|
||||
{
|
||||
var existing = File.ReadAllText(TrimmerFile.ItemSpec);
|
||||
|
||||
if (string.Equals(rootDescriptor, existing, StringComparison.Ordinal))
|
||||
{
|
||||
Log.LogMessage(MessageImportance.Low, "Skipping write to file {0} because contents would not change.", TrimmerFile.ItemSpec);
|
||||
// Avoid writing if the file contents are identical. This is required for build incrementalism.
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(TrimmerFile.ItemSpec, rootDescriptor);
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
internal string CreateRootDescriptorContents()
|
||||
{
|
||||
var roots = new XElement("linker");
|
||||
foreach (var assembly in Assemblies.OrderBy(a => a.ItemSpec))
|
||||
{
|
||||
// NOTE: Descriptor files don't include the file extension
|
||||
// in the assemblyName.
|
||||
var assemblyName = assembly.GetMetadata("FileName");
|
||||
var typePreserved = assembly.GetMetadata("Preserve");
|
||||
var typeRequired = assembly.GetMetadata("Required");
|
||||
|
||||
var attributes = new List<XAttribute>
|
||||
{
|
||||
new XAttribute("fullname", "*"),
|
||||
new XAttribute("required", typeRequired),
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(typePreserved))
|
||||
{
|
||||
attributes.Add(new XAttribute("preserve", typePreserved));
|
||||
}
|
||||
|
||||
roots.Add(new XElement("assembly",
|
||||
new XAttribute("fullname", assemblyName),
|
||||
new XElement("type", attributes)));
|
||||
}
|
||||
|
||||
var xmlWriterSettings = new XmlWriterSettings
|
||||
{
|
||||
Indent = true,
|
||||
OmitXmlDeclaration = true
|
||||
};
|
||||
|
||||
return new XDocument(roots).Root.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// 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;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class GZipCompress : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem[] FilesToCompress { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] CompressedFiles { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputDirectory { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
CompressedFiles = new ITaskItem[FilesToCompress.Length];
|
||||
|
||||
Directory.CreateDirectory(OutputDirectory);
|
||||
|
||||
System.Threading.Tasks.Parallel.For(0, FilesToCompress.Length, i =>
|
||||
{
|
||||
var file = FilesToCompress[i];
|
||||
var inputPath = file.ItemSpec;
|
||||
var relativePath = file.GetMetadata("RelativePath");
|
||||
var outputRelativePath = Path.Combine(
|
||||
OutputDirectory,
|
||||
BrotliCompress.CalculateTargetPath(relativePath, ".gz"));
|
||||
|
||||
var outputItem = new TaskItem(outputRelativePath);
|
||||
outputItem.SetMetadata("RelativePath", relativePath + ".gz");
|
||||
CompressedFiles[i] = outputItem;
|
||||
|
||||
if (File.Exists(outputRelativePath) && File.GetLastWriteTimeUtc(inputPath) < File.GetLastWriteTimeUtc(outputRelativePath))
|
||||
{
|
||||
// Incrementalism. If input source doesn't exist or it exists and is not newer than the expected output, do nothing.
|
||||
Log.LogMessage(MessageImportance.Low, $"Skipping '{inputPath}' because '{outputRelativePath}' is newer than '{inputPath}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var sourceStream = File.OpenRead(inputPath);
|
||||
using var fileStream = File.Create(outputRelativePath);
|
||||
using var stream = new GZipStream(fileStream, CompressionLevel.Optimal);
|
||||
|
||||
sourceStream.CopyTo(stream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.LogErrorFromException(e);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class GenerateBlazorWebAssemblyBootJson : Task
|
||||
{
|
||||
[Required]
|
||||
public string AssemblyPath { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] Resources { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool DebugBuild { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool LinkerEnabled { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool CacheBootResources { get; set; }
|
||||
|
||||
public ITaskItem[] ConfigurationFiles { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
public ITaskItem[] LazyLoadedAssemblies { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
using var fileStream = File.Create(OutputPath);
|
||||
var entryAssemblyName = AssemblyName.GetAssemblyName(AssemblyPath).Name;
|
||||
|
||||
try
|
||||
{
|
||||
WriteBootJson(fileStream, entryAssemblyName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
// Internal for tests
|
||||
public void WriteBootJson(Stream output, string entryAssemblyName)
|
||||
{
|
||||
var result = new BootJsonData
|
||||
{
|
||||
entryAssembly = entryAssemblyName,
|
||||
cacheBootResources = CacheBootResources,
|
||||
debugBuild = DebugBuild,
|
||||
linkerEnabled = LinkerEnabled,
|
||||
resources = new ResourcesData(),
|
||||
config = new List<string>(),
|
||||
};
|
||||
|
||||
// Build a two-level dictionary of the form:
|
||||
// - assembly:
|
||||
// - UriPath (e.g., "System.Text.Json.dll")
|
||||
// - ContentHash (e.g., "4548fa2e9cf52986")
|
||||
// - runtime:
|
||||
// - UriPath (e.g., "dotnet.js")
|
||||
// - ContentHash (e.g., "3448f339acf512448")
|
||||
if (Resources != null)
|
||||
{
|
||||
var resourceData = result.resources;
|
||||
foreach (var resource in Resources)
|
||||
{
|
||||
ResourceHashesByNameDictionary resourceList;
|
||||
|
||||
var fileName = resource.GetMetadata("FileName");
|
||||
var extension = resource.GetMetadata("Extension");
|
||||
var resourceCulture = resource.GetMetadata("Culture");
|
||||
var assetType = resource.GetMetadata("AssetType");
|
||||
var resourceName = $"{fileName}{extension}";
|
||||
|
||||
if (IsLazyLoadedAssembly(fileName))
|
||||
{
|
||||
resourceData.lazyAssembly ??= new ResourceHashesByNameDictionary();
|
||||
resourceList = resourceData.lazyAssembly;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(resourceCulture))
|
||||
{
|
||||
resourceData.satelliteResources ??= new Dictionary<string, ResourceHashesByNameDictionary>(StringComparer.OrdinalIgnoreCase);
|
||||
resourceName = resourceCulture + "/" + resourceName;
|
||||
|
||||
if (!resourceData.satelliteResources.TryGetValue(resourceCulture, out resourceList))
|
||||
{
|
||||
resourceList = new ResourceHashesByNameDictionary();
|
||||
resourceData.satelliteResources.Add(resourceCulture, resourceList);
|
||||
}
|
||||
}
|
||||
else if (string.Equals(extension, ".pdb", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
resourceData.pdb ??= new ResourceHashesByNameDictionary();
|
||||
resourceList = resourceData.pdb;
|
||||
}
|
||||
else if (string.Equals(extension, ".dll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
resourceList = resourceData.assembly;
|
||||
}
|
||||
else if (string.Equals(assetType, "native", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
resourceList = resourceData.runtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This should include items such as XML doc files, which do not need to be recorded in the manifest.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!resourceList.ContainsKey(resourceName))
|
||||
{
|
||||
resourceList.Add(resourceName, $"sha256-{resource.GetMetadata("FileHash")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigurationFiles != null)
|
||||
{
|
||||
foreach (var configFile in ConfigurationFiles)
|
||||
{
|
||||
result.config.Add(Path.GetFileName(configFile.ItemSpec));
|
||||
}
|
||||
}
|
||||
|
||||
var serializer = new DataContractJsonSerializer(typeof(BootJsonData), new DataContractJsonSerializerSettings
|
||||
{
|
||||
UseSimpleDictionaryFormat = true
|
||||
});
|
||||
|
||||
using var writer = JsonReaderWriterFactory.CreateJsonWriter(output, Encoding.UTF8, ownsStream: false, indent: true);
|
||||
serializer.WriteObject(writer, result);
|
||||
}
|
||||
|
||||
private bool IsLazyLoadedAssembly(string fileName)
|
||||
{
|
||||
return LazyLoadedAssemblies != null && LazyLoadedAssemblies.Any(a => a.ItemSpec == fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// 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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public partial class GenerateServiceWorkerAssetsManifest : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem[] Assets { get; set; }
|
||||
|
||||
public string Version { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
[Output]
|
||||
public string CalculatedVersion { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
using var fileStream = File.Create(OutputPath);
|
||||
CalculatedVersion = GenerateAssetManifest(fileStream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal string GenerateAssetManifest(Stream stream)
|
||||
{
|
||||
var assets = new AssetsManifestFileEntry[Assets.Length];
|
||||
System.Threading.Tasks.Parallel.For(0, assets.Length, i =>
|
||||
{
|
||||
var item = Assets[i];
|
||||
var hash = item.GetMetadata("FileHash");
|
||||
var url = item.GetMetadata("AssetUrl");
|
||||
|
||||
if (string.IsNullOrEmpty(hash))
|
||||
{
|
||||
// Some files that are part of the service worker manifest may not have their hashes previously
|
||||
// calcualted. Calculate them at this time.
|
||||
using var sha = SHA256.Create();
|
||||
using var file = File.OpenRead(item.ItemSpec);
|
||||
var bytes = sha.ComputeHash(file);
|
||||
|
||||
hash = Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
assets[i] = new AssetsManifestFileEntry
|
||||
{
|
||||
hash = "sha256-" + hash,
|
||||
url = url,
|
||||
};
|
||||
});
|
||||
|
||||
var version = Version;
|
||||
if (string.IsNullOrEmpty(version))
|
||||
{
|
||||
// If a version isn't specified (which is likely the most common case), construct a Version by combining
|
||||
// the file names + hashes of all the inputs.
|
||||
|
||||
var combinedHash = string.Join(
|
||||
Environment.NewLine,
|
||||
assets.OrderBy(f => f.url, StringComparer.Ordinal).Select(f => f.hash));
|
||||
|
||||
using var sha = SHA256.Create();
|
||||
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(combinedHash));
|
||||
version = Convert.ToBase64String(bytes).Substring(0, 8);
|
||||
}
|
||||
|
||||
var data = new AssetsManifestFile
|
||||
{
|
||||
version = version,
|
||||
assets = assets,
|
||||
};
|
||||
|
||||
using var streamWriter = new StreamWriter(stream, Encoding.UTF8, bufferSize: 50, leaveOpen: true);
|
||||
streamWriter.Write("self.assetsManifest = ");
|
||||
streamWriter.Flush();
|
||||
|
||||
using var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, ownsStream: false, indent: true);
|
||||
new DataContractJsonSerializer(typeof(AssetsManifestFile)).WriteObject(jsonWriter, data);
|
||||
jsonWriter.Flush();
|
||||
|
||||
streamWriter.WriteLine(";");
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<Description>MSBuild support for building Blazor WebAssembly apps.</Description>
|
||||
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net46</TargetFrameworks>
|
||||
|
||||
<TargetName>Microsoft.NET.Sdk.BlazorWebAssembly.Tasks</TargetName>
|
||||
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
|
||||
<Serviceable>true</Serviceable>
|
||||
<SdkOutputPath>$(ArtifactsBinDir)Microsoft.NET.Sdk.BlazorWebAssembly\$(Configuration)\sdk-output\</SdkOutputPath>
|
||||
|
||||
<!-- Allow assemblies outside of lib in the package -->
|
||||
<NoWarn>$(NoWarn);NU5100</NoWarn>
|
||||
<!-- Need to build this project in source build -->
|
||||
<ExcludeFromSourceBuild>false</ExcludeFromSourceBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Build.Framework" />
|
||||
<Reference Include="Microsoft.Build.Utilities.Core" />
|
||||
|
||||
<ProjectReference
|
||||
Include="..\tools\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj"
|
||||
Targets="Publish"
|
||||
ReferenceOutputAssembly="false"
|
||||
IsImplicityDefined="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
UndefineProperties="TargetFramework;TargetFrameworks;RuntimeIdentifier;PublishDir" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="_._" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="LayoutDependencies" BeforeTargets="Build"
|
||||
Condition="'$(IsInnerBuild)' != 'true' AND '$(NoBuild)' != 'true'">
|
||||
<!-- Layout tasks, compiler, and extensions in the sdk-output folder. The entire folder structure gets packaged as-is into the SDK -->
|
||||
|
||||
<PropertyGroup Condition="'$(ContinuousIntegrationBuild)' != 'true'">
|
||||
<_ContinueOnError>true</_ContinueOnError>
|
||||
<_Retries>1</_Retries>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(ContinuousIntegrationBuild)' == 'true'">
|
||||
<_ContinueOnError>false</_ContinueOnError>
|
||||
<_Retries>10</_Retries>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_WebAssemblyToolsOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.BlazorWebAssembly.Tools\$(Configuration)\$(DefaultNetCoreTargetFramework)\publish\Microsoft.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Error
|
||||
Text="WebAssembly SDK tools outputs were not found in $(ArtifactsBinDir)Microsoft.NET.Sdk.BlazorWebAssembly.Tools\$(Configuration)\$(DefaultNetCoreTargetFramework)\publish"
|
||||
Condition="'@(_WebAssemblyToolsOutput->Count())' == '0'" />
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(_WebAssemblyToolsOutput)"
|
||||
DestinationFolder="$(SdkOutputPath)tools\$(DefaultNetCoreTargetFramework)\"
|
||||
SkipUnchangedFiles="true"
|
||||
Retries="$(_Retries)"
|
||||
ContinueOnError="$(_ContinueOnError)" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.BlazorWebAssembly\$(Configuration)\net46*\Microsoft.NET.Sdk.BlazorWebAssembly.*" />
|
||||
<ProjectOutput Include="$(ArtifactsBinDir)Microsoft.NET.Sdk.BlazorWebAssembly\$(Configuration)\$(DefaultNetCoreTargetFramework)*\Microsoft.NET.Sdk.BlazorWebAssembly.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="@(ProjectOutput)" DestinationFiles="$(SdkOutputPath)tasks\%(RecursiveDir)%(FileName)%(Extension)" SkipUnchangedFiles="true" Retries="$(_Retries)" ContinueOnError="$(_ContinueOnError)">
|
||||
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
|
||||
</Copy>
|
||||
|
||||
<Message Text="Blazor WebAssembly SDK output -> $(SdkOutputPath)" Importance="High" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PopulateNuspec" BeforeTargets="InitializeStandardNuspecProperties" DependsOnTargets="LayoutDependencies">
|
||||
<PropertyGroup>
|
||||
<PackageTags>$(PackageTags.Replace(';',' '))</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<NuspecProperty Include="outputPath=$(OutputPath)\sdk-output" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!-- Workarounds to allow publishing to work when the SDK is referenced as a project. -->
|
||||
<Target Name="GetTargetPath" />
|
||||
<Target Name="GetCopyToPublishDirectoryItems" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
$CommonMetadataElements$
|
||||
<dependencies>
|
||||
<group targetFramework=".NET5.0" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
||||
<files>
|
||||
$CommonFileElements$
|
||||
<file src="Sdk\*" target="Sdk" />
|
||||
<file src="build\**" target="build" />
|
||||
<file src="targets\**" target="targets" />
|
||||
<file src="_._" target="lib\net5.0\_._" />
|
||||
|
||||
<file src="$outputPath$\**" target="\" />
|
||||
</files>
|
||||
</package>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Sdk.props
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
<Project ToolsVersion="14.0" TreatAsLocalProperty="RuntimeIdentifier">
|
||||
<PropertyGroup>
|
||||
<UsingMicrosoftNETSdkBlazorWebAssembly>true</UsingMicrosoftNETSdkBlazorWebAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorWebAssemblyPropsFile Condition="'$(_BlazorWebAssemblyPropsFile)' == ''">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.props</_BlazorWebAssemblyPropsFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(_BlazorWebAssemblyPropsFile)" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Sdk.targets
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
<Project ToolsVersion="14.0">
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorWebAssemblyTargetsFile Condition="'$(_BlazorWebAssemblyTargetsFile)' == ''">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets</_BlazorWebAssemblyTargetsFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(_BlazorWebAssemblyTargetsFile)" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Microsoft.NET.Sdk.BlazorWebAssembly.props
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
<Project ToolsVersion="14.0">
|
||||
<PropertyGroup>
|
||||
<_BlazorWebAssemblyPropsFile>$(MSBuildThisFileDirectory)..\..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.props</_BlazorWebAssemblyPropsFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Microsoft.NET.Sdk.BlazorWebAssembly.props
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
<Project ToolsVersion="14.0">
|
||||
<PropertyGroup>
|
||||
<_BlazorWebAssemblyTargetsFile>$(MSBuildThisFileDirectory)..\..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets</_BlazorWebAssemblyTargetsFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<staticContent>
|
||||
<remove fileExtension=".dat" />
|
||||
<remove fileExtension=".dll" />
|
||||
<remove fileExtension=".json" />
|
||||
<remove fileExtension=".wasm" />
|
||||
<remove fileExtension=".woff" />
|
||||
<remove fileExtension=".woff2" />
|
||||
<mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
|
||||
<mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
|
||||
<mimeMap fileExtension=".json" mimeType="application/json" />
|
||||
<mimeMap fileExtension=".wasm" mimeType="application/wasm" />
|
||||
<mimeMap fileExtension=".woff" mimeType="application/font-woff" />
|
||||
<mimeMap fileExtension=".woff2" mimeType="application/font-woff" />
|
||||
</staticContent>
|
||||
<httpCompression>
|
||||
<dynamicTypes>
|
||||
<add mimeType="application/octet-stream" enabled="true" />
|
||||
<add mimeType="application/wasm" enabled="true" />
|
||||
</dynamicTypes>
|
||||
</httpCompression>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Serve subdir">
|
||||
<match url=".*" />
|
||||
<action type="Rewrite" url="wwwroot\{R:0}" />
|
||||
</rule>
|
||||
<rule name="SPA fallback routing" stopProcessing="true">
|
||||
<match url=".*" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="wwwroot\" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<linker>
|
||||
|
||||
<!-- This file specifies which parts of the BCL or Blazor packages must not be stripped
|
||||
by the IL linker even if they are not referenced by user code. The file format is
|
||||
described at https://github.com/mono/linker/blob/master/src/linker/README.md#syntax-of-xml-descriptor -->
|
||||
|
||||
<assembly fullname="System">
|
||||
<!-- Without this, [Required(typeof(bool), "true", "true", ErrorMessage = "...")] fails -->
|
||||
<type fullname="System.ComponentModel.BooleanConverter" />
|
||||
|
||||
<!-- TypeConverters are only used through reflection. These are two built-in TypeConverters that are useful. -->
|
||||
<type fullname="System.ComponentModel.GuidConverter" />
|
||||
<type fullname="System.ComponentModel.TimeSpanConverter" />
|
||||
</assembly>
|
||||
</linker>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Microsoft.NET.Sdk.BlazorWebAssembly.props
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
<Project ToolsVersion="14.0" TreatAsLocalProperty="RuntimeIdentifier">
|
||||
<PropertyGroup>
|
||||
<!-- Blazor WASM projects are always browser-wasm -->
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
|
||||
<!-- Avoid having the rid show up in output paths -->
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
|
||||
<OutputType>exe</OutputType>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Determines if this Sdk is responsible for importing Microsoft.NET.Sdk.Razor. Temporary workaround until we can create a SDK. -->
|
||||
<_RazorSdkImportsMicrosoftNetSdkRazor Condition="'$(UsingMicrosoftNETSdkRazor)' != 'true'">true</_RazorSdkImportsMicrosoftNetSdkRazor>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Sdk="Microsoft.NET.Sdk.Razor" Project="Sdk.props" Condition="'$(_RazorSdkImportsMicrosoftNetSdkRazor)' == 'true'" />
|
||||
<Import Sdk="Microsoft.NET.Sdk.Web.ProjectSystem" Project="Sdk.props" />
|
||||
<Import Sdk="Microsoft.NET.Sdk.Publish" Project="Sdk.props" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,582 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Microsoft.NET.Sdk.BlazorWebAssembly.targets
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
<Project ToolsVersion="14.0">
|
||||
|
||||
<PropertyGroup>
|
||||
<EnableDefaultContentItems Condition=" '$(EnableDefaultContentItems)' == '' ">true</EnableDefaultContentItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Sdk="Microsoft.NET.Sdk.Razor" Project="Sdk.targets" Condition="'$(_RazorSdkImportsMicrosoftNetSdkRazor)' == 'true'" />
|
||||
<Import Sdk="Microsoft.NET.Sdk.Web.ProjectSystem" Project="Sdk.targets" />
|
||||
<Import Sdk="Microsoft.NET.Sdk.Publish" Project="Sdk.targets" />
|
||||
|
||||
<!--
|
||||
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 Blazor targets. By default this is unused.
|
||||
-->
|
||||
<Import Project="$(CustomBeforeBlazorWebAssemblySdkTargets)" Condition="'$(CustomBeforeBlazorWebAssemblySdkTargets)' != '' and Exists('$(CustomBeforeBlazorWebAssemblySdkTargets)')"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Paths to tools, tasks, and extensions are calculated relative to the BlazorWebAssemblySdkDirectoryRoot. This can be modified to test a local build. -->
|
||||
<BlazorWebAssemblySdkDirectoryRoot Condition="'$(BlazorWebAssemblySdkDirectoryRoot)'==''">$(MSBuildThisFileDirectory)..\..\</BlazorWebAssemblySdkDirectoryRoot>
|
||||
<_BlazorWebAssemblySdkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">net5.0</_BlazorWebAssemblySdkTasksTFM>
|
||||
<_BlazorWebAssemblySdkTasksTFM Condition=" '$(MSBuildRuntimeType)' != 'Core'">net46</_BlazorWebAssemblySdkTasksTFM>
|
||||
<_BlazorWebAssemblySdkTasksAssembly>$(BlazorWebAssemblySdkDirectoryRoot)tasks\$(_BlazorWebAssemblySdkTasksTFM)\Microsoft.NET.Sdk.BlazorWebAssembly.Tasks.dll</_BlazorWebAssemblySdkTasksAssembly>
|
||||
<_BlazorWebAssemblySdkToolAssembly>$(BlazorWebAssemblySdkDirectoryRoot)tools\net5.0\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.dll</_BlazorWebAssemblySdkToolAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.GenerateBlazorWebAssemblyBootJson" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.BlazorWriteSatelliteAssemblyFile" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.BlazorReadSatelliteAssemblyFile" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.BrotliCompress" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.GzipCompress" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.CreateBlazorTrimmerRootDescriptorFile" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
|
||||
<PropertyGroup>
|
||||
<SelfContained>true</SelfContained>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
||||
<!-- Trimmer defaults -->
|
||||
<PublishTrimmed Condition="'$(PublishTrimmed)' == ''">true</PublishTrimmed>
|
||||
<TrimMode Condition="'$(TrimMode)' == ''">link</TrimMode>
|
||||
|
||||
<StaticWebAssetBasePath Condition="'$(StaticWebAssetBasePath)' == ''">/</StaticWebAssetBasePath>
|
||||
<BlazorCacheBootResources Condition="'$(BlazorCacheBootResources)' == ''">true</BlazorCacheBootResources>
|
||||
|
||||
<!-- Turn off parts of the build that do not apply to WASM projects -->
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
<GenerateRuntimeConfigurationFiles>false</GenerateRuntimeConfigurationFiles>
|
||||
<PreserveCompilationContext>false</PreserveCompilationContext>
|
||||
<PreserveCompilationReferences>false</PreserveCompilationReferences>
|
||||
<IsWebConfigTransformDisabled>true</IsWebConfigTransformDisabled>
|
||||
|
||||
<!-- Internal properties -->
|
||||
<_BlazorOutputPath>wwwroot\_framework\</_BlazorOutputPath>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Microsoft.NET.Sdk.BlazorWebAssembly.ServiceWorkerAssetsManifest.targets" />
|
||||
|
||||
<Target Name="_ScrambleDotnetJsFileName" AfterTargets="ResolveRuntimePackAssets">
|
||||
<!--
|
||||
We want the dotnet.js file output to have a version to better work with caching. We'll append the runtime version to the file name as soon as file has been discovered.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<_DotNetJsVersion>$(BundledNETCoreAppPackageVersion)</_DotNetJsVersion>
|
||||
<_DotNetJsVersion Condition="'$(RuntimeFrameworkVersion)' != ''">$(RuntimeFrameworkVersion)</_DotNetJsVersion>
|
||||
<_BlazorDotnetJsFileName>dotnet.$(_DotNetJsVersion).js</_BlazorDotnetJsFileName>
|
||||
<_BlazorDotNetJsFilePath>$(IntermediateOutputPath)$(_BlazorDotnetJsFileName)</_BlazorDotNetJsFilePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_DotNetJsItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.DestinationSubPath)' == 'dotnet.js' AND '%(ReferenceCopyLocalPaths.AssetType)' == 'native'" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(_DotNetJsItem)"
|
||||
DestinationFiles="$(_BlazorDotNetJsFilePath)"
|
||||
SkipUnchangedFiles="true"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)" />
|
||||
|
||||
<ItemGroup Condition="'@(_DotNetJsItem->Count())' != '0'">
|
||||
<ReferenceCopyLocalPaths
|
||||
Include="$(_BlazorDotNetJsFilePath)"
|
||||
AssetType="native"
|
||||
CopyLocal="true"
|
||||
DestinationSubPath="$(_BlazorDotnetJsFileName)" />
|
||||
|
||||
<ReferenceCopyLocalPaths Remove="@(_DotNetJsItem)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_ResolveBlazorWasmOutputs" DependsOnTargets="ResolveReferences;PrepareResourceNames;ComputeIntermediateSatelliteAssemblies">
|
||||
<!--
|
||||
Calculates the outputs and the paths for Blazor WASM. This target is invoked frequently and should perform minimal work.
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorSatelliteAssemblyCacheFile>$(IntermediateOutputPath)blazor.satelliteasm.props</_BlazorSatelliteAssemblyCacheFile>
|
||||
<!-- Workaround for https://github.com/dotnet/sdk/issues/12114-->
|
||||
<PublishDir Condition="'$(AppendRuntimeIdentifierToOutputPath)' != 'true' AND '$(PublishDir)' == '$(OutputPath)$(RuntimeIdentifier)\$(PublishDirName)\'">$(OutputPath)$(PublishDirName)\</PublishDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorJSFile Include="$(BlazorWebAssemblyJSPath)" />
|
||||
<_BlazorJSFile Include="$(BlazorWebAssemblyJSMapPath)" Condition="Exists('$(BlazorWebAssemblyJSMapPath)')" />
|
||||
|
||||
<_BlazorConfigFile Include="wwwroot\appsettings*.json" />
|
||||
|
||||
<!-- Clear out temporary build artifacts that the runtime packages -->
|
||||
<ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.a'" />
|
||||
|
||||
<!--
|
||||
ReferenceCopyLocalPaths includes satellite assemblies from referenced projects but are inexpicably missing
|
||||
any metadata that might allow them to be differentiated. We'll explicitly add those
|
||||
to _BlazorOutputWithTargetPath so that satellite assemblies from packages, the current project and referenced project
|
||||
are all treated the same.
|
||||
-->
|
||||
|
||||
<_BlazorCopyLocalPath
|
||||
Include="@(ReferenceCopyLocalPaths)"
|
||||
Exclude="@(ReferenceSatellitePaths)"/>
|
||||
|
||||
<_BlazorCopyLocalPath Include="@(IntermediateSatelliteAssembliesWithTargetPath)">
|
||||
<DestinationSubDirectory>%(IntermediateSatelliteAssembliesWithTargetPath.Culture)\</DestinationSubDirectory>
|
||||
</_BlazorCopyLocalPath>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="
|
||||
@(_BlazorCopyLocalPath);
|
||||
@(IntermediateAssembly);
|
||||
@(_DebugSymbolsIntermediatePath);
|
||||
@(_BlazorJSFile)" />
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(ReferenceSatellitePaths)">
|
||||
<Culture>$([System.String]::Copy('%(ReferenceSatellitePaths.DestinationSubDirectory)').Trim('\').Trim('/'))</Culture>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
BuildingProject=false is typically set for referenced projects when building inside VisualStudio.
|
||||
|
||||
When building with BuildingProject=false, satellite assemblies do not get resolved (the ones for the current project and the one for
|
||||
referenced project). Satellite assemblies from packages get resolved.
|
||||
To workaround this, we'll cache metadata during a regular build, and rehydrate from it when BuildingProject=false.
|
||||
-->
|
||||
<BlazorReadSatelliteAssemblyFile
|
||||
ReadFile="$(_BlazorSatelliteAssemblyCacheFile)"
|
||||
Condition="'$(BuildingProject)' != 'true' AND EXISTS('$(_BlazorSatelliteAssemblyCacheFile)')">
|
||||
<Output TaskParameter="SatelliteAssembly" ItemName="_BlazorReadSatelliteAssembly" />
|
||||
</BlazorReadSatelliteAssemblyFile>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- We've imported a previously Cacheed file. Let's turn in to a _BlazorOutputWithTargetPath -->
|
||||
<_BlazorOutputWithTargetPath
|
||||
Include="@(_BlazorReadSatelliteAssembly)"
|
||||
Exclude="@(_BlazorOutputWithTargetPath)"
|
||||
Condition="'@(_BlazorReadSatelliteAssembly->Count())' != '0'" />
|
||||
|
||||
<!-- Calculate the target path -->
|
||||
<_BlazorOutputWithTargetPath
|
||||
TargetPath="$(_BlazorOutputPath)%(_BlazorOutputWithTargetPath.DestinationSubDirectory)%(FileName)%(Extension)"
|
||||
Condition="'%(__BlazorOutputWithTargetPath.TargetPath)' == ''" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_ProcessBlazorWasmOutputs" DependsOnTargets="_ResolveBlazorWasmOutputs">
|
||||
<PropertyGroup>
|
||||
<_BlazorBuildGZipCompressDirectory>$(IntermediateOutputPath)build-gz\</_BlazorBuildGZipCompressDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Compress referenced binaries using GZip during build. This skips files such as the project's assemblies
|
||||
that change from build to build. Runtime assets contribute to the bulk of the download size. Compressing it
|
||||
has the most benefit while avoiding any ongoing costs to the dev inner loop.
|
||||
-->
|
||||
<ItemGroup>
|
||||
<_GzipFileToCompressForBuild
|
||||
Include="@(ReferenceCopyLocalPaths)"
|
||||
RelativePath="$(_BlazorOutputPath)%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(FileName)%(Extension)"
|
||||
Condition="'%(Extension)' == '.dll' or '%(ReferenceCopyLocalPaths.AssetType)' == 'native'" />
|
||||
</ItemGroup>
|
||||
|
||||
<GZipCompress
|
||||
FilesToCompress="@(_GzipFileToCompressForBuild)"
|
||||
OutputDirectory="$(_BlazorBuildGZipCompressDirectory)">
|
||||
|
||||
<Output TaskParameter="CompressedFiles" ItemName="_BlazorBuildGZipCompressedFile" />
|
||||
<Output TaskParameter="CompressedFiles" ItemName="FileWrites" />
|
||||
</GZipCompress>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorWriteSatelliteAssembly Include="@(_BlazorOutputWithTargetPath->HasMetadata('Culture'))" />
|
||||
|
||||
<!-- Retarget ReferenceCopyLocalPaths to copy to the wwwroot directory -->
|
||||
<ReferenceCopyLocalPaths DestinationSubDirectory="$(_BlazorOutputPath)%(ReferenceCopyLocalPaths.DestinationSubDirectory)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- A missing blazor.webassembly.js is our packaging error. Produce an error so it's discovered early. -->
|
||||
<Error
|
||||
Text="Unable to find BlazorWebAssembly JS files. This usually indicates a packaging error."
|
||||
Code="RAZORSDK1007"
|
||||
Condition="'@(_BlazorJSFile->Count())' == '0'" />
|
||||
|
||||
<!--
|
||||
When building with BuildingProject=false, satellite assemblies do not get resolved (the ones for the current project and the one for
|
||||
referenced project). BuildingProject=false is typically set for referenced projects when building inside VisualStudio.
|
||||
To workaround this, we'll cache metadata during a regular build, and rehydrate from it when BuildingProject=false.
|
||||
-->
|
||||
|
||||
<BlazorWriteSatelliteAssemblyFile
|
||||
SatelliteAssembly="@(_BlazorWriteSatelliteAssembly)"
|
||||
WriteFile="$(_BlazorSatelliteAssemblyCacheFile)"
|
||||
Condition="'$(BuildingProject)' == 'true' AND '@(_BlazorWriteSatelliteAssembly->Count())' != '0'" />
|
||||
|
||||
<Delete
|
||||
Files="$(_BlazorSatelliteAssemblyCacheFile)"
|
||||
Condition="'$(BuildingProject)' == 'true' AND '@(_BlazorWriteSatelliteAssembly->Count())' == '0' and EXISTS('$(_BlazorSatelliteAssemblyCacheFile)')" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(_BlazorSatelliteAssemblyCacheFile)" Condition="Exists('$(_BlazorSatelliteAssemblyCacheFile)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<GetFileHash Files="@(_BlazorOutputWithTargetPath)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_BlazorOutputWithHash" />
|
||||
</GetFileHash>
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<PrepareForRunDependsOn>
|
||||
_BlazorWasmPrepareForRun;
|
||||
$(PrepareForRunDependsOn)
|
||||
</PrepareForRunDependsOn>
|
||||
|
||||
<GetCurrentProjectStaticWebAssetsDependsOn>
|
||||
$(GetCurrentProjectStaticWebAssetsDependsOn);
|
||||
_BlazorWasmPrepareForRun;
|
||||
</GetCurrentProjectStaticWebAssetsDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_BlazorWasmPrepareForRun" DependsOnTargets="_ProcessBlazorWasmOutputs" BeforeTargets="_RazorPrepareForRun" AfterTargets="GetCurrentProjectStaticWebAssets">
|
||||
<PropertyGroup>
|
||||
<_BlazorBuildBootJsonPath>$(IntermediateOutputPath)blazor.boot.json</_BlazorBuildBootJsonPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<GenerateBlazorWebAssemblyBootJson
|
||||
AssemblyPath="@(IntermediateAssembly)"
|
||||
Resources="@(_BlazorOutputWithHash)"
|
||||
DebugBuild="true"
|
||||
LinkerEnabled="false"
|
||||
CacheBootResources="$(BlazorCacheBootResources)"
|
||||
OutputPath="$(_BlazorBuildBootJsonPath)"
|
||||
ConfigurationFiles="@(_BlazorConfigFile)"
|
||||
LazyLoadedAssemblies="@(BlazorWebAssemblyLazyLoad)" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(OutDir)$(_BlazorOutputPath)blazor.boot.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorWebAssemblyStaticWebAsset Include="$(_BlazorBuildBootJsonPath)">
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<SourceType></SourceType>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>_framework/blazor.boot.json</RelativePath>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</_BlazorWebAssemblyStaticWebAsset>
|
||||
|
||||
<_BlazorWebAssemblyStaticWebAsset Include="@(_BlazorOutputWithHash)">
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<SourceType></SourceType>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>$([System.String]::Copy('%(_BlazorOutputWithHash.TargetPath)').Replace('\','/').Substring(8))</RelativePath>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</_BlazorWebAssemblyStaticWebAsset>
|
||||
|
||||
<_BlazorWebAssemblyStaticWebAsset Include="@(_BlazorBuildGZipCompressedFile)">
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<SourceType></SourceType>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>$([System.String]::Copy('%(_BlazorBuildGZipCompressedFile.RelativePath)').Replace('\','/').Substring(8))</RelativePath>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</_BlazorWebAssemblyStaticWebAsset>
|
||||
|
||||
<StaticWebAsset Include="@(_BlazorWebAssemblyStaticWebAsset)" />
|
||||
<_ExternalStaticWebAsset Include="@(_BlazorWebAssemblyStaticWebAsset)" SourceType="Generated" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!-- Mimics the behavior of CopyFilesToOutputDirectory. We simply copy relevant build outputs to the wwwroot directory -->
|
||||
<Target Name="_BlazorCopyFilesToOutputDirectory" AfterTargets="CopyFilesToOutputDirectory">
|
||||
<Copy
|
||||
SourceFiles="@(IntermediateAssembly)"
|
||||
DestinationFolder="$(OutDir)$(_BlazorOutputPath)"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)"
|
||||
Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<Message Importance="High" Text="$(MSBuildProjectName) (Blazor output) -> $(TargetDir)wwwroot" Condition="'$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)'!='true'" />
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(_DebugSymbolsIntermediatePath)"
|
||||
DestinationFolder="$(OutDir)$(_BlazorOutputPath)"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)"
|
||||
Condition="'$(_DebugSymbolsProduced)'=='true' and '$(SkipCopyingSymbolsToOutputDirectory)' != 'true' and '$(CopyOutputSymbolsToOutputDirectory)'=='true'">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(IntermediateSatelliteAssembliesWithTargetPath)"
|
||||
DestinationFiles="@(IntermediateSatelliteAssembliesWithTargetPath->'$(OutDir)$(_BlazorOutputPath)%(Culture)\$(TargetName).resources.dll')"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)"
|
||||
Condition="'@(IntermediateSatelliteAssembliesWithTargetPath)' != ''" >
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(_BlazorJSFile);$(_BlazorBuildBootJsonPath)"
|
||||
DestinationFolder="$(OutDir)$(_BlazorOutputPath)"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(_BlazorBuildGZipCompressedFile)"
|
||||
DestinationFiles="@(_BlazorBuildGZipCompressedFile->'$(OutDir)%(RelativePath)')"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorWasmPrepareForLink" BeforeTargets="PrepareForILLink">
|
||||
<PropertyGroup>
|
||||
<_BlazorTypeGranularTrimmerDescriptorFile>$(IntermediateOutputPath)typegranularity.trimmerdescriptor.xml</_BlazorTypeGranularTrimmerDescriptorFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorTypeGranularAssembly
|
||||
Include="@(ManagedAssemblyToLink)"
|
||||
Condition="'%(Extension)' == '.dll' AND ($([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.')) or $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.')))">
|
||||
<Required>false</Required>
|
||||
<Preserve>all</Preserve>
|
||||
</_BlazorTypeGranularAssembly>
|
||||
|
||||
<ManagedAssemblyToLink
|
||||
IsTrimmable="true"
|
||||
Condition="'%(Extension)' == '.dll' AND ($([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.')) or $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.')))" />
|
||||
</ItemGroup>
|
||||
|
||||
<CreateBlazorTrimmerRootDescriptorFile
|
||||
Assemblies="@(_BlazorTypeGranularAssembly)"
|
||||
TrimmerFile="$(_BlazorTypeGranularTrimmerDescriptorFile)" />
|
||||
|
||||
<ItemGroup>
|
||||
<TrimmerRootDescriptor Include="$(_BlazorTypeGranularTrimmerDescriptorFile)" />
|
||||
<TrimmerRootDescriptor Include="$(MSBuildThisFileDirectory)LinkerWorkaround.xml" />
|
||||
|
||||
<FileWrites Include="$(_BlazorTypeGranularTrimmerDescriptorFile)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_ProcessPublishFilesForBlazor" DependsOnTargets="_ResolveBlazorWasmOutputs" AfterTargets="ILLink">
|
||||
|
||||
<!--
|
||||
ResolvedFileToPublish.Culture is missing for satellite assemblies from project references.
|
||||
Since we need the culture to correctly generate blazor.boot.json, we cross-reference the culture we calculate as part of _ResolveBlazorWasmOutputs
|
||||
-->
|
||||
<JoinItems Left="@(ResolvedFileToPublish)"
|
||||
Right="@(_BlazorOutputWithTargetPath->HasMetadata('Culture'))"
|
||||
LeftMetadata="*"
|
||||
RightMetadata="Culture"
|
||||
ItemSpecToUse="Left">
|
||||
<Output TaskParameter="JoinResult" ItemName="_ResolvedSatelliteToPublish" />
|
||||
</JoinItems>
|
||||
|
||||
<ItemGroup>
|
||||
<ResolvedFileToPublish Remove="@(_ResolvedSatelliteToPublish)" />
|
||||
<ResolvedFileToPublish Include="@(_ResolvedSatelliteToPublish)" />
|
||||
|
||||
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'%(Extension)' == '.a'" />
|
||||
|
||||
<!-- Remove dotnet.js from publish output -->
|
||||
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.RelativePath)' == 'dotnet.js'" />
|
||||
|
||||
<!-- Retarget so that items are published to the wwwroot directory -->
|
||||
<ResolvedFileToPublish
|
||||
RelativePath="$(_BlazorOutputPath)%(ResolvedFileToPublish.RelativePath)"
|
||||
Condition="'%(ResolvedFileToPublish.RelativePath)' != 'web.config' AND !$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||
|
||||
<!-- Remove pdbs from the publish output -->
|
||||
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'$(BlazorWebAssemblyEnableDebugging)' != 'true' AND '%(Extension)' == '.pdb'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'@(ResolvedFileToPublish->AnyHaveMetadataValue('RelativePath', 'web.config'))' != 'true'">
|
||||
<ResolvedFileToPublish
|
||||
Include="$(MSBuildThisFileDirectory)BlazorWasm.web.config"
|
||||
ExcludeFromSingleFile="true"
|
||||
CopyToPublishDirectory="PreserveNewest"
|
||||
RelativePath="web.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Generate the publish boot json -->
|
||||
<ItemGroup>
|
||||
<_BlazorPublishBootResource
|
||||
Include="@(ResolvedFileToPublish)"
|
||||
Condition="$([System.String]::Copy('%(RelativePath)').Replace('\','/').StartsWith('wwwroot/_framework')) AND '%(Extension)' != '.a'" />
|
||||
</ItemGroup>
|
||||
|
||||
<GetFileHash Files="@(_BlazorPublishBootResource)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_BlazorPublishBootResourceWithHash" />
|
||||
</GetFileHash>
|
||||
|
||||
<GenerateBlazorWebAssemblyBootJson
|
||||
AssemblyPath="@(IntermediateAssembly)"
|
||||
Resources="@(_BlazorPublishBootResourceWithHash)"
|
||||
DebugBuild="false"
|
||||
LinkerEnabled="$(PublishTrimmed)"
|
||||
CacheBootResources="$(BlazorCacheBootResources)"
|
||||
OutputPath="$(IntermediateOutputPath)blazor.publish.boot.json"
|
||||
ConfigurationFiles="@(_BlazorConfigFile)"
|
||||
LazyLoadedAssemblies="@(BlazorWebAssemblyLazyLoad)" />
|
||||
|
||||
<ItemGroup>
|
||||
<ResolvedFileToPublish
|
||||
Include="$(IntermediateOutputPath)blazor.publish.boot.json"
|
||||
RelativePath="$(_BlazorOutputPath)blazor.boot.json" />
|
||||
|
||||
<ResolvedFileToPublish
|
||||
Include="@(_BlazorJSFile)"
|
||||
RelativePath="$(_BlazorOutputPath)%(FileName)%(Extension)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorCompressPublishFiles" AfterTargets="_ProcessPublishFilesForBlazor" Condition="'$(BlazorEnableCompression)' != 'false'">
|
||||
<PropertyGroup>
|
||||
<_CompressedFileOutputPath>$(IntermediateOutputPath)compress\</_CompressedFileOutputPath>
|
||||
<_BlazorWebAssemblyBrotliIncremental>true</_BlazorWebAssemblyBrotliIncremental>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_FileToCompress
|
||||
Include="@(ResolvedFileToPublish)"
|
||||
Condition="$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||
</ItemGroup>
|
||||
|
||||
<Message Text="Compressing Blazor WebAssembly publish artifacts. This may take a while..." Importance="High" />
|
||||
|
||||
<MakeDir Directories="$(_CompressedFileOutputPath)" Condition="!Exists('$(_CompressedFileOutputPath)')" />
|
||||
|
||||
<PropertyGroup Condition="'$(DOTNET_HOST_PATH)' == ''">
|
||||
<_DotNetHostDirectory>$(NetCoreRoot)</_DotNetHostDirectory>
|
||||
<_DotNetHostFileName>dotnet</_DotNetHostFileName>
|
||||
<_DotNetHostFileName Condition="'$(OS)' == 'Windows_NT'">dotnet.exe</_DotNetHostFileName>
|
||||
</PropertyGroup>
|
||||
|
||||
<BrotliCompress
|
||||
OutputDirectory="$(_CompressedFileOutputPath)"
|
||||
FilesToCompress="@(_FileToCompress)"
|
||||
CompressionLevel="$(_BlazorBrotliCompressionLevel)"
|
||||
SkipIfOutputIsNewer="$(_BlazorWebAssemblyBrotliIncremental)"
|
||||
ToolAssembly="$(_BlazorWebAssemblySdkToolAssembly)"
|
||||
ToolExe="$(_DotNetHostFileName)"
|
||||
ToolPath="$(_DotNetHostDirectory)">
|
||||
|
||||
<Output TaskParameter="CompressedFiles" ItemName="_BrotliCompressedFile" />
|
||||
<Output TaskParameter="CompressedFiles" ItemName="FileWrites" />
|
||||
</BrotliCompress>
|
||||
|
||||
<GZipCompress
|
||||
OutputDirectory="$(_CompressedFileOutputPath)"
|
||||
FilesToCompress="@(_FileToCompress)">
|
||||
|
||||
<Output TaskParameter="CompressedFiles" ItemName="_BlazorPublishGZipCompressedFile" />
|
||||
<Output TaskParameter="CompressedFiles" ItemName="FileWrites" />
|
||||
</GZipCompress>
|
||||
|
||||
<ItemGroup>
|
||||
<ResolvedFileToPublish Include="@(_BrotliCompressedFile)" />
|
||||
<ResolvedFileToPublish Include="@(_BlazorPublishGZipCompressedFile)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_SetupPublishSemaphore" BeforeTargets="PrepareForPublish">
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
Add marker that indicates Blazor WASM is doing a publish. This is used to identify when GetCopyToPublishDirectoryItems
|
||||
is invoked as a result of a P2P reference.
|
||||
-->
|
||||
<_PublishingBlazorWasmProject>true</_PublishingBlazorWasmProject>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_GetBlazorWasmFilesForPublishInner"
|
||||
DependsOnTargets="_ResolveBlazorWasmOutputs;ComputeFilesToPublish"
|
||||
Returns="@(ResolvedFileToPublish)" />
|
||||
|
||||
<Target Name="_GetBlazorWasmFilesForPublish" BeforeTargets="GetCopyToPublishDirectoryItems">
|
||||
<MSBuild
|
||||
Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="_GetBlazorWasmFilesForPublishInner"
|
||||
Properties="BuildProjectReferences=false;ResolveAssemblyReferencesFindRelatedSatellites=true;_PublishingBlazorWasmProject=true"
|
||||
RemoveProperties="NoBuild;RuntimeIdentifier"
|
||||
BuildInParallel="$(BuildInParallel)"
|
||||
Condition="'$(_PublishingBlazorWasmProject)' != 'true'">
|
||||
|
||||
<Output TaskParameter="TargetOutputs" ItemName="_ResolvedFileToPublish" />
|
||||
</MSBuild>
|
||||
|
||||
<ItemGroup>
|
||||
<AllPublishItemsFullPathWithTargetPath Include="@(_ResolvedFileToPublish->'%(FullPath)')">
|
||||
<TargetPath>%(RelativePath)</TargetPath>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</AllPublishItemsFullPathWithTargetPath>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorApplyLinkPreferencesToContent" BeforeTargets="AssignTargetPaths;ResolveCurrentProjectStaticWebAssetsInputs;ResolveStaticWebAssetsInputs" Returns="@(Content)">
|
||||
<ItemGroup>
|
||||
<Content
|
||||
Condition="'%(Content.Link)' != '' AND '%(Content.CopyToPublishDirectory)' == '' AND $([System.String]::Copy('%(Content.Link)').Replace('\','/').StartsWith('wwwroot/'))"
|
||||
CopyToPublishDirectory="PreserveNewest" />
|
||||
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
This is a hook to import a set of targets after the Blazor WebAssembly targets. By default this is unused.
|
||||
-->
|
||||
<Import Project="$(CustomAfterBlazorWebAssemblySdkTargets)" Condition="'$(CustomAfterBlazorWebAssemblySdkTargets)' != '' and Exists('$(CustomAfterBlazorWebAssemblySdkTargets)')"/>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
<!--
|
||||
***********************************************************************************************
|
||||
Microsoft.NET.Sdk.BlazorWebAssembly.ServiceWorkerAssetsManifest.targets
|
||||
|
||||
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
|
||||
created a backup copy. Incorrect changes to this file will make it
|
||||
impossible to load or build your projects from the command-line or the IDE.
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
***********************************************************************************************
|
||||
-->
|
||||
|
||||
<Project>
|
||||
<UsingTask TaskName="Microsoft.NET.Sdk.BlazorWebAssembly.GenerateServiceWorkerAssetsManifest" AssemblyFile="$(_BlazorWebAssemblySdkTasksAssembly)" />
|
||||
|
||||
<Target Name="_ComputeServiceWorkerAssets" BeforeTargets="ResolveStaticWebAssetsInputs">
|
||||
|
||||
<PropertyGroup>
|
||||
<_ServiceWorkerAssetsManifestIntermediateOutputPath Condition="'$([System.IO.Path]::IsPathRooted($(BaseIntermediateOutputPath)))' == 'true'">obj\$(Configuration)\$(TargetFramework)\$(ServiceWorkerAssetsManifest)</_ServiceWorkerAssetsManifestIntermediateOutputPath>
|
||||
<_ServiceWorkerAssetsManifestIntermediateOutputPath Condition="'$([System.IO.Path]::IsPathRooted($(BaseIntermediateOutputPath)))' != 'true'">$(IntermediateOutputPath)$(ServiceWorkerAssetsManifest)</_ServiceWorkerAssetsManifestIntermediateOutputPath>
|
||||
<_ServiceWorkerAssetsManifestFullPath>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/$(_ServiceWorkerAssetsManifestIntermediateOutputPath)'))</_ServiceWorkerAssetsManifestFullPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ManifestStaticWebAsset Include="$(_ServiceWorkerAssetsManifestFullPath)">
|
||||
<SourceType></SourceType>
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>$(ServiceWorkerAssetsManifest)</RelativePath>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</_ManifestStaticWebAsset>
|
||||
|
||||
<!-- Figure out where we're getting the content for each @(ServiceWorker) entry, depending on whether there's a PublishedContent value -->
|
||||
<_ServiceWorkerIntermediateFile Include="@(ServiceWorker->'$(IntermediateOutputPath)serviceworkers\%(Identity)')">
|
||||
<ContentSourcePath Condition="'%(_ServiceWorker.PublishedContent)' != ''">%(ServiceWorker.PublishedContent)</ContentSourcePath>
|
||||
<ContentSourcePath Condition="'%(_ServiceWorker.PublishedContent)' == ''">%(ServiceWorker.Identity)</ContentSourcePath>
|
||||
<OriginalPath>%(ServiceWorker.Identity)</OriginalPath>
|
||||
<TargetOutputPath>%(ServiceWorker.Identity)</TargetOutputPath>
|
||||
<TargetOutputPath Condition="$([System.String]::Copy('%(ServiceWorker.Identity)').Replace('\','/').StartsWith('wwwroot/'))">$([System.String]::Copy('%(ServiceWorker.Identity)').Substring(8))</TargetOutputPath>
|
||||
</_ServiceWorkerIntermediateFile>
|
||||
|
||||
<_ServiceWorkerStaticWebAsset Include="%(_ServiceWorkerIntermediateFile.FullPath)">
|
||||
<SourceType></SourceType>
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>%(TargetOutputPath)</RelativePath>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</_ServiceWorkerStaticWebAsset>
|
||||
|
||||
<StaticWebAsset Include="
|
||||
@(_ManifestStaticWebAsset);
|
||||
@(_ServiceWorkerStaticWebAsset)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_WriteServiceWorkerAssetsManifest"
|
||||
DependsOnTargets="_ComputeServiceWorkerAssets;ResolveStaticWebAssetsInputs">
|
||||
|
||||
<ItemGroup>
|
||||
<_ServiceWorkItem Include="@(StaticWebAsset)" Exclude="$(_ServiceWorkerAssetsManifestFullPath);@(_ServiceWorkerStaticWebAsset)">
|
||||
<AssetUrl>$([System.String]::Copy('$([System.String]::Copy('%(StaticWebAsset.BasePath)').TrimEnd('/'))/%(StaticWebAsset.RelativePath)').Replace('\','/').TrimStart('/'))</AssetUrl>
|
||||
</_ServiceWorkItem>
|
||||
</ItemGroup>
|
||||
|
||||
<GenerateServiceWorkerAssetsManifest
|
||||
Version="$(ServiceWorkerAssetsManifestVersion)"
|
||||
Assets="@(_ServiceWorkItem)"
|
||||
OutputPath="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)">
|
||||
<Output TaskParameter="CalculatedVersion" PropertyName="_ServiceWorkerAssetsManifestVersion" />
|
||||
</GenerateServiceWorkerAssetsManifest>
|
||||
|
||||
<Copy
|
||||
SourceFiles="%(_ServiceWorkerIntermediateFile.ContentSourcePath)"
|
||||
DestinationFiles="%(_ServiceWorkerIntermediateFile.Identity)" />
|
||||
|
||||
<WriteLinesToFile
|
||||
File="%(_ServiceWorkerIntermediateFile.Identity)"
|
||||
Lines="/* Manifest version: $(_ServiceWorkerAssetsManifestVersion) */"
|
||||
Condition="'$(_ServiceWorkerAssetsManifestVersion)' != ''" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="@(_ServiceWorkerIntermediateFile)" />
|
||||
<FileWrites Include="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorStaticAssetsCopyFilesToOutputDirectory" AfterTargets="CopyFilesToOutputDirectory" DependsOnTargets="_WriteServiceWorkerAssetsManifest">
|
||||
<Copy
|
||||
SourceFiles="@(_ManifestStaticWebAsset);@(_ServiceWorkerStaticWebAsset)"
|
||||
DestinationFiles="$(OutDir)wwwroot\%(RelativePath)"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
ErrorIfLinkFails="$(ErrorIfLinkFailsForCopyFilesToOutputDirectory)"
|
||||
Condition="Exists('%(Identity)')">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
</Target>
|
||||
|
||||
<Target Name="_OmitServiceWorkerContent"
|
||||
BeforeTargets="AssignTargetPaths;ResolveCurrentProjectStaticWebAssetsInputs">
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Don't emit the service worker source files to the output -->
|
||||
<Content Remove="@(ServiceWorker)" />
|
||||
<Content Remove="@(ServiceWorker->'%(PublishedContent)')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateServiceWorkerFileForPublish"
|
||||
BeforeTargets="_BlazorCompressPublishFiles"
|
||||
AfterTargets="_ProcessPublishFilesForBlazor">
|
||||
|
||||
<PropertyGroup>
|
||||
<_ServiceWorkerAssetsManifestPublishIntermediateOutputPath>$(IntermediateOutputPath)publish-$(ServiceWorkerAssetsManifest)</_ServiceWorkerAssetsManifestPublishIntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ServiceWorkerIntermediatePublishFile Include="$(IntermediateOutputPath)serviceworkers\%(FileName).publish%(Extension)">
|
||||
<ContentSourcePath Condition="'%(ServiceWorker.PublishedContent)' != ''">%(ServiceWorker.PublishedContent)</ContentSourcePath>
|
||||
<ContentSourcePath Condition="'%(ServiceWorker.PublishedContent)' == ''">%(ServiceWorker.Identity)</ContentSourcePath>
|
||||
<RelativePath>%(ServiceWorker.Identity)</RelativePath>
|
||||
</_ServiceWorkerIntermediatePublishFile>
|
||||
|
||||
<_ServiceWorkerPublishFile Include="@(ResolvedFileToPublish)" Condition="$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))">
|
||||
<AssetUrl>$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').TrimStart('/'))</AssetUrl>
|
||||
<AssetUrl>$([System.String]::Copy('%(RelativePath)').Replace('\','/').Substring(8))</AssetUrl>
|
||||
</_ServiceWorkerPublishFile>
|
||||
</ItemGroup>
|
||||
|
||||
<GenerateServiceWorkerAssetsManifest
|
||||
Version="$(ServiceWorkerAssetsManifestVersion)"
|
||||
Assets="@(_ServiceWorkerPublishFile)"
|
||||
OutputPath="$(_ServiceWorkerAssetsManifestPublishIntermediateOutputPath)">
|
||||
|
||||
<Output TaskParameter="CalculatedVersion" PropertyName="_ServiceWorkerPublishAssetsManifestVersion" />
|
||||
</GenerateServiceWorkerAssetsManifest>
|
||||
|
||||
<Copy SourceFiles="%(_ServiceWorkerIntermediatePublishFile.ContentSourcePath)"
|
||||
DestinationFiles="%(_ServiceWorkerIntermediatePublishFile.Identity)" />
|
||||
|
||||
<WriteLinesToFile
|
||||
File="%(_ServiceWorkerIntermediatePublishFile.Identity)"
|
||||
Lines="/* Manifest version: $(_ServiceWorkerPublishAssetsManifestVersion) */" />
|
||||
|
||||
<ItemGroup>
|
||||
<ResolvedFileToPublish
|
||||
Include="@(_ServiceWorkerIntermediatePublishFile)"
|
||||
CopyToPublishDirectory="PreserveNewest"
|
||||
RelativePath="%(_ServiceWorkerIntermediatePublishFile.RelativePath)"
|
||||
ExcludeFromSingleFile="true" />
|
||||
|
||||
<ResolvedFileToPublish
|
||||
Include="$(_ServiceWorkerAssetsManifestPublishIntermediateOutputPath)"
|
||||
CopyToPublishDirectory="PreserveNewest"
|
||||
RelativePath="wwwroot\$(ServiceWorkerAssetsManifest)"
|
||||
ExcludeFromSingleFile="true" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class BlazorReadSatelliteAssemblyFileTest
|
||||
{
|
||||
[Fact]
|
||||
public void WritesAndReadsRoundTrip()
|
||||
{
|
||||
// Arrange/Act
|
||||
var tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
var writer = new BlazorWriteSatelliteAssemblyFile
|
||||
{
|
||||
BuildEngine = Mock.Of<IBuildEngine>(),
|
||||
WriteFile = new TaskItem(tempFile),
|
||||
SatelliteAssembly = new[]
|
||||
{
|
||||
new TaskItem("Resources.fr.dll", new Dictionary<string, string>
|
||||
{
|
||||
["Culture"] = "fr",
|
||||
["DestinationSubDirectory"] = "fr\\",
|
||||
}),
|
||||
new TaskItem("Resources.ja-jp.dll", new Dictionary<string, string>
|
||||
{
|
||||
["Culture"] = "ja-jp",
|
||||
["DestinationSubDirectory"] = "ja-jp\\",
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
var reader = new BlazorReadSatelliteAssemblyFile
|
||||
{
|
||||
BuildEngine = Mock.Of<IBuildEngine>(),
|
||||
ReadFile = new TaskItem(tempFile),
|
||||
};
|
||||
|
||||
writer.Execute();
|
||||
|
||||
Assert.True(File.Exists(tempFile), "Write should have succeeded.");
|
||||
|
||||
reader.Execute();
|
||||
|
||||
Assert.Collection(
|
||||
reader.SatelliteAssembly,
|
||||
assembly =>
|
||||
{
|
||||
Assert.Equal("Resources.fr.dll", assembly.ItemSpec);
|
||||
Assert.Equal("fr", assembly.GetMetadata("Culture"));
|
||||
Assert.Equal("fr\\", assembly.GetMetadata("DestinationSubDirectory"));
|
||||
},
|
||||
assembly =>
|
||||
{
|
||||
Assert.Equal("Resources.ja-jp.dll", assembly.ItemSpec);
|
||||
Assert.Equal("ja-jp", assembly.GetMetadata("Culture"));
|
||||
Assert.Equal("ja-jp\\", assembly.GetMetadata("DestinationSubDirectory"));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
// 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.Linq;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using Microsoft.Build.Framework;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
||||
{
|
||||
public class GenerateBlazorWebAssemblyBootJsonTest
|
||||
{
|
||||
[Fact]
|
||||
public void GroupsResourcesByType()
|
||||
{
|
||||
// Arrange
|
||||
var taskInstance = new GenerateBlazorWebAssemblyBootJson
|
||||
{
|
||||
AssemblyPath = "MyApp.Entrypoint.dll",
|
||||
Resources = new[]
|
||||
{
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "My.Assembly1"),
|
||||
("Extension", ".dll"),
|
||||
("FileHash", "abcdefghikjlmnopqrstuvwxyz")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "My.Assembly2"),
|
||||
("Extension", ".dll"),
|
||||
("FileHash", "012345678901234567890123456789")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "SomePdb"),
|
||||
("Extension", ".pdb"),
|
||||
("FileHash", "pdbhashpdbhashpdbhash")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "My.Assembly1"),
|
||||
("Extension", ".pdb"),
|
||||
("FileHash", "pdbdefghikjlmnopqrstuvwxyz")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "some-runtime-file"),
|
||||
("FileHash", "runtimehashruntimehash"),
|
||||
("AssetType", "native")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "satellite-assembly1"),
|
||||
("Extension", ".dll"),
|
||||
("FileHash", "hashsatelliteassembly1"),
|
||||
("Culture", "en-GB")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "satellite-assembly2"),
|
||||
("Extension", ".dll"),
|
||||
("FileHash", "hashsatelliteassembly2"),
|
||||
("Culture", "fr")),
|
||||
|
||||
CreateResourceTaskItem(
|
||||
("FileName", "satellite-assembly3"),
|
||||
("Extension", ".dll"),
|
||||
("FileHash", "hashsatelliteassembly3"),
|
||||
("Culture", "en-GB")),
|
||||
}
|
||||
};
|
||||
|
||||
using var stream = new MemoryStream();
|
||||
|
||||
// Act
|
||||
taskInstance.WriteBootJson(stream, "MyEntrypointAssembly");
|
||||
|
||||
// Assert
|
||||
var parsedContent = ParseBootData(stream);
|
||||
Assert.Equal("MyEntrypointAssembly", parsedContent.entryAssembly);
|
||||
|
||||
var resources = parsedContent.resources.assembly;
|
||||
Assert.Equal(2, resources.Count);
|
||||
Assert.Equal("sha256-abcdefghikjlmnopqrstuvwxyz", resources["My.Assembly1.dll"]);
|
||||
Assert.Equal("sha256-012345678901234567890123456789", resources["My.Assembly2.dll"]);
|
||||
|
||||
resources = parsedContent.resources.pdb;
|
||||
Assert.Equal(2, resources.Count);
|
||||
Assert.Equal("sha256-pdbhashpdbhashpdbhash", resources["SomePdb.pdb"]);
|
||||
Assert.Equal("sha256-pdbdefghikjlmnopqrstuvwxyz", resources["My.Assembly1.pdb"]);
|
||||
|
||||
resources = parsedContent.resources.runtime;
|
||||
Assert.Single(resources);
|
||||
Assert.Equal("sha256-runtimehashruntimehash", resources["some-runtime-file"]);
|
||||
|
||||
var satelliteResources = parsedContent.resources.satelliteResources;
|
||||
Assert.Collection(
|
||||
satelliteResources.OrderBy(kvp => kvp.Key),
|
||||
kvp =>
|
||||
{
|
||||
Assert.Equal("en-GB", kvp.Key);
|
||||
Assert.Collection(
|
||||
kvp.Value.OrderBy(item => item.Key),
|
||||
item =>
|
||||
{
|
||||
Assert.Equal("en-GB/satellite-assembly1.dll", item.Key);
|
||||
Assert.Equal("sha256-hashsatelliteassembly1", item.Value);
|
||||
},
|
||||
item =>
|
||||
{
|
||||
Assert.Equal("en-GB/satellite-assembly3.dll", item.Key);
|
||||
Assert.Equal("sha256-hashsatelliteassembly3", item.Value);
|
||||
});
|
||||
},
|
||||
kvp =>
|
||||
{
|
||||
Assert.Equal("fr", kvp.Key);
|
||||
Assert.Collection(
|
||||
kvp.Value.OrderBy(item => item.Key),
|
||||
item =>
|
||||
{
|
||||
Assert.Equal("fr/satellite-assembly2.dll", item.Key);
|
||||
Assert.Equal("sha256-hashsatelliteassembly2", item.Value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void CanSpecifyCacheBootResources(bool flagValue)
|
||||
{
|
||||
// Arrange
|
||||
var taskInstance = new GenerateBlazorWebAssemblyBootJson { CacheBootResources = flagValue };
|
||||
using var stream = new MemoryStream();
|
||||
|
||||
// Act
|
||||
taskInstance.WriteBootJson(stream, "MyEntrypointAssembly");
|
||||
|
||||
// Assert
|
||||
var parsedContent = ParseBootData(stream);
|
||||
Assert.Equal(flagValue, parsedContent.cacheBootResources);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void CanSpecifyDebugBuild(bool flagValue)
|
||||
{
|
||||
// Arrange
|
||||
var taskInstance = new GenerateBlazorWebAssemblyBootJson { DebugBuild = flagValue };
|
||||
using var stream = new MemoryStream();
|
||||
|
||||
// Act
|
||||
taskInstance.WriteBootJson(stream, "MyEntrypointAssembly");
|
||||
|
||||
// Assert
|
||||
var parsedContent = ParseBootData(stream);
|
||||
Assert.Equal(flagValue, parsedContent.debugBuild);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void CanSpecifyLinkerEnabled(bool flagValue)
|
||||
{
|
||||
// Arrange
|
||||
var taskInstance = new GenerateBlazorWebAssemblyBootJson { LinkerEnabled = flagValue };
|
||||
using var stream = new MemoryStream();
|
||||
|
||||
// Act
|
||||
taskInstance.WriteBootJson(stream, "MyEntrypointAssembly");
|
||||
|
||||
// Assert
|
||||
var parsedContent = ParseBootData(stream);
|
||||
Assert.Equal(flagValue, parsedContent.linkerEnabled);
|
||||
}
|
||||
|
||||
private static BootJsonData ParseBootData(Stream stream)
|
||||
{
|
||||
stream.Position = 0;
|
||||
var serializer = new DataContractJsonSerializer(
|
||||
typeof(BootJsonData),
|
||||
new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true });
|
||||
return (BootJsonData)serializer.ReadObject(stream);
|
||||
}
|
||||
|
||||
private static ITaskItem CreateResourceTaskItem(params (string key, string value)[] values)
|
||||
{
|
||||
var mock = new Mock<ITaskItem>();
|
||||
|
||||
foreach (var (key, value) in values)
|
||||
{
|
||||
mock.Setup(m => m.GetMetadata(key)).Returns(value);
|
||||
}
|
||||
return mock.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Build.Utilities.Core" />
|
||||
<Reference Include="Microsoft.NET.Sdk.BlazorWebAssembly" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<Project>
|
||||
<Import Project="Before.Directory.Build.props" Condition="Exists('Before.Directory.Build.props')" />
|
||||
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
In the case that a user is building a sample directly the MicrosoftNetCompilersToolsetPackagerVersion will not be provided.
|
||||
We'll fall back to whatever the current SDK provides in regards to Roslyn's Microsoft.Net.Compilers.Toolset.
|
||||
-->
|
||||
<BuildingTestAppsIndependently>false</BuildingTestAppsIndependently>
|
||||
<BuildingTestAppsIndependently Condition="'$(MicrosoftNetCompilersToolsetPackageVersion)' == ''">true</BuildingTestAppsIndependently>
|
||||
|
||||
<!-- Do not resolve Reference ItemGroup since it has a different semantic meaning in Razor test apps -->
|
||||
<EnableCustomReferenceResolution>false</EnableCustomReferenceResolution>
|
||||
|
||||
<DefaultNetCoreTargetFramework>net5.0</DefaultNetCoreTargetFramework>
|
||||
|
||||
<RepoRoot Condition="'$(RepoRoot)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, 'AspNetCore.sln'))\</RepoRoot>
|
||||
|
||||
<RazorSdkCurrentVersionProps>$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Sdk.Razor.CurrentVersion.props</RazorSdkCurrentVersionProps>
|
||||
<RazorSdkCurrentVersionTargets>$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Sdk.Razor.CurrentVersion.targets</RazorSdkCurrentVersionTargets>
|
||||
<RazorSdkArtifactsDirectory>$(RepoRoot)artifacts\bin\Microsoft.NET.Sdk.Razor\</RazorSdkArtifactsDirectory>
|
||||
<BlazorWebAssemblySdkArtifactsDirectory>$(RepoRoot)artifacts\bin\Microsoft.NET.Sdk.BlazorWebAssembly\</BlazorWebAssemblySdkArtifactsDirectory>
|
||||
<BlazorWebAssemblyJSPath>$(MSBuildThisFileDirectory)blazor.webassembly.js</BlazorWebAssemblyJSPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(RepoRoot)eng\Versions.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Reset version prefix to 1.0.0 for test projects -->
|
||||
<VersionPrefix>1.0.0</VersionPrefix>
|
||||
|
||||
<!-- Turn down the compression level for brotli -->
|
||||
<_BlazorBrotliCompressionLevel>NoCompression</_BlazorBrotliCompressionLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Have the SDK treat the MvcShim as an MVC assembly -->
|
||||
<_MvcAssemblyName Include="Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(BuildingTestAppsIndependently) == 'false'">
|
||||
<PackageReference Include="Microsoft.Net.Compilers.Toolset"
|
||||
Version="$(MicrosoftNetCompilersToolsetPackageVersion)"
|
||||
PrivateAssets="all"
|
||||
IsImplicitlyDefined="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="After.Directory.Build.props" Condition="Exists('After.Directory.Build.props')" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)' ">$(MicrosoftNETCoreAppRuntimeVersion)</RuntimeFrameworkVersion>
|
||||
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
|
||||
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\blazorhosted\blazorhosted.csproj" />
|
||||
<ProjectReference Include="..\blazorhosted-rid\blazorhosted-rid.csproj" />
|
||||
<ProjectReference Include="..\blazorwasm\blazorwasm.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1 @@
|
|||
Test file
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<Import Project="$(RepoRoot)src\Components\WebAssembly\Sdk\src\Sdk\Sdk.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<RazorSdkDirectoryRoot>$(RazorSdkArtifactsDirectory)$(Configuration)\sdk-output\</RazorSdkDirectoryRoot>
|
||||
<BlazorWebAssemblySdkDirectoryRoot>$(BlazorWebAssemblySdkArtifactsDirectory)$(Configuration)\sdk-output\</BlazorWebAssemblySdkDirectoryRoot>
|
||||
<ServiceWorkerAssetsManifest>custom-service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
@ -50,4 +52,6 @@
|
|||
<ServiceWorker Include="wwwroot\serviceworkers\my-service-worker.js" PublishedContent="wwwroot\serviceworkers\my-prod-service-worker.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(RepoRoot)src\Components\WebAssembly\Sdk\src\Sdk\Sdk.targets" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly.Tools
|
||||
{
|
||||
internal class Application : CommandLineApplication
|
||||
{
|
||||
public Application(
|
||||
CancellationToken cancellationToken,
|
||||
TextWriter output = null,
|
||||
TextWriter error = null)
|
||||
{
|
||||
CancellationToken = cancellationToken;
|
||||
Out = output ?? Out;
|
||||
Error = error ?? Error;
|
||||
|
||||
Name = "BlazorWebAssembly.Tools";
|
||||
FullName = "Microsoft Blazor WebAssembly SDK tool";
|
||||
Description = "CLI for Blazor WebAssembly operations.";
|
||||
ShortVersionGetter = GetInformationalVersion;
|
||||
|
||||
HelpOption("-?|-h|--help");
|
||||
|
||||
Commands.Add(new BrotliCompressCommand(this));
|
||||
}
|
||||
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
public new int Execute(params string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
return base.Execute(ExpandResponseFiles(args));
|
||||
}
|
||||
catch (AggregateException ex) when (ex.InnerException != null)
|
||||
{
|
||||
foreach (var innerException in ex.Flatten().InnerExceptions)
|
||||
{
|
||||
Error.WriteLine(innerException.Message);
|
||||
Error.WriteLine(innerException.StackTrace);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
catch (CommandParsingException ex)
|
||||
{
|
||||
// Don't show a call stack when we have unneeded arguments, just print the error message.
|
||||
// The code that throws this exception will print help, so no need to do it here.
|
||||
Error.WriteLine(ex.Message);
|
||||
return 1;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// This is a cancellation, not a failure.
|
||||
Error.WriteLine("Cancelled");
|
||||
return 1;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Error.WriteLine(ex.Message);
|
||||
Error.WriteLine(ex.StackTrace);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetInformationalVersion()
|
||||
{
|
||||
var assembly = typeof(Application).GetTypeInfo().Assembly;
|
||||
var attribute = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
||||
return attribute.InformationalVersion;
|
||||
}
|
||||
|
||||
private static string[] ExpandResponseFiles(string[] args)
|
||||
{
|
||||
var expandedArgs = new List<string>();
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (!arg.StartsWith("@", StringComparison.Ordinal))
|
||||
{
|
||||
expandedArgs.Add(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = arg.Substring(1);
|
||||
expandedArgs.AddRange(File.ReadLines(fileName));
|
||||
}
|
||||
}
|
||||
|
||||
return expandedArgs.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// 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;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly.Tools
|
||||
{
|
||||
internal class BrotliCompressCommand : CommandLineApplication
|
||||
{
|
||||
public BrotliCompressCommand(Application parent)
|
||||
: base(throwOnUnexpectedArg: true)
|
||||
{
|
||||
base.Parent = parent;
|
||||
Name = "brotli";
|
||||
Sources = Option("-s", "files to compress", CommandOptionType.MultipleValue);
|
||||
Outputs = Option("-o", "Output file path", CommandOptionType.MultipleValue);
|
||||
CompressionLevelOption = Option("-c", "Compression level", CommandOptionType.SingleValue);
|
||||
|
||||
Invoke = () => Execute().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public CommandOption Sources { get; }
|
||||
|
||||
public CommandOption Outputs { get; }
|
||||
|
||||
public CommandOption CompressionLevelOption { get; }
|
||||
|
||||
public CompressionLevel CompressionLevel { get; private set; } = CompressionLevel.Optimal;
|
||||
|
||||
private Task<int> Execute()
|
||||
{
|
||||
if (!ValidateArguments())
|
||||
{
|
||||
ShowHelp();
|
||||
return Task.FromResult(1);
|
||||
}
|
||||
|
||||
return ExecuteCoreAsync();
|
||||
}
|
||||
|
||||
private bool ValidateArguments()
|
||||
{
|
||||
if (Sources.Values.Count != Outputs.Values.Count)
|
||||
{
|
||||
Error.WriteLine($"{Sources.Description} has {Sources.Values.Count}, but {Outputs.Description} has {Outputs.Values.Count} values.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CompressionLevelOption.HasValue())
|
||||
{
|
||||
if (!Enum.TryParse<CompressionLevel>(CompressionLevelOption.Value(), out var value))
|
||||
{
|
||||
Error.WriteLine($"Invalid option {CompressionLevelOption.Value()} for {CompressionLevelOption.Template}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CompressionLevel = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Task<int> ExecuteCoreAsync()
|
||||
{
|
||||
Parallel.For(0, Sources.Values.Count, i =>
|
||||
{
|
||||
var source = Sources.Values[i];
|
||||
var output = Outputs.Values[i];
|
||||
|
||||
using var sourceStream = File.OpenRead(source);
|
||||
using var fileStream = new FileStream(output, FileMode.Create);
|
||||
|
||||
using var stream = new BrotliStream(fileStream, CompressionLevel);
|
||||
|
||||
sourceStream.CopyTo(stream);
|
||||
});
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly.Tools
|
||||
{
|
||||
internal static class DebugMode
|
||||
{
|
||||
public static void HandleDebugSwitch(ref string[] args)
|
||||
{
|
||||
if (args.Length > 0 && string.Equals("--debug", args[0], StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
args = args.Skip(1).ToArray();
|
||||
|
||||
Console.WriteLine("Waiting for debugger in pid: {0}", Process.GetCurrentProcess().Id);
|
||||
while (!Debugger.IsAttached)
|
||||
{
|
||||
Thread.Sleep(TimeSpan.FromSeconds(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsShipping>false</IsShipping>
|
||||
<DisablePubternalApiCheck>true</DisablePubternalApiCheck>
|
||||
|
||||
<UseAppHost>false</UseAppHost>
|
||||
<RuntimeIdentifier />
|
||||
|
||||
<!-- Need to build this project in source build -->
|
||||
<ExcludeFromSourceBuild>false</ExcludeFromSourceBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.NET.Sdk.BlazorWebAssembly.Tools
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
DebugMode.HandleDebugSwitch(ref args);
|
||||
|
||||
var cancel = new CancellationTokenSource();
|
||||
Console.CancelKeyPress += (sender, e) => { cancel.Cancel(); };
|
||||
|
||||
var application = new Application(
|
||||
cancel.Token,
|
||||
Console.Out,
|
||||
Console.Error);
|
||||
|
||||
application.Commands.Add(new BrotliCompressCommand(application));
|
||||
|
||||
return application.Execute(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rollForwardOnNoCandidateFx": 2
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
|
|
@ -13,8 +13,11 @@
|
|||
|
||||
<!-- Tests do not work on Helix yet -->
|
||||
<BuildHelixPayload>false</BuildHelixPayload>
|
||||
<TestAppsRoot>$(MSBuildProjectDirectory)\..\..\test\testassets\</TestAppsRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SharedSourceRoot)MSBuild.Testing\MSBuild.Testing.targets" />
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
|
@ -24,49 +27,6 @@
|
|||
<Reference Include="Microsoft.Extensions.DependencyModel" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.AdditionalRestoreSources</_Parameter1>
|
||||
<_Parameter2>$(MSBuildThisFileDirectory)..\testassets\PregeneratedPackages</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>ArtifactsLogDir</_Parameter1>
|
||||
<_Parameter2>$([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'log', '$(_BuildConfig)'))</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>ProcDumpToolPath</_Parameter1>
|
||||
<_Parameter2>$(ProcDumpPath)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.RepoRoot</_Parameter1>
|
||||
<_Parameter2>$(RepoRoot)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>MicrosoftNETCoreAppRuntimeVersion</_Parameter1>
|
||||
<_Parameter2>$(MicrosoftNETCoreAppRuntimeVersion)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>DefaultNetCoreTargetFramework</_Parameter1>
|
||||
<_Parameter2>$(DefaultNetCoreTargetFramework)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>MicrosoftNetCompilersToolsetPackageVersion</_Parameter1>
|
||||
<_Parameter2>$(MicrosoftNetCompilersToolsetPackageVersion)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>RazorSdkDirectoryRoot</_Parameter1>
|
||||
<_Parameter2>$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\sdk-output\</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="rzc" />
|
||||
<ProjectReference Include="..\..\test\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.csproj" />
|
||||
|
|
|
|||
|
|
@ -66,14 +66,9 @@
|
|||
<_DefaultProjectRoot>$([System.IO.Path]::GetFullPath($(_DefaultProjectFilter)))</_DefaultProjectRoot>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<_ContentRootProjectReferencesUnfiltered
|
||||
Include="@(ReferencePath)"
|
||||
Condition="'%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference'" />
|
||||
<_ContentRootProjectReferencesFilter
|
||||
Include="@(_ContentRootProjectReferencesUnfiltered->StartsWith('$(_DefaultProjectRoot)'))" />
|
||||
<_ContentRootProjectReferences
|
||||
Include="@(_ContentRootProjectReferencesFilter)"
|
||||
Condition="'%(Identity)' == 'True'" />
|
||||
Include="@(ReferencePath)"
|
||||
Condition="'%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference' AND $([System.String]::Copy(%(ReferencePath.MSBuildSourceProjectFile)).StartsWith('$(_DefaultProjectRoot)'))" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,12 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
public static string RazorSdkDirectoryRoot => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "RazorSdkDirectoryRoot").Value;
|
||||
|
||||
public static string BlazorWebAssemblySdkDirectoryRoot => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "BlazorWebAssemblySdkDirectoryRoot").Value;
|
||||
|
||||
public static string RepoRoot => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "Testing.RepoRoot").Value;
|
||||
|
||||
|
||||
public static string DefaultNetCoreTargetFramework => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "DefaultNetCoreTargetFramework").Value;
|
||||
|
||||
public static string TestAppsRoot => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "TestAppsRoot").Value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<Project>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>ArtifactsLogDir</_Parameter1>
|
||||
<_Parameter2>$([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'log', '$(_BuildConfig)'))</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>ProcDumpToolPath</_Parameter1>
|
||||
<_Parameter2>$(ProcDumpPath)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.RepoRoot</_Parameter1>
|
||||
<_Parameter2>$(RepoRoot)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>MicrosoftNETCoreAppRuntimeVersion</_Parameter1>
|
||||
<_Parameter2>$(MicrosoftNETCoreAppRuntimeVersion)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>DefaultNetCoreTargetFramework</_Parameter1>
|
||||
<_Parameter2>$(DefaultNetCoreTargetFramework)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>MicrosoftNetCompilersToolsetPackageVersion</_Parameter1>
|
||||
<_Parameter2>$(MicrosoftNetCompilersToolsetPackageVersion)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>RazorSdkDirectoryRoot</_Parameter1>
|
||||
<_Parameter2>$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\sdk-output\</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>BlazorWebAssemblySdkDirectoryRoot</_Parameter1>
|
||||
<_Parameter2>$(ArtifactsBinDir)Microsoft.NET.Sdk.BlazorWebAssembly\$(Configuration)\sdk-output\</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>TestAppsRoot</_Parameter1>
|
||||
<_Parameter2>$(TestAppsRoot)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)*.cs" LinkBase="Infrastructure" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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;
|
||||
|
|
@ -37,6 +37,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
$"/p:MicrosoftNETCoreAppRuntimeVersion={BuildVariables.MicrosoftNETCoreAppRuntimeVersion}",
|
||||
$"/p:MicrosoftNetCompilersToolsetPackageVersion={BuildVariables.MicrosoftNetCompilersToolsetPackageVersion}",
|
||||
$"/p:RazorSdkDirectoryRoot={BuildVariables.RazorSdkDirectoryRoot}",
|
||||
$"/p:BlazorWebAssemblySdkDirectoryRoot={BuildVariables.BlazorWebAssemblySdkDirectoryRoot}",
|
||||
$"/p:RepoRoot={BuildVariables.RepoRoot}",
|
||||
$"/p:Configuration={project.Configuration}",
|
||||
$"/t:{target}",
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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;
|
||||
|
|
@ -49,12 +49,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
|
||||
var repositoryRoot = BuildVariables.RepoRoot;
|
||||
var solutionRoot = Path.Combine(repositoryRoot, "src", "Razor");
|
||||
var binariesRoot = Path.GetDirectoryName(typeof(ProjectDirectory).Assembly.Location);
|
||||
var testAppsRoot = BuildVariables.TestAppsRoot;
|
||||
|
||||
foreach (var project in new string[] { originalProjectName, }.Concat(additionalProjects))
|
||||
{
|
||||
var testAppsRoot = Path.Combine(solutionRoot, "test", "testassets");
|
||||
var projectRoot = Path.Combine(testAppsRoot, project);
|
||||
if (!Directory.Exists(projectRoot))
|
||||
{
|
||||
|
|
@ -146,6 +145,11 @@ $@"<Project>
|
|||
.ForEach(file =>
|
||||
{
|
||||
var source = Path.Combine(testAppsRoot, file);
|
||||
if (!File.Exists(source))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var destination = Path.Combine(projectDestination, file);
|
||||
File.Copy(source, destination);
|
||||
});
|
||||
Loading…
Reference in New Issue