Skip to content

Commit 6257b8e

Browse files
authored
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 dotnet/installer#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](dotnet/sdk#36733).
1 parent 5df2181 commit 6257b8e

File tree

4 files changed

+45
-0
lines changed

4 files changed

+45
-0
lines changed

documentation/wiki/ChangeWaves.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ A wave of features is set to "rotate out" (i.e. become standard functionality) t
2929
- [Cache SDK resolver data process-wide](https://github.com/dotnet/msbuild/pull/9335)
3030
- [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
3131
- [Change Version switch output to finish with a newline](https://github.com/dotnet/msbuild/pull/9485)
32+
- [Load Microsoft.DotNet.MSBuildSdkResolver into default load context (MSBuild.exe only)](https://github.com/dotnet/msbuild/pull/9439)
3233

3334
### 17.8
3435
- [[RAR] Don't do I/O on SDK-provided references](https://github.com/dotnet/msbuild/pull/8688)

src/Build/BackEnd/Components/SdkResolution/SdkResolverLoader.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,20 @@ protected virtual IEnumerable<Type> GetResolverTypes(Assembly assembly)
226226
protected virtual Assembly LoadResolverAssembly(string resolverPath)
227227
{
228228
#if !FEATURE_ASSEMBLYLOADCONTEXT
229+
if (ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_10))
230+
{
231+
string resolverFileName = Path.GetFileNameWithoutExtension(resolverPath);
232+
if (resolverFileName.Equals("Microsoft.DotNet.MSBuildSdkResolver", StringComparison.OrdinalIgnoreCase))
233+
{
234+
// This will load the resolver assembly into the default load context if possible, and fall back to LoadFrom context.
235+
// We very much prefer the default load context because it allows native images to be used by the CLR, improving startup perf.
236+
AssemblyName assemblyName = new AssemblyName(resolverFileName)
237+
{
238+
CodeBase = resolverPath,
239+
};
240+
return Assembly.Load(assemblyName);
241+
}
242+
}
229243
return Assembly.LoadFrom(resolverPath);
230244
#else
231245
return s_loader.LoadFromPath(resolverPath);

src/MSBuild/app.amd64.config

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,21 @@
184184
<assemblyIdentity name="Microsoft.VisualStudio.CodeAnalysis.Sdk" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
185185
<codeBase version="17.0.0.0" href="..\..\..\Microsoft\VisualStudio\v17.0\CodeAnalysis\Microsoft.VisualStudio.CodeAnalysis.Sdk.dll" />
186186
</dependentAssembly>
187+
188+
<!-- Redirects for SDK resolver components -->
189+
<qualifyAssembly partialName="Microsoft.DotNet.MSBuildSdkResolver" fullName="Microsoft.DotNet.MSBuildSdkResolver, Version=8.0.100.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" />
190+
<dependentAssembly>
191+
<assemblyIdentity name="Microsoft.DotNet.MSBuildSdkResolver" culture="neutral" publicKeyToken="adb9793829ddae60" />
192+
<codeBase version="8.0.100.0" href="..\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.DotNet.MSBuildSdkResolver.dll" />
193+
</dependentAssembly>
194+
<dependentAssembly>
195+
<assemblyIdentity name="Microsoft.Deployment.DotNet.Releases" culture="neutral" publicKeyToken="31bf3856ad364e35" />
196+
<codeBase version="2.0.0.0" href="..\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.Deployment.DotNet.Releases.dll" />
197+
</dependentAssembly>
198+
<dependentAssembly>
199+
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
200+
<codeBase version="13.0.0.0" href="..\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Newtonsoft.Json.dll" />
201+
</dependentAssembly>
187202
</assemblyBinding>
188203
</runtime>
189204
<!-- To define one or more new toolsets, add an 'msbuildToolsets' element in this file. -->

src/MSBuild/app.config

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,21 @@
133133
<assemblyIdentity name="Microsoft.VisualStudio.CodeAnalysis.Sdk" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
134134
<codeBase version="17.0.0.0" href="..\..\Microsoft\VisualStudio\v17.0\CodeAnalysis\Microsoft.VisualStudio.CodeAnalysis.Sdk.dll" />
135135
</dependentAssembly>
136+
137+
<!-- Redirects for SDK resolver components -->
138+
<qualifyAssembly partialName="Microsoft.DotNet.MSBuildSdkResolver" fullName="Microsoft.DotNet.MSBuildSdkResolver, Version=8.0.100.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" />
139+
<dependentAssembly>
140+
<assemblyIdentity name="Microsoft.DotNet.MSBuildSdkResolver" culture="neutral" publicKeyToken="adb9793829ddae60" />
141+
<codeBase version="8.0.100.0" href=".\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.DotNet.MSBuildSdkResolver.dll" />
142+
</dependentAssembly>
143+
<dependentAssembly>
144+
<assemblyIdentity name="Microsoft.Deployment.DotNet.Releases" culture="neutral" publicKeyToken="31bf3856ad364e35" />
145+
<codeBase version="2.0.0.0" href=".\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.Deployment.DotNet.Releases.dll" />
146+
</dependentAssembly>
147+
<dependentAssembly>
148+
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
149+
<codeBase version="13.0.0.0" href=".\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Newtonsoft.Json.dll" />
150+
</dependentAssembly>
136151
</assemblyBinding>
137152
</runtime>
138153
<!-- To define one or more new toolsets, add an 'msbuildToolsets' element in this file. -->

0 commit comments

Comments
 (0)