From 012746c2e734b137783687fc5bceba95d96c52a9 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 14 Apr 2017 09:43:09 -0700 Subject: [PATCH 1/5] Detect package references containing dll's that were not used during compilation --- .../GetUnusedAssemblies.cs | 80 +++++++++++++++++++ ...nternal.AspNetCore.BuildTools.Tasks.csproj | 2 +- .../build/Tasks.tasks | 3 +- .../Internal.AspNetCore.Sdk.Tasks.csproj | 1 + .../build/FindUnusedReferences.targets | 15 ++++ .../build/Internal.AspNetCore.Sdk.targets | 1 + 6 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs create mode 100644 src/Internal.AspNetCore.Sdk/build/FindUnusedReferences.targets diff --git a/src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs b/src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs new file mode 100644 index 000000000..d58f7c59a --- /dev/null +++ b/src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Microsoft.AspNetCore.BuildTools +{ +#if SDK + public class Sdk_FindUnusedReferences : Task +#elif BuildTools + public class FindUnusedReferences : Task +#else +#error This must be built either for an SDK or for BuildTools +#endif + { + /// + /// IntermediateAssembly from CoreCompile + /// + [Required] + public string Assembly { get; set; } + + /// + /// ReferencePath from CoreCompile + /// + [Required] + public ITaskItem[] References { get; set; } + + /// + /// FileDefinitions from RunResolvePackageDependencies + /// + [Required] + public ITaskItem[] Packages { get; set; } + + /// + /// PackageDependencies from RunResolvePackageDependencies + /// + [Required] + public ITaskItem[] Files { get; set; } + + [Output] + public ITaskItem[] UnusedReferences { get; set; } + + public override bool Execute() + { + var references = new HashSet(References.Select(item => item.ItemSpec), StringComparer.OrdinalIgnoreCase); + var referenceFiles = Files.Where(file => references.Contains(file.GetMetadata("ResolvedPath"))) + .ToDictionary(item => Path.GetFileNameWithoutExtension(item.GetMetadata("ResolvedPath")), StringComparer.OrdinalIgnoreCase); + + var directReferences = new HashSet( + Packages.Where(p => string.IsNullOrEmpty(p.GetMetadata("ParentPackage"))).Select(i => i.ItemSpec), + StringComparer.OrdinalIgnoreCase); + + using (var fileStream = File.OpenRead(Assembly)) + using (PEReader reader = new PEReader(fileStream)) + { + var metadataReader = reader.GetMetadataReader(); + foreach (AssemblyReferenceHandle assemblyReferenceHandle in metadataReader.AssemblyReferences) + { + var assemblyReference = metadataReader.GetAssemblyReference(assemblyReferenceHandle); + var name = metadataReader.GetString(assemblyReference.Name); + if (referenceFiles.TryGetValue(name, out var fileItem)) + { + var packageName = fileItem.GetMetadata("PackageName") + "/" + fileItem.GetMetadata("PackageVersion"); + directReferences.Remove(packageName); + referenceFiles.Remove(name); + } + + } + } + + UnusedReferences = referenceFiles.Values.Where(f => directReferences.Any(r => f.ItemSpec.StartsWith(r))).ToArray(); + return true; + } + } +} diff --git a/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj b/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj index b6e6545ec..8ceb4c848 100644 --- a/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj +++ b/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj @@ -34,11 +34,11 @@ + - diff --git a/src/Internal.AspNetCore.BuildTools.Tasks/build/Tasks.tasks b/src/Internal.AspNetCore.BuildTools.Tasks/build/Tasks.tasks index 1a3476b87..b92f4df66 100644 --- a/src/Internal.AspNetCore.BuildTools.Tasks/build/Tasks.tasks +++ b/src/Internal.AspNetCore.BuildTools.Tasks/build/Tasks.tasks @@ -1,4 +1,4 @@ - + <_BuildToolsAssemblyTfm Condition="'$(MSBuildRuntimeType)' == 'Core'">netstandard1.6 @@ -17,6 +17,7 @@ + diff --git a/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj b/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj index 43c404363..315f842f4 100644 --- a/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj +++ b/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj @@ -44,6 +44,7 @@ + diff --git a/src/Internal.AspNetCore.Sdk/build/FindUnusedReferences.targets b/src/Internal.AspNetCore.Sdk/build/FindUnusedReferences.targets new file mode 100644 index 000000000..84b95d24a --- /dev/null +++ b/src/Internal.AspNetCore.Sdk/build/FindUnusedReferences.targets @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/src/Internal.AspNetCore.Sdk/build/Internal.AspNetCore.Sdk.targets b/src/Internal.AspNetCore.Sdk/build/Internal.AspNetCore.Sdk.targets index 30944f3ae..59809fc60 100644 --- a/src/Internal.AspNetCore.Sdk/build/Internal.AspNetCore.Sdk.targets +++ b/src/Internal.AspNetCore.Sdk/build/Internal.AspNetCore.Sdk.targets @@ -5,6 +5,7 @@ for use outside of Microsoft. + From d2a8f8cdc6edf629b879d811667a8cdb0f2d9622 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 14 Apr 2017 09:44:30 -0700 Subject: [PATCH 2/5] Nits --- .../{GetUnusedAssemblies.cs => FindUnusedReferences.cs} | 6 ++++-- src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) rename src/Internal.AspNetCore.BuildTools.Tasks/{GetUnusedAssemblies.cs => FindUnusedReferences.cs} (94%) diff --git a/src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs b/src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs similarity index 94% rename from src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs rename to src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs index d58f7c59a..6011a473b 100644 --- a/src/Internal.AspNetCore.BuildTools.Tasks/GetUnusedAssemblies.cs +++ b/src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs @@ -1,10 +1,12 @@ -using System; +// 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.Metadata; using System.Reflection.PortableExecutable; -using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; diff --git a/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj b/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj index d18d184d9..7288b27f6 100644 --- a/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj +++ b/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj @@ -30,4 +30,10 @@ + + + %(Identity) + + + From 4f7c9cd576009a17352b836e8457f45cbb1f8aef Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 14 Apr 2017 09:53:10 -0700 Subject: [PATCH 3/5] Revert src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj --- src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj b/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj index 7288b27f6..d18d184d9 100644 --- a/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj +++ b/src/Internal.AspNetCore.Sdk/Internal.AspNetCore.Sdk.csproj @@ -30,10 +30,4 @@ - - - %(Identity) - - - From 99a88e083d2bea24b22d1e3fc88f39bbab5c5e26 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 14 Apr 2017 11:13:44 -0700 Subject: [PATCH 4/5] Fix net46 build --- .../Internal.AspNetCore.BuildTools.Tasks.csproj | 17 ++++++++++++++++- .../Internal.AspNetCore.Sdk.Tasks.csproj | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj b/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj index 8ceb4c848..d4404dd61 100644 --- a/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj +++ b/src/Internal.AspNetCore.BuildTools.Tasks/Internal.AspNetCore.BuildTools.Tasks.csproj @@ -34,11 +34,26 @@ - + + + + + + + <_PackageFiles Include="bin\$(Configuration)\*\System.Reflection.Metadata.dll;bin\$(Configuration)\*\System.Collections.Immutable.dll"> + tools\%(RecursiveDir) + false + Content + + + diff --git a/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj b/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj index 315f842f4..6ceaf38af 100644 --- a/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj +++ b/src/Internal.AspNetCore.Sdk.Tasks/Internal.AspNetCore.Sdk.Tasks.csproj @@ -44,7 +44,9 @@ - + + + @@ -52,4 +54,17 @@ + + + + <_PackageFiles Include="bin\$(Configuration)\*\System.Reflection.Metadata.dll;bin\$(Configuration)\*\System.Collections.Immutable.dll"> + tools\%(RecursiveDir) + false + Content + + + From 41c23092de6de0cede1c4fbb90c98ecefd11c66b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 14 Apr 2017 12:47:27 -0700 Subject: [PATCH 5/5] More PP's --- .../FindUnusedReferences.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs b/src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs index 6011a473b..e027cedc4 100644 --- a/src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs +++ b/src/Internal.AspNetCore.BuildTools.Tasks/FindUnusedReferences.cs @@ -58,7 +58,7 @@ public override bool Execute() StringComparer.OrdinalIgnoreCase); using (var fileStream = File.OpenRead(Assembly)) - using (PEReader reader = new PEReader(fileStream)) + using (var reader = new PEReader(fileStream)) { var metadataReader = reader.GetMetadataReader(); foreach (AssemblyReferenceHandle assemblyReferenceHandle in metadataReader.AssemblyReferences)