From 6257b8ee53833e060efd7b7c4cdbda5789ab17b5 Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Wed, 13 Dec 2023 17:44:09 +0100 Subject: [PATCH] Load Microsoft.DotNet.MSBuildSdkResolver into default load context (MSBuild.exe only) (#9439) Fixes #9303 ### Context After a new version of `VS.Redist.Common.Net.Core.SDK.MSBuildExtensions` is inserted into VS, a native image for `Microsoft.DotNet.MSBuildSdkResolver` will be generated, both for devenv.exe and MSBuild.exe (see https://github.com/dotnet/installer/pull/17732). We currently load SDK resolvers using `Assembly.LoadFrom` on .NET Framework, which disqualifies it from using native images even if they existed. This PR makes us use the native image. ### Changes Made Added a code path to use `Assembly.Load` to load resolver assemblies. The call is made such that if the assembly cannot be found by simple name, it falls back to loading by path into the load-from context, just like today. The new code path is enabled only for `Microsoft.DotNet.MSBuildSdkResolver` under a change-wave check. ### Testing Experimental insertions. ### Notes Using `qualifyAssembly` in the app config has the advantage of keeping everything _field-configurable_, i.e. in the unlikely case that a custom build environment will ship with a different version of the resolver, it will be possible to compensate for that by tweaking the config file. The disadvantage is that the same `qualifyAssembly` will need to be added to devenv.exe.config because .pkgdef doesn't support this kind of entry, to my best knowledge. It should be a one-time change, though, because [we have frozen the version of `Microsoft.DotNet.MSBuildSdkResolver` to 8.0.100.0](https://github.com/dotnet/sdk/pull/36733). --- documentation/wiki/ChangeWaves.md | 1 + .../Components/SdkResolution/SdkResolverLoader.cs | 14 ++++++++++++++ src/MSBuild/app.amd64.config | 15 +++++++++++++++ src/MSBuild/app.config | 15 +++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/documentation/wiki/ChangeWaves.md b/documentation/wiki/ChangeWaves.md index 6282a09e7b1..ec84d18521a 100644 --- a/documentation/wiki/ChangeWaves.md +++ b/documentation/wiki/ChangeWaves.md @@ -29,6 +29,7 @@ A wave of features is set to "rotate out" (i.e. become standard functionality) t - [Cache SDK resolver data process-wide](https://github.com/dotnet/msbuild/pull/9335) - [Target parameters will be unquoted](https://github.com/dotnet/msbuild/pull/9452), meaning the ';' symbol in the parameter target name will always be treated as separator - [Change Version switch output to finish with a newline](https://github.com/dotnet/msbuild/pull/9485) +- [Load Microsoft.DotNet.MSBuildSdkResolver into default load context (MSBuild.exe only)](https://github.com/dotnet/msbuild/pull/9439) ### 17.8 - [[RAR] Don't do I/O on SDK-provided references](https://github.com/dotnet/msbuild/pull/8688) diff --git a/src/Build/BackEnd/Components/SdkResolution/SdkResolverLoader.cs b/src/Build/BackEnd/Components/SdkResolution/SdkResolverLoader.cs index 3c5349611c1..25039ccd712 100644 --- a/src/Build/BackEnd/Components/SdkResolution/SdkResolverLoader.cs +++ b/src/Build/BackEnd/Components/SdkResolution/SdkResolverLoader.cs @@ -226,6 +226,20 @@ protected virtual IEnumerable GetResolverTypes(Assembly assembly) protected virtual Assembly LoadResolverAssembly(string resolverPath) { #if !FEATURE_ASSEMBLYLOADCONTEXT + if (ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_10)) + { + string resolverFileName = Path.GetFileNameWithoutExtension(resolverPath); + if (resolverFileName.Equals("Microsoft.DotNet.MSBuildSdkResolver", StringComparison.OrdinalIgnoreCase)) + { + // This will load the resolver assembly into the default load context if possible, and fall back to LoadFrom context. + // We very much prefer the default load context because it allows native images to be used by the CLR, improving startup perf. + AssemblyName assemblyName = new AssemblyName(resolverFileName) + { + CodeBase = resolverPath, + }; + return Assembly.Load(assemblyName); + } + } return Assembly.LoadFrom(resolverPath); #else return s_loader.LoadFromPath(resolverPath); diff --git a/src/MSBuild/app.amd64.config b/src/MSBuild/app.amd64.config index 1feab29307d..34c409fa079 100644 --- a/src/MSBuild/app.amd64.config +++ b/src/MSBuild/app.amd64.config @@ -184,6 +184,21 @@ + + + + + + + + + + + + + + + diff --git a/src/MSBuild/app.config b/src/MSBuild/app.config index 51d2a26861e..cb3e75d2510 100644 --- a/src/MSBuild/app.config +++ b/src/MSBuild/app.config @@ -133,6 +133,21 @@ + + + + + + + + + + + + + + +