Create a Blazor WebAssembly SDK (#24044)

This commit is contained in:
Pranav K 2020-07-20 13:25:49 -07:00 committed by GitHub
parent 5266918ed2
commit e822f5f12d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 2625 additions and 72 deletions

View File

@ -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}

View File

@ -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\**\*;"

View File

@ -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" />

View File

@ -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"
]
}

View File

@ -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",

View File

@ -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>

View File

@ -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 &quot;$(_BlazorDevServerPath)&quot; serve --applicationpath &quot;$(TargetPath)&quot; $(AdditionalRunArguments)</RunArguments>
</PropertyGroup>

View File

@ -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="&quot;$(NuGetPackageRoot)vswhere\$(VSWhereVersion)\tools\vswhere.exe&quot; -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>

View File

@ -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
{

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -0,0 +1,5 @@
{
"methodDisplay": "method",
"shadowCopy": false,
"maxParallelThreads": -1
}

View File

@ -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
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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 -&gt; $(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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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) -&gt; $(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>

View File

@ -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>

View File

@ -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"));
});
}
}
}

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1 @@
Test file

View 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>

View File

@ -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();
}
}
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}
}
}
}

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -0,0 +1,3 @@
{
"rollForwardOnNoCandidateFx": 2
}

View File

@ -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" />

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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}",

View File

@ -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);
});