Pre-trim Mono BCL (#1382)

* Add "ilwipe" build command

* Perform BCL wipe as part of build

* Simplify by converting ilwipe command to process entire directories

* Clean up the build
This commit is contained in:
Steve Sanderson 2018-09-05 10:03:54 +01:00 committed by GitHub
parent b004ffdc24
commit facc1e466e
15 changed files with 498 additions and 35 deletions

View File

@ -8,9 +8,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B867E038-B3CE-43E3-9292-61568C46CDEB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mono", "mono", "{7B5CAAB1-A3EB-44F7-87E3-A13ED89FC17D}"
ProjectSection(SolutionItems) = preProject
src\mono\mono.targets = src\mono\mono.targets
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "samples\MonoSanity\MonoSanity.csproj", "{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}"
EndProject
@ -125,6 +122,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{F380
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.JSInterop.Test", "modules\jsinterop\test\Microsoft.JSInterop.Test\Microsoft.JSInterop.Test.csproj", "{ECF02708-4CA4-44B3-B23F-274F4B417FA5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mono", "src\mono\mono.csproj", "{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -456,6 +455,14 @@ Global
{ECF02708-4CA4-44B3-B23F-274F4B417FA5}.Release|Any CPU.Build.0 = Release|Any CPU
{ECF02708-4CA4-44B3-B23F-274F4B417FA5}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
{ECF02708-4CA4-44B3-B23F-274F4B417FA5}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.Release|Any CPU.Build.0 = Release|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -512,6 +519,7 @@ Global
{4A5D7F9D-9CED-44C1-983E-054D8E99A292} = {1386F99B-3862-40C2-B24D-796C07DC7921}
{1386F99B-3862-40C2-B24D-796C07DC7921} = {F380B6B6-9486-42BC-9B24-C388F8BF13A3}
{ECF02708-4CA4-44B3-B23F-274F4B417FA5} = {ADA3AE29-F6DE-49F6-8C7C-B321508CAE8E}
{DEEAE26E-D00C-4A3C-BE12-7A51A63CE55E} = {7B5CAAB1-A3EB-44F7-87E3-A13ED89FC17D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {504DA352-6788-4DC0-8705-82167E72A4D3}

View File

@ -5,18 +5,20 @@
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<DefaultItemExcludes>${DefaultItemExcludes};node_modules\**</DefaultItemExcludes>
<IsPackable>false</IsPackable>
<!-- VS's FastUpToDateCheck doesn't consider .ts file changes, so it's necessary to disable it to get incremental builds to work correctly (albeit not as fast as if FastUpToDateCheck did work for them) -->
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.Blazor.BuildTools\Microsoft.AspNetCore.Blazor.BuildTools.csproj" PrivateAssets="all" ReferenceOutputAssembly="false" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="$(AspNetCorePackageVersion)" />
<WebpackInputs Include="**\*.ts" Exclude="node_modules\**" />
<WebpackInputs Include="..\..\modules\jsinterop\src\Microsoft.JSInterop.JS\src\**" />
</ItemGroup>
<Import Project="..\Microsoft.AspNetCore.Blazor.BuildTools\ReferenceFromSource.props" />
<Import Project="..\Microsoft.AspNetCore.Blazor.BuildTools\BuildToolsExe.props" />
<Target Name="EnsureNpmRestored" Condition="!Exists('node_modules')">
<Exec Command="$(BlazorBuildToolsExe) checknodejs -v 8.3.0" />

View File

@ -21,9 +21,6 @@
<Import Project="$(MSBuildThisFileDirectory)targets/All.props" />
<Import Project="$(MSBuildThisFileDirectory)targets/All.targets" />
<Import Project="$(MSBuildThisFileDirectory)../mono/mono.targets" />
<Target Name="ProvisionMono" DependsOnTargets="OptimizeMono" BeforeTargets="BuildBlazorBuildBinary" />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="$(RazorPackageVersion)"/>
@ -37,9 +34,11 @@
<Target
Name="BuildBlazorBuildBinary"
BeforeTargets="BlazorGenerateDeclaration">
<!-- Ensures this project is built before the consuming project, but without
<!-- Ensures these projects are built before the consuming project, but without
adding a runtime dependency on the .dll (to be equivalent to a <PackageDependency>
given that the packed version of this project wouldn't add a .dll reference) -->
<MSBuild Projects="$(MSBuildThisFileDirectory)..\Microsoft.AspNetCore.Blazor.BuildTools\Microsoft.AspNetCore.Blazor.BuildTools.csproj" Targets="Build" />
<MSBuild Projects="$(MSBuildThisFileDirectory)..\mono\mono.csproj" Targets="Build" />
<MSBuild Projects="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Blazor.Build.csproj" Targets="Build" />
</Target>

View File

@ -25,13 +25,4 @@
<BlazorBootJsonOutputPath>$(BaseBlazorRuntimeOutputPath)$(BlazorBootJsonName)</BlazorBootJsonOutputPath>
</PropertyGroup>
<ItemGroup>
<MonoBCLFile Include="$(MonoBaseClassLibraryPath)*.dll" />
<MonoBCLFacadeFile Include="$(MonoBaseClassLibraryFacadesPath)*.dll" />
<MonoAsmjsFile Include="$(MonoAsmjsRuntimePath)**/*.*" />
<MonoWasmFile Include="$(MonoWasmRuntimePath)**/*.*" />
<BlazorJsFile Include="$(BlazorJsPath)" />
<MonoBaseClassLibraryFolder Include="$(MonoBaseClassLibraryPath);$(MonoBaseClassLibraryFacadesPath)" />
</ItemGroup>
</Project>

View File

@ -157,6 +157,9 @@
</PropertyGroup>
<ItemGroup Label="Static content to copy to the output folder">
<MonoAsmjsFile Include="$(MonoAsmjsRuntimePath)**/*.*" />
<MonoWasmFile Include="$(MonoWasmRuntimePath)**/*.*" />
<BlazorJsFile Include="$(BlazorJsPath)" />
<BlazorItemOutput Include="@(MonoAsmjsFile)">
<TargetOutputPath>$(TargetDir)$(BaseBlazorRuntimeAsmjsOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>AsmJs</Type>
@ -424,9 +427,10 @@
4) Add the file we just created to the list of file writes, to support incremental builds.
-->
<ItemGroup>
<_MonoBaseClassLibraryFolder Include="$(MonoBaseClassLibraryPath);$(MonoBaseClassLibraryFacadesPath)" />
<_BlazorAssembliesToLink Include="@(_BlazorDependencyInput->'-a &quot;%(Identity)&quot;')" />
<_BlazorAssembliesToLink Include="@(IntermediateAssembly->'-a &quot;%(FullPath)&quot;')" />
<_BlazorFolderLookupPaths Include="@(MonoBaseClassLibraryFolder->'-d &quot;%(Identity)&quot;')" />
<_BlazorFolderLookupPaths Include="@(_MonoBaseClassLibraryFolder->'-d &quot;%(Identity)&quot;')" />
<_BlazorAssemblyDescriptorFiles
Include="@(BlazorLinkerDescriptor->'-x &quot;%(FullPath)&quot;')" Condition="'@(BlazorLinkerDescriptor)' != ''" />
</ItemGroup>

View File

@ -0,0 +1,5 @@
<Project>
<PropertyGroup>
<BlazorBuildToolsExe>dotnet &quot;$(ArtifactsBinDir)Microsoft.AspNetCore.Blazor.BuildTools/netcoreapp2.1/Microsoft.AspNetCore.Blazor.BuildTools.dll&quot;</BlazorBuildToolsExe>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,110 @@
// 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 Microsoft.AspNetCore.Blazor.BuildTools.Core.ILWipe;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Blazor.BuildTools.Cli.Commands
{
static class ILWipeCommand
{
public static void Command(CommandLineApplication command)
{
command.Description = "Wipes code from .NET assemblies.";
command.HelpOption("-?|-h|--help");
var inputDirOption = command.Option(
"-i|--input",
"The directory containing assemblies from which code should be wiped.",
CommandOptionType.SingleValue);
var specFileOption = command.Option(
"-s|--spec",
"The directory containing spec files describing which members to wipe from the assemblies.",
CommandOptionType.SingleValue);
var verboseOption = command.Option(
"-v|--verbose",
"If set, logs additional information to the console.",
CommandOptionType.NoValue);
var listOption = command.Option(
"-l|--list",
"If set, just writes lists the assembly contents to disk.",
CommandOptionType.NoValue);
var outputOption = command.Option(
"-o|--output",
"The directory to which the wiped assembly files should be written.",
CommandOptionType.SingleValue);
command.OnExecute(() =>
{
var inputDir = GetRequiredOptionValue(inputDirOption);
var outputDir = GetRequiredOptionValue(outputOption);
var specDir = GetRequiredOptionValue(specFileOption);
var specFiles = Directory.EnumerateFiles(
specDir, "*.txt",
new EnumerationOptions { RecurseSubdirectories = true });
foreach (var specFilePath in specFiles)
{
var specFileRelativePath = Path.GetRelativePath(specDir, specFilePath);
var assemblyRelativePath = Path.ChangeExtension(specFileRelativePath, ".dll");
var inputAssemblyPath = Path.Combine(inputDir, assemblyRelativePath);
var outputAssemblyPath = Path.Combine(outputDir, assemblyRelativePath);
var inputAssemblySize = new FileInfo(inputAssemblyPath).Length;
if (listOption.HasValue())
{
var outputList = AssemblyItem
.ListContents(inputAssemblyPath)
.Select(item => item.ToString());
File.WriteAllLines(
Path.ChangeExtension(outputAssemblyPath, ".txt"),
outputList);
}
else
{
WipeAssembly.Exec(
inputAssemblyPath,
outputAssemblyPath,
specFilePath,
verboseOption.HasValue());
Console.WriteLine(
$"{assemblyRelativePath.PadRight(40)} " +
$"{FormatFileSize(inputAssemblySize)} ==> " +
$"{FormatFileSize(outputAssemblyPath)}");
}
}
return 0;
});
}
private static string FormatFileSize(string path)
{
return FormatFileSize(new FileInfo(path).Length);
}
private static string FormatFileSize(long length)
{
return string.Format("{0:0.000} MB", ((double)length) / (1024*1024));
}
private static string GetRequiredOptionValue(CommandOption option)
{
if (!option.HasValue())
{
throw new InvalidOperationException($"Missing value for required option '{option.LongName}'.");
}
return option.Value();
}
}
}

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 Microsoft.AspNetCore.Blazor.BuildTools.Cli.Commands;
@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.Blazor.BuildTools
app.HelpOption("-?|-h|--help");
app.Command("checknodejs", CheckNodeJsInstalledCommand.Command);
app.Command("ilwipe", ILWipeCommand.Command);
if (args.Length > 0)
{

View File

@ -0,0 +1,80 @@
// 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 Mono.Cecil;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil.Cil;
namespace Microsoft.AspNetCore.Blazor.BuildTools.Core.ILWipe
{
class AssemblyItem
{
public static IEnumerable<AssemblyItem> ListContents(string assemblyPath)
{
var moduleDefinition = ModuleDefinition.ReadModule(assemblyPath);
return ListContents(moduleDefinition);
}
public static IEnumerable<AssemblyItem> ListContents(ModuleDefinition moduleDefinition)
{
return moduleDefinition.Types
.SelectMany(GetNestedTypesRecursive)
.SelectMany(type => type.Methods)
.Select(method => new AssemblyItem(method))
.OrderBy(item => item.ToString(), StringComparer.Ordinal);
}
public MethodDefinition Method { get; }
public AssemblyItem(MethodDefinition method)
{
Method = method ?? throw new ArgumentNullException(nameof(method));
}
public void WipeFromAssembly(MethodDefinition createMethodWipedException)
{
if (!Method.HasBody)
{
return; // Nothing to do
}
// We don't want to actually remove the method definition from the assembly, because
// then you'd have an assembly that was invalid (it could contain calls to the method
// that no longer exists). Instead, remove all the instructions from its body, and
// replace it with "throw CreateMethodWipedException()". Then:
// [1] The method body is very short, while still definitely being valid (still OK for
// it to have any return type)
// [2] We've removed its references to other methods/types, so they are more likely
// to be actually removed fully by a subsequent IL linker pass
// [3] If the method is actually invoked at runtime, the stack trace will make clear
// which method is being excessively wiped
var il = Method.Body.GetILProcessor();
il.Body.Instructions.Clear();
il.Body.Variables.Clear();
il.Body.ExceptionHandlers.Clear();
il.Append(il.Create(OpCodes.Call, createMethodWipedException));
il.Append(il.Create(OpCodes.Throw));
}
public override string ToString()
{
var result = Method.ToString();
return result.Substring(result.IndexOf(' ') + 1);
}
public int CodeSize
=> Method.Body?.CodeSize ?? 0;
private static IEnumerable<TypeDefinition> GetNestedTypesRecursive(TypeDefinition type)
{
yield return type;
foreach (var descendant in type.NestedTypes.SelectMany(GetNestedTypesRecursive))
{
yield return descendant;
}
}
}
}

View File

@ -0,0 +1,74 @@
// 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 Mono.Cecil;
using Mono.Cecil.Cil;
using System;
namespace Microsoft.AspNetCore.Blazor.BuildTools.Core.ILWipe
{
static class MethodWipedExceptionMethod
{
public static MethodDefinition AddToAssembly(ModuleDefinition moduleDefinition)
{
// Adds the following method to the assembly:
// namespace ILWipe
// {
// internal static class ILWipeHelpers
// {
// public static Exception CreateMethodWipedException()
// {
// return new NotImplementedException("Cannot call method because it was wiped. See stack trace for details.");
// }
// }
// }
var ilWipeHelpersType = new TypeDefinition("ILWipe", "ILWipeHelpers",
TypeAttributes.NotPublic | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
moduleDefinition.Types.Add(ilWipeHelpersType);
var methodAttributes =
MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.Static;
var createMethodWipedExceptionMethod = new MethodDefinition(
"CreateMethodWipedException",
methodAttributes,
ImportEquivalentTypeFromMscorlib(moduleDefinition, typeof(Exception)));
ilWipeHelpersType.Methods.Add(createMethodWipedExceptionMethod);
var notImplExceptionType = ImportEquivalentTypeFromMscorlib(moduleDefinition, typeof(NotImplementedException));
var notImplExceptionCtor = new MethodReference(".ctor", moduleDefinition.TypeSystem.Void, notImplExceptionType);
notImplExceptionCtor.Parameters.Add(new ParameterDefinition(moduleDefinition.TypeSystem.String));
var il = createMethodWipedExceptionMethod.Body.GetILProcessor();
il.Append(il.Create(OpCodes.Ldstr, "Cannot invoke method because it was wiped. See stack trace for details."));
il.Append(il.Create(OpCodes.Newobj, notImplExceptionCtor));
il.Append(il.Create(OpCodes.Ret));
return createMethodWipedExceptionMethod;
}
static TypeReference ImportEquivalentTypeFromMscorlib(ModuleDefinition module, Type type)
{
// We have to do this instead of module.ImportReference(type), because the latter
// would try to reference it in System.Private.CoreLib because this tool itself
// compiles to target netcoreapp rather than netstandard
IMetadataScope mscorlibScope;
if (module.TryGetTypeReference(typeof(object).FullName, out var objectRef))
{
mscorlibScope = objectRef.Scope;
}
else if (module.Name == "mscorlib.dll")
{
mscorlibScope = module;
}
else
{
throw new InvalidOperationException($"Could not resolve System.Object type within '{module.FileName}'.");
}
var typeRef = new TypeReference(type.Namespace, type.Name, module, mscorlibScope, type.IsValueType);
return module.ImportReference(typeRef);
}
}
}

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.
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Blazor.BuildTools.Core.ILWipe
{
class SpecList
{
private List<SpecListEntry> _itemSpecs;
public SpecList(string[] fromSpecLines)
{
var linesToUse = fromSpecLines.Where(
line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith('#'));
_itemSpecs = new List<SpecListEntry>(
linesToUse.Select(line => new SpecListEntry(line)));
}
public bool IsEmpty
{
get => _itemSpecs.Count == 0;
}
public bool Match(AssemblyItem item)
{
// If this needs to be faster, consider implementing some kind of matching tree.
var lastMatchingSpec = _itemSpecs.LastOrDefault(spec => spec.IsMatch(item));
return lastMatchingSpec == null ? false : !lastMatchingSpec.Negated;
}
}
}

View File

@ -0,0 +1,121 @@
// 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;
namespace Microsoft.AspNetCore.Blazor.BuildTools.Core.ILWipe
{
class SpecListEntry
{
public bool Negated { get; }
public string TypeName { get; }
public string MethodName { get; }
public string Args { get; }
public SpecListEntry(string parseSpecLine)
{
parseSpecLine = parseSpecLine.Trim();
if (parseSpecLine.StartsWith('!'))
{
Negated = true;
parseSpecLine = parseSpecLine.Substring(1);
}
var colonsPos = parseSpecLine.IndexOf("::");
if (colonsPos < 0)
{
TypeName = parseSpecLine;
}
else
{
TypeName = parseSpecLine.Substring(0, colonsPos);
parseSpecLine = parseSpecLine.Substring(colonsPos + 2);
var bracketPos = parseSpecLine.IndexOf('(');
if (bracketPos < 0)
{
MethodName = parseSpecLine;
}
else
{
MethodName = parseSpecLine.Substring(0, bracketPos);
Args = parseSpecLine.Substring(bracketPos + 1, parseSpecLine.Length - bracketPos - 2);
}
}
}
public bool IsMatch(AssemblyItem item)
{
return MatchesType(item)
&& MatchesMethod(item)
&& MatchesArgs(item);
}
private bool MatchesArgs(AssemblyItem item)
{
if (Args == null)
{
return true;
}
else
{
var methodString = item.Method.ToString();
var bracketPos = methodString.IndexOf('(');
var argsString = methodString.Substring(bracketPos + 1, methodString.Length - bracketPos - 2);
return string.Equals(argsString, Args, StringComparison.Ordinal);
}
}
private bool MatchesMethod(AssemblyItem item)
{
if (MethodName == null)
{
return true;
}
else if (MethodName.EndsWith('*'))
{
return item.Method.Name.StartsWith(
MethodName.Substring(0, MethodName.Length - 1),
StringComparison.Ordinal);
}
else
{
return string.Equals(item.Method.Name, MethodName, StringComparison.Ordinal);
}
}
private bool MatchesType(AssemblyItem item)
{
var declaringTypeFullName = item.Method.DeclaringType.FullName;
if (TypeName.EndsWith('*'))
{
// Wildcard match
return declaringTypeFullName.StartsWith(
TypeName.Substring(0, TypeName.Length - 1),
StringComparison.Ordinal);
}
else
{
// Exact match
if (string.Equals(
item.Method.DeclaringType.FullName,
TypeName,
StringComparison.Ordinal))
{
return true;
}
// If we're matching all members of the type, include nested types
if (MethodName == null && declaringTypeFullName.StartsWith(
$"{TypeName}/",
StringComparison.Ordinal))
{
return true;
}
return false;
}
}
}
}

View File

@ -0,0 +1,49 @@
// 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 Mono.Cecil;
using System.Linq;
namespace Microsoft.AspNetCore.Blazor.BuildTools.Core.ILWipe
{
static class WipeAssembly
{
public static void Exec(string inputPath, string outputPath, string specFilePath, bool logVerbose)
{
if (string.IsNullOrEmpty(outputPath))
{
outputPath = Path.ChangeExtension(inputPath, ".wiped" + Path.GetExtension(inputPath));
}
var specLines = File.ReadAllLines(specFilePath);
var wipeSpecList = new SpecList(specLines);
var moduleDefinition = ModuleDefinition.ReadModule(inputPath);
if (!wipeSpecList.IsEmpty)
{
var createMethodWipedException = MethodWipedExceptionMethod.AddToAssembly(moduleDefinition);
var contents = AssemblyItem.ListContents(moduleDefinition).ToList();
foreach (var contentItem in contents)
{
var shouldWipe = wipeSpecList.Match(contentItem)
&& contentItem.Method != createMethodWipedException;
if (logVerbose)
{
Console.WriteLine($"{(shouldWipe ? "Wiping" : "Retaining")}: {contentItem}");
}
if (shouldWipe)
{
contentItem.WipeFromAssembly(createMethodWipedException);
}
}
}
moduleDefinition.Write(outputPath);
}
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
@ -6,12 +6,9 @@
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<None Remove="tools\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
<PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" />
</ItemGroup>
</Project>

View File

@ -1,11 +0,0 @@
<Project>
<PropertyGroup>
<BlazorBuildToolsExe>dotnet &quot;$(ArtifactsBinDir)Microsoft.AspNetCore.Blazor.BuildTools/netcoreapp2.1/Microsoft.AspNetCore.Blazor.BuildTools.dll&quot;</BlazorBuildToolsExe>
</PropertyGroup>
<ItemGroup>
<!-- Ensures BuildTools itself is built before the consuming project, but without
adding a runtime dependency on the .dll -->
<ProjectReference Include="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Blazor.BuildTools.csproj" ReferenceOutputAssembly="false" PrivateAssets="all" />
</ItemGroup>
</Project>