|
296 | 296 | </ItemGroup> |
297 | 297 | </Target> |
298 | 298 |
|
| 299 | + <!-- |
| 300 | + The net472 servicing redistribution above swaps DLLs and updates the binding redirects only in |
| 301 | + the projects that opt in ($(DeployRuntimeServicingAssemblies) == 'true': MSBuild.exe and the |
| 302 | + bootstrap). Other net472 projects that re-bundle MSBuild.exe (the test projects that spawn it |
| 303 | + out-of-proc, e.g. via ProjectReference to MSBuild.csproj) copy MSBuild.exe.config (which now |
| 304 | + carries the servicing redirects) but resolve their own copy-local runtime assemblies at the |
| 305 | + compiled-against versions. That leaves MSBuild.exe.config pointing at servicing versions |
| 306 | + (e.g. System.Memory 4.0.5.0) while the assembly on disk is the compiled-against one |
| 307 | + (4.0.2.0), so the copied MSBuild.exe fails to start with a FileLoadException, breaking every |
| 308 | + out-of-proc test (and hanging tests that wait on a spawned node/server). |
| 309 | +
|
| 310 | + These bins are not a VS redistribution surface, so the fix is to keep them self-consistent at |
| 311 | + the compiled-against versions: realign the copied MSBuild.exe.config binding redirects to the |
| 312 | + runtime assemblies actually next to it. Deploy surfaces are excluded; their DLLs already are |
| 313 | + the servicing build, so realigning would be a no-op there anyway. |
| 314 | + --> |
| 315 | + <UsingTask TaskName="AlignBindingRedirectsToOutputAssemblies" |
| 316 | + AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" |
| 317 | + TaskFactory="RoslynCodeTaskFactory"> |
| 318 | + <ParameterGroup> |
| 319 | + <ConfigFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" /> |
| 320 | + </ParameterGroup> |
| 321 | + <Task> |
| 322 | + <Code Type="Fragment" Language="cs"><![CDATA[ |
| 323 | + System.Xml.Linq.XNamespace ns = "urn:schemas-microsoft-com:asm.v1"; |
| 324 | + foreach (Microsoft.Build.Framework.ITaskItem item in ConfigFiles) |
| 325 | + { |
| 326 | + string configPath = item.ItemSpec; |
| 327 | + if (!System.IO.File.Exists(configPath)) |
| 328 | + { |
| 329 | + continue; |
| 330 | + } |
| 331 | +
|
| 332 | + string directory = System.IO.Path.GetDirectoryName(configPath); |
| 333 | + System.Xml.Linq.XDocument document = System.Xml.Linq.XDocument.Load(configPath); |
| 334 | + bool changed = false; |
| 335 | +
|
| 336 | + foreach (System.Xml.Linq.XElement dependentAssembly in document.Descendants(ns + "dependentAssembly")) |
| 337 | + { |
| 338 | + System.Xml.Linq.XElement identity = dependentAssembly.Element(ns + "assemblyIdentity"); |
| 339 | + System.Xml.Linq.XElement redirect = dependentAssembly.Element(ns + "bindingRedirect"); |
| 340 | + if (identity == null || redirect == null) |
| 341 | + { |
| 342 | + continue; |
| 343 | + } |
| 344 | +
|
| 345 | + string name = (string)identity.Attribute("name"); |
| 346 | + if (string.IsNullOrEmpty(name)) |
| 347 | + { |
| 348 | + continue; |
| 349 | + } |
| 350 | +
|
| 351 | + string assemblyPath = System.IO.Path.Combine(directory, name + ".dll"); |
| 352 | + if (!System.IO.File.Exists(assemblyPath)) |
| 353 | + { |
| 354 | + continue; |
| 355 | + } |
| 356 | +
|
| 357 | + string version; |
| 358 | + try |
| 359 | + { |
| 360 | + version = System.Reflection.AssemblyName.GetAssemblyName(assemblyPath).Version.ToString(); |
| 361 | + } |
| 362 | + catch (System.Exception) |
| 363 | + { |
| 364 | + continue; |
| 365 | + } |
| 366 | +
|
| 367 | + redirect.SetAttributeValue("oldVersion", "0.0.0.0-" + version); |
| 368 | + redirect.SetAttributeValue("newVersion", version); |
| 369 | +
|
| 370 | + System.Xml.Linq.XElement codeBase = dependentAssembly.Element(ns + "codeBase"); |
| 371 | + if (codeBase != null) |
| 372 | + { |
| 373 | + codeBase.SetAttributeValue("version", version); |
| 374 | + } |
| 375 | +
|
| 376 | + changed = true; |
| 377 | + } |
| 378 | +
|
| 379 | + if (changed) |
| 380 | + { |
| 381 | + document.Save(configPath); |
| 382 | + Log.LogMessage(Microsoft.Build.Framework.MessageImportance.Normal, "Aligned binding redirects in '{0}' to the runtime assemblies in its output directory.", configPath); |
| 383 | + } |
| 384 | + } |
| 385 | + ]]></Code> |
| 386 | + </Task> |
| 387 | + </UsingTask> |
| 388 | + |
| 389 | + <Target Name="AlignCopiedMSBuildExeConfigBindingRedirects" |
| 390 | + AfterTargets="Build" |
| 391 | + Condition="'$(TargetFramework)' == 'net472' and '$(DeployRuntimeServicingAssemblies)' != 'true'"> |
| 392 | + <ItemGroup> |
| 393 | + <_CopiedMSBuildExeConfig Include="$(TargetDir)**\MSBuild.exe.config" /> |
| 394 | + </ItemGroup> |
| 395 | + <AlignBindingRedirectsToOutputAssemblies ConfigFiles="@(_CopiedMSBuildExeConfig)" |
| 396 | + Condition="'@(_CopiedMSBuildExeConfig)' != ''" /> |
| 397 | + </Target> |
| 398 | + |
299 | 399 | <!-- Import parent targets --> |
300 | 400 | <Import Project="..\Directory.Build.targets"/> |
301 | 401 |
|
|
0 commit comments