Use linker extensibility to enable better trimming (#23512)
* Use linker extensibility to enable better trimming * Configure TrimmerDefaults=link if unspecified * Allow Microsoft.AspNetCore.* and Microsoft.Extensions.* packages to be trimmed. * Make producing the trimmer root descriptor more incremental
This commit is contained in:
parent
7f4b846e9f
commit
8768cab874
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "5.0.100-preview.6.20310.4"
|
||||
"version": "5.0.100-preview.7.20330.3"
|
||||
},
|
||||
"tools": {
|
||||
"dotnet": "5.0.100-preview.6.20310.4",
|
||||
"dotnet": "5.0.100-preview.7.20330.3",
|
||||
"runtimes": {
|
||||
"dotnet/x64": [
|
||||
"2.1.18",
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
{
|
||||
using (var file = File.OpenRead(assemblyPath))
|
||||
{
|
||||
var peReader = new PEReader(file);
|
||||
using var peReader = new PEReader(file);
|
||||
var metadataReader = peReader.GetMetadataReader();
|
||||
return metadataReader.TypeDefinitions.Where(t => !t.IsNil).Select(t =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Razor.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
||||
using static Microsoft.AspNetCore.Razor.Design.IntegrationTests.ServiceWorkerAssert;
|
||||
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
{
|
||||
|
|
@ -60,6 +60,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
|
||||
serviceWorkerContent: "// This is the production service worker",
|
||||
assetsManifestPath: "custom-service-worker-assets.js");
|
||||
|
||||
VerifyTypeGranularTrimming(result, blazorPublishDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -223,6 +225,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
|
||||
serviceWorkerContent: "// This is the production service worker",
|
||||
assetsManifestPath: "custom-service-worker-assets.js");
|
||||
|
||||
// Verify assemblies are not trimmed
|
||||
var loggingAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.Extensions.Logging.Abstractions.dll");
|
||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.Abstractions.NullLogger");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -309,6 +315,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
|
||||
serviceWorkerContent: "// This is the production service worker",
|
||||
assetsManifestPath: "custom-service-worker-assets.js");
|
||||
|
||||
VerifyTypeGranularTrimming(result, blazorPublishDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -693,6 +701,21 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void VerifyTypeGranularTrimming(MSBuildResult result, string blazorPublishDirectory)
|
||||
{
|
||||
var loggingAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.Extensions.Logging.Abstractions.dll");
|
||||
Assert.FileExists(result, loggingAssemblyPath);
|
||||
|
||||
// ILogger is referenced by the app, so we expect it to be preserved
|
||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.ILogger");
|
||||
// LogLevel is referenced by ILogger and therefore must be preserved.
|
||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.LogLevel");
|
||||
|
||||
// NullLogger is not referenced by the app, and should be trimmed.
|
||||
Assert.AssemblyDoesNotContainType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.Abstractions.NullLogger");
|
||||
}
|
||||
|
||||
private static BootJsonData ReadBootJsonData(MSBuildResult result, string path)
|
||||
{
|
||||
return JsonSerializer.Deserialize<BootJsonData>(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// 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;
|
||||
|
|
@ -21,16 +23,27 @@ namespace Microsoft.AspNetCore.Razor.Tasks
|
|||
|
||||
public override bool Execute()
|
||||
{
|
||||
using var fileStream = File.Create(TrimmerFile.ItemSpec);
|
||||
var rootDescriptor = CreateRootDescriptorContents();
|
||||
if (File.Exists(TrimmerFile.ItemSpec))
|
||||
{
|
||||
var existing = File.ReadAllText(TrimmerFile.ItemSpec);
|
||||
|
||||
WriteRootDescriptor(fileStream);
|
||||
return true;
|
||||
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 void WriteRootDescriptor(Stream stream)
|
||||
internal string CreateRootDescriptorContents()
|
||||
{
|
||||
var roots = new XElement("linker");
|
||||
foreach (var assembly in Assemblies)
|
||||
foreach (var assembly in Assemblies.OrderBy(a => a.ItemSpec))
|
||||
{
|
||||
// NOTE: Descriptor files don't include the file extension
|
||||
// in the assemblyName.
|
||||
|
|
@ -60,10 +73,7 @@ namespace Microsoft.AspNetCore.Razor.Tasks
|
|||
OmitXmlDeclaration = true
|
||||
};
|
||||
|
||||
using var writer = XmlWriter.Create(stream, xmlWriterSettings);
|
||||
var xDocument = new XDocument(roots);
|
||||
|
||||
xDocument.Save(writer);
|
||||
return new XDocument(roots).Root.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,13 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
<UsingTask TaskName="Microsoft.AspNetCore.Razor.Tasks.CreateBlazorTrimmerRootDescriptorFile" AssemblyFile="$(RazorSdkBuildTasksAssembly)" />
|
||||
|
||||
<PropertyGroup>
|
||||
<PublishTrimmed Condition="'$(PublishTrimmed)' == ''">true</PublishTrimmed>
|
||||
<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>
|
||||
|
||||
|
|
@ -46,14 +49,6 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
<KnownFrameworkReference Remove="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Temporary workaround until ILLink.targets are updated -->
|
||||
<PropertyGroup Condition=" '$(PublishTrimmed)' == 'true' ">
|
||||
<IntermediateLinkDir Condition=" '$(IntermediateLinkDir)' == '' ">$(IntermediateOutputPath)linked\</IntermediateLinkDir>
|
||||
<IntermediateLinkDir Condition=" !HasTrailingSlash('$(IntermediateLinkDir)') ">$(IntermediateLinkDir)\</IntermediateLinkDir>
|
||||
<!-- Used to enable incremental build for the linker target. -->
|
||||
<_LinkSemaphore>$(IntermediateOutputPath)Link.semaphore</_LinkSemaphore>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Microsoft.NET.Sdk.Razor.Components.ServiceWorkerAssetsManifest.targets" Condition="'$(ServiceWorkerAssetsManifest)' != ''" />
|
||||
|
||||
<Target Name="_ScrambleDotnetJsFileName" AfterTargets="ResolveRuntimePackAssets">
|
||||
|
|
@ -312,18 +307,22 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
</Copy>
|
||||
</Target>
|
||||
|
||||
<Target Name="_CreateBlazorTrimmerRootDescriptorFiles" BeforeTargets="ILLink" AfterTargets="ComputeResolvedFilesToPublishList">
|
||||
<Target Name="_BlazorWasmPrepareForLink" BeforeTargets="PrepareForILLink">
|
||||
<PropertyGroup>
|
||||
<_BlazorTypeGranularTrimmerDescriptorFile>$(IntermediateOutputPath)typegranularity.trimmerdescriptor.xml</_BlazorTypeGranularTrimmerDescriptorFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorTypeGranularAssembly
|
||||
Include="@(ResolvedFileToPublish)"
|
||||
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
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace standalone
|
|||
{
|
||||
GC.KeepAlive(typeof(System.Text.Json.JsonSerializer));
|
||||
GC.KeepAlive(typeof(RazorClassLibrary.Class1));
|
||||
GC.KeepAlive(typeof(Microsoft.Extensions.Logging.ILogger));
|
||||
#if REFERENCE_classlibrarywithsatelliteassemblies
|
||||
GC.KeepAlive(typeof(classlibrarywithsatelliteassemblies.Class1));
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@
|
|||
<ProjectReference Include="..\razorclasslibrary\RazorClassLibrary.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--
|
||||
We need a Microsoft.* package to verify type granular trimming. We'll pick a fixed version to we can bake in some details about
|
||||
the contents of the package in our tests.
|
||||
-->
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- These assets should be treated as static web assets for publish purposes -->
|
||||
<Content Include="..\LinkBaseToWebRoot\**\*.js">
|
||||
|
|
|
|||
Loading…
Reference in New Issue