diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 954afabfe053..f14f85b39186 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -125,10 +125,6 @@ https://github.com/dotnet/runtime bf7fb2ecbf69deb6a73bb8bbca1e56e7beec8d8a - - https://github.com/dotnet/linker - c790896f128957acd2999208f44f09ae1e826c8c - https://github.com/dotnet/runtime bf7fb2ecbf69deb6a73bb8bbca1e56e7beec8d8a diff --git a/src/Layout/redist/redist.csproj b/src/Layout/redist/redist.csproj index ada9291ad247..3042bb92be44 100644 --- a/src/Layout/redist/redist.csproj +++ b/src/Layout/redist/redist.csproj @@ -35,7 +35,6 @@ - diff --git a/src/Layout/redist/targets/GenerateLayout.targets b/src/Layout/redist/targets/GenerateLayout.targets index 92446fb9f2a5..208029371ca0 100644 --- a/src/Layout/redist/targets/GenerateLayout.targets +++ b/src/Layout/redist/targets/GenerateLayout.targets @@ -57,9 +57,6 @@ - - - @@ -78,8 +75,6 @@ - - diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index b8b3d129e583..f6d34e3b351b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -44,7 +44,7 @@ public class ProcessFrameworkReferences : TaskBase public bool ReadyToRunUseCrossgen2 { get; set; } - public bool TrimmingEnabled { get; set; } + public bool RequiresILLinkPack { get; set; } public bool AotEnabled { get; set; } @@ -384,7 +384,7 @@ var runtimeRequiredByDeployment } } - if (TrimmingEnabled) + if (RequiresILLinkPack) { if (!AddToolPack(ToolPackType.ILLink, _normalizedTargetFrameworkVersion, packagesToDownload, implicitPackageReferences)) { @@ -712,6 +712,15 @@ private bool AddToolPack( implicitPackageReferences.Add(buildPackage); } + // Before net8.0, ILLink analyzers shipped in a separate package. + // Add the analyzer package with version taken from KnownILLinkPack. + if (normalizedTargetFrameworkVersion < new Version(8, 0) && toolPackType is ToolPackType.ILLink) + { + var analyzerPackage = new TaskItem("Microsoft.NET.ILLink.Analyzers"); + analyzerPackage.SetMetadata(MetadataKeys.Version, packVersion); + implicitPackageReferences.Add(analyzerPackage); + } + return true; } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets index e528742a5873..8bba61aab697 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets @@ -22,8 +22,14 @@ Copyright (c) .NET Foundation. All rights reserved. true true - <_IsTrimmingEnabled Condition="'$(_IsTrimmingEnabled)' == '' And ('$(PublishTrimmed)' == 'true' Or '$(IsTrimmable)' == 'true')">true - <_IsTrimmingEnabled Condition="'$(_IsTrimmingEnabled)' == ''">false + <_RequiresILLinkPack Condition="'$(_RequiresILLinkPack)' == '' And ( + '$(PublishTrimmed)' == 'true' Or + '$(PublishSingleFile)' == 'true' Or + '$(IsTrimmable)' == 'true' Or + '$(EnableAotAnalyzer)' == 'true' Or + '$(EnableTrimAnalyzer)' == 'true' Or + '$(EnableSingleFileAnalyzer)' == 'true')">true + <_RequiresILLinkPack Condition="'$(_RequiresILLinkPack)' == ''">false false diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.Analyzers.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.Analyzers.targets index 366690015088..c673899606d6 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.Analyzers.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.Analyzers.targets @@ -101,8 +101,6 @@ Copyright (c) .NET Foundation. All rights reserved. Condition="'$(Language)' == 'C#' Or '$(Language)' == 'VB'" /> - @@ -124,13 +122,6 @@ Copyright (c) .NET Foundation. All rights reserved. IsImplicitlyDefined="true" /> - - - - - diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets index 8c26d26d161a..d4a5897a1744 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets @@ -99,7 +99,7 @@ Copyright (c) .NET Foundation. All rights reserved. SelfContained="$(SelfContained)" ReadyToRunEnabled="$(PublishReadyToRun)" ReadyToRunUseCrossgen2="$(PublishReadyToRunUseCrossgen2)" - TrimmingEnabled="$(_IsTrimmingEnabled)" + RequiresILLinkPack="$(_RequiresILLinkPack)" AotEnabled="$(PublishAot)" AotUseKnownRuntimePackForTarget="$(PublishAotUsingRuntimePack)" RuntimeIdentifier="$(RuntimeIdentifier)" diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs index 7fa4163aeabb..5e99619fdf5d 100644 --- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToRunILLink.cs @@ -11,6 +11,7 @@ using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; using System.Text; +using System.Text.RegularExpressions; using FluentAssertions; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.DependencyModel; @@ -486,14 +487,27 @@ public void ILLink_analysis_warnings_are_enabled_by_default(string targetFramewo var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: targetFramework); var publishCommand = new PublishCommand(testAsset); - publishCommand.Execute($"/p:RuntimeIdentifier={rid}") - .Should().Pass() - // trim analysis warnings are enabled - .And.HaveStdOutMatching("warning IL2075.*Program.IL_2075") - .And.HaveStdOutMatching("warning IL2026.*Program.IL_2026.*Testing analysis warning IL2026") - .And.HaveStdOutMatching("warning IL2043.*Program.IL_2043.get") - .And.HaveStdOutMatching("warning IL2046.*Program.Derived.IL_2046") - .And.HaveStdOutMatching("warning IL2093.*Program.Derived.IL_2093"); + // Minimal verbosity prevents desktop MSBuild.exe from duplicating the warnings in the warning summary + var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/v:m"); + result.Should().Pass(); + // trim analysis warnings are enabled + var expectedWarnings = new List { + // ILLink warnings + "Trim analysis warning IL2075.*Program.IL_2075", + "Trim analysis warning IL2026.*Program.IL_2026.*Testing analysis warning IL2026", + "Trim analysis warning IL2043.*Program.IL_2043.get", + "Trim analysis warning IL2026.*Program.Base.IL_2046", + "Trim analysis warning IL2046.*Program.Derived.IL_2046", + "Trim analysis warning IL2093.*Program.Derived.IL_2093", + // analyzer warnings + "warning IL2075.*Type.GetMethod", + "warning IL2026.*Program.IL_2026.*Testing analysis warning IL2026", + "warning IL2043.*Program.IL_2043.get", + "warning IL2026.*Program.Base.IL_2046", + "warning IL2046.*Program.Derived.IL_2046", + "warning IL2093.*Program.Derived.IL_2093" + }; + ValidateWarningsOnHelloWorldApp(publishCommand, result, expectedWarnings, targetFramework, rid, useRegex: true); } [RequiresMSBuildVersionTheory("17.0.0.32901")] @@ -553,9 +567,19 @@ public void ILLink_accepts_option_to_enable_analysis_warnings_without_PublishTri var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: targetFramework); var publishCommand = new PublishCommand(testAsset); - publishCommand.Execute($"/p:RuntimeIdentifier={rid}") - .Should().Pass() - .And.HaveStdOutMatching("warning IL2026.*Program.IL_2026.*Testing analysis warning IL2026"); + // Minimal verbosity prevents desktop MSBuild.exe from duplicating the warnings in the warning summary + var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/v:m"); + result.Should().Pass(); + var expectedWarnings = new List { + // analyzer warnings + "warning IL2075.*Type.GetMethod", + "warning IL2026.*Program.IL_2026.*Testing analysis warning IL2026", + "warning IL2043.*Program.IL_2043.get", + "warning IL2026.*Program.Base.IL_2046", + "warning IL2046.*Program.Derived.IL_2046", + "warning IL2093.*Program.Derived.IL_2093" + }; + ValidateWarningsOnHelloWorldApp(publishCommand, result, expectedWarnings, targetFramework, rid, useRegex: true); } [RequiresMSBuildVersionTheory("17.0.0.32901")] @@ -674,7 +698,7 @@ public void ILLink_verify_analysis_warnings_hello_world_app_trim_mode_copyused(s var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); // Please keep list below sorted and de-duplicated - var expectedOutput = new List { + var expectedWarnings = new List { "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.ComActivator.GetClassFactoryForTypeInternal(ComActivationContextInternal*", "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.ComponentActivator.GetFunctionPointer(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr", "ILLink : Trim analysis warning IL2026: System.ComponentModel.Design.DesigntimeLicenseContextSerializer.DeserializeUsingBinaryFormatter(DesigntimeLicenseContextSerializer.StreamWrapper, String, RuntimeLicenseContext", @@ -686,13 +710,13 @@ public void ILLink_verify_analysis_warnings_hello_world_app_trim_mode_copyused(s switch (targetFramework) { case "net6.0": - expectedOutput.AddRange(new string[] { + expectedWarnings.AddRange(new string[] { "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.InMemoryAssemblyLoader.LoadInMemoryAssembly(IntPtr, IntPtr", }); break; case "net7.0": case "net8.0": - expectedOutput.AddRange(new string[] { + expectedWarnings.AddRange(new string[] { "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.InMemoryAssemblyLoader.LoadInMemoryAssembly(IntPtr, IntPtr", "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.InMemoryAssemblyLoader.LoadInMemoryAssemblyInContextWhenSupported(IntPtr, IntPtr", }); @@ -705,9 +729,11 @@ public void ILLink_verify_analysis_warnings_hello_world_app_trim_mode_copyused(s var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: targetFramework); var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); - var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:PublishTrimmed=true", "/p:TrimMode=copyused", "/p:TrimmerSingleWarn=false"); + var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:PublishTrimmed=true", "/p:TrimMode=copyused", "/p:TrimmerSingleWarn=false", "/p:EnableTrimAnalyzer=false", + // Minimal verbosity prevents desktop MSBuild.exe from duplicating the warnings in the warning summary + "/v:m"); result.Should().Pass(); - ValidateWarningsOnHelloWorldApp(publishCommand, result, expectedOutput.ToArray(), targetFramework, rid); + ValidateWarningsOnHelloWorldApp(publishCommand, result, expectedWarnings, targetFramework, rid); } [RequiresMSBuildVersionTheory("17.0.0.32901")] @@ -718,7 +744,7 @@ public void ILLink_verify_analysis_warnings_framework_assemblies(string targetFr var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); // Please keep list below sorted and de-duplicated - var expectedOutput = new List { + var expectedWarnings = new List { "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.ComponentActivator.GetFunctionPointer(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr", "ILLink : Trim analysis warning IL2026: System.ComponentModel.Design.DesigntimeLicenseContextSerializer.DeserializeUsingBinaryFormatter(DesigntimeLicenseContextSerializer.StreamWrapper, String, RuntimeLicenseContext", "ILLink : Trim analysis warning IL2026: System.ComponentModel.Design.DesigntimeLicenseContextSerializer.SerializeWithBinaryFormatter(Stream, String, DesigntimeLicenseContext", @@ -734,7 +760,7 @@ public void ILLink_verify_analysis_warnings_framework_assemblies(string targetFr switch (targetFramework) { case "net6.0": - expectedOutput.AddRange(new string[] { + expectedWarnings.AddRange(new string[] { "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.InMemoryAssemblyLoader.LoadInMemoryAssembly(IntPtr, IntPtr", "ILLink : Trim analysis warning IL2055: System.Runtime.Serialization.ClassDataContract.UnadaptedClassType.get", "ILLink : Trim analysis warning IL2067: System.Runtime.Serialization.SurrogateDataContract.GetUninitializedObject(Type" @@ -742,7 +768,7 @@ public void ILLink_verify_analysis_warnings_framework_assemblies(string targetFr break; case "net7.0": case "net8.0": - expectedOutput.AddRange(new string[] { + expectedWarnings.AddRange(new string[] { "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.ComActivator.GetClassFactoryForTypeInternal(ComActivationContextInternal*", "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.InMemoryAssemblyLoader.LoadInMemoryAssembly(IntPtr, IntPtr", "ILLink : Trim analysis warning IL2026: Internal.Runtime.InteropServices.InMemoryAssemblyLoader.LoadInMemoryAssemblyInContextWhenSupported(IntPtr, IntPtr", @@ -765,9 +791,11 @@ public void ILLink_verify_analysis_warnings_framework_assemblies(string targetFr var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:PublishTrimmed=true", - "/p:TrimMode=copy", "/p:_TrimmerDefaultAction=copy", "/p:TrimmerSingleWarn=false"); + "/p:TrimMode=copy", "/p:_TrimmerDefaultAction=copy", "/p:TrimmerSingleWarn=false", "/p:EnableTrimAnalyzer=false", + // Minimal verbosity prevents desktop MSBuild.exe from duplicating the warnings in the warning summary + "/v:m"); result.Should().Pass(); - ValidateWarningsOnHelloWorldApp(publishCommand, result, expectedOutput.ToArray(), targetFramework, rid); + ValidateWarningsOnHelloWorldApp(publishCommand, result, expectedWarnings, targetFramework, rid); } [RequiresMSBuildVersionTheory("17.0.0.32901")] @@ -783,7 +811,7 @@ public void ILLink_verify_analysis_warnings_hello_world_app_trim_mode_link(strin var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:PublishTrimmed=true", "/p:TrimmerSingleWarn=false"); result.Should().Pass(); - ValidateWarningsOnHelloWorldApp(publishCommand, result, Array.Empty(), targetFramework, rid); + ValidateWarningsOnHelloWorldApp(publishCommand, result, new List(), targetFramework, rid); } [RequiresMSBuildVersionFact("17.0.0.32901")] @@ -800,14 +828,34 @@ public void ILLink_verify_analysis_warnings_hello_world_app_trim_mode_link_5_0() var result = publishCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:PublishTrimmed=true", "/p:TrimmerSingleWarn=false", "/p:TrimMode=link"); result.Should().Pass(); - ValidateWarningsOnHelloWorldApp(publishCommand, result, Array.Empty(), targetFramework, rid); + ValidateWarningsOnHelloWorldApp(publishCommand, result, new List(), targetFramework, rid); } - private void ValidateWarningsOnHelloWorldApp(PublishCommand publishCommand, CommandResult result, string[] expectedOutput, string targetFramework, string rid) + private void ValidateWarningsOnHelloWorldApp(PublishCommand publishCommand, CommandResult result, List expectedWarnings, string targetFramework, string rid, bool useRegex = false) { // This checks that there are no unexpected warnings, but does not cause failures for missing expected warnings. var warnings = result.StdOut.Split('\n', '\r').Where(line => line.Contains("warning IL")); - var extraWarnings = warnings.Where(warning => !expectedOutput.Any(expected => warning.Contains(expected))); + + // This should also detect unexpected duplicates of expected warnings. + // Each expected warning string/regex matches at most one warning. + List extraWarnings = new(); + foreach (var warning in warnings) { + bool expected = false; + for (int i = 0; i < expectedWarnings.Count; i++) + { + if ((useRegex && Regex.IsMatch(warning, expectedWarnings[i])) || + (!useRegex && warning.Contains(expectedWarnings[i]))) + { + expectedWarnings.RemoveAt(i); + expected = true; + break; + } + } + + if (!expected) { + extraWarnings.Add(warning); + } + } StringBuilder errorMessage = new StringBuilder();