From 964e9e5fb740e297bd119fed58ba865c1131976f Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Fri, 22 Oct 2021 17:08:43 -0700 Subject: [PATCH 1/2] Improve loading of Roslyn assemblies on validate package task (#22277) * Improve loading of Roslyn assemblies on validate package task * PR Feedback --- .../ValidatePackage.cs | 45 ++++++++++++++++--- ...Microsoft.NET.Compatibility.Common.targets | 5 ++- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/Compatibility/Microsoft.DotNet.Compatibility/ValidatePackage.cs b/src/Compatibility/Microsoft.DotNet.Compatibility/ValidatePackage.cs index e373ab00454a..08dd61ff53d9 100644 --- a/src/Compatibility/Microsoft.DotNet.Compatibility/ValidatePackage.cs +++ b/src/Compatibility/Microsoft.DotNet.Compatibility/ValidatePackage.cs @@ -3,13 +3,15 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Reflection; using Microsoft.Build.Framework; using Microsoft.DotNet.PackageValidation; using Microsoft.NET.Build.Tasks; using NuGet.RuntimeModel; +#if NETCOREAPP +using System.Runtime.Loader; +#endif namespace Microsoft.DotNet.Compatibility { @@ -43,14 +45,23 @@ public class ValidatePackage : TaskBase public override bool Execute() { +#if NETCOREAPP + AssemblyLoadContext currentContext = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()); + currentContext.Resolving += ResolverForRoslyn; +#else AppDomain.CurrentDomain.AssemblyResolve += ResolverForRoslyn; +#endif try { return base.Execute(); } finally { +#if NETCOREAPP + currentContext.Resolving -= ResolverForRoslyn; +#else AppDomain.CurrentDomain.AssemblyResolve -= ResolverForRoslyn; +#endif } } @@ -103,19 +114,41 @@ protected override void ExecuteCore() } } +#if NETCOREAPP + private Assembly ResolverForRoslyn(AssemblyLoadContext context, AssemblyName assemblyName) + { + return LoadRoslyn(assemblyName, path => context.LoadFromAssemblyPath(path)); + } +#else private Assembly ResolverForRoslyn(object sender, ResolveEventArgs args) { AssemblyName name = new(args.Name); - if (name.Name == "Microsoft.CodeAnalysis" || name.Name == "Microsoft.CodeAnalysis.CSharp") + return LoadRoslyn(name, path => Assembly.LoadFrom(path)); + } +#endif + + private Assembly LoadRoslyn(AssemblyName name, Func loadFromPath) + { + const string codeAnalysisName = "Microsoft.CodeAnalysis"; + const string codeAnalysisCsharpName = "Microsoft.CodeAnalysis.CSharp"; + if (name.Name == codeAnalysisName || name.Name == codeAnalysisCsharpName) { - Assembly asm = Assembly.LoadFrom(Path.Combine(RoslynAssembliesPath, $"{name.Name}.dll")); - Version version = asm.GetName().Version; - if (version < name.Version) + Assembly asm = loadFromPath(Path.Combine(RoslynAssembliesPath, $"{name.Name}.dll")); + Version resolvedVersion = asm.GetName().Version; + if (resolvedVersion < name.Version) { - throw new Exception(string.Format(Resources.UpdateSdkVersion, version, name.Version)); + throw new Exception(string.Format(Resources.UpdateSdkVersion, resolvedVersion, name.Version)); } + + // Being extra defensive but we want to avoid that we accidentally load two different versions of either + // of the roslyn assemblies from a different location, so let's load them both on the first request. + Assembly _ = name.Name == codeAnalysisName ? + loadFromPath(Path.Combine(RoslynAssembliesPath, $"{codeAnalysisCsharpName}.dll")) : + loadFromPath(Path.Combine(RoslynAssembliesPath, $"{codeAnalysisName}.dll")); + return asm; } + return null; } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Compatibility.Common.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Compatibility.Common.targets index dbf92087766c..0682e75574e5 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Compatibility.Common.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Compatibility.Common.targets @@ -15,8 +15,9 @@ $(RoslynTargetsPath) <_packageReferenceList>@(PackageReference) - $([System.IO.Path]::GetDirectoryName($(CSharpCoreTargetsPath))) - $([System.IO.Path]::GetDirectoryName($(VisualBasicCoreTargetsPath))) + + $([System.IO.Path]::GetDirectoryName($(CSharpCoreTargetsPath))) $([System.IO.Path]::Combine('$(RoslynAssembliesPath)', bincore)) From 622e2c574003fb261a643fb5d01fdf01370e8ab8 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Fri, 11 Mar 2022 14:32:37 -0800 Subject: [PATCH 2/2] Bump the minor package version of Microsoft.DotNet.Compatiblity --- .../Microsoft.DotNet.Compatibility.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compatibility/Microsoft.DotNet.Compatibility/Microsoft.DotNet.Compatibility.csproj b/src/Compatibility/Microsoft.DotNet.Compatibility/Microsoft.DotNet.Compatibility.csproj index 92624be84535..d5720d272bf3 100644 --- a/src/Compatibility/Microsoft.DotNet.Compatibility/Microsoft.DotNet.Compatibility.csproj +++ b/src/Compatibility/Microsoft.DotNet.Compatibility/Microsoft.DotNet.Compatibility.csproj @@ -6,7 +6,7 @@ true true Open - 1.0.0 + 1.1.0 false $(NoWarn);NU5128