Skip to content

Commit 657005a

Browse files
mshea-msftrainersigwald
authored andcommitted
Removing sln level turn off of setplatform feature
Currently we turn off dynamic platform resolution for a whole solution if a single project in the solution is assigned a configuration. This is problematic as some projects are outside of the scope of the solution but still have certain targets that run on them that are architecture specific. These projects will build as the wrong architecture because no configuration is defined and no platform negotiation takes place. I removed the conditional that turns platform negotiation off on a sln level. The logic to turn this off on a project level is already in place through checking is a projectreference has setplatform appended to it. This will make sure no projects with configurations defined will be negotiated for as MSbuild adds setplatform metadata to projectreferences with configurations.
1 parent 5785ed5 commit 657005a

File tree

3 files changed

+110
-5
lines changed

3 files changed

+110
-5
lines changed

src/Build.UnitTests/Graph/GetCompatiblePlatformGraph_Tests.cs

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace Microsoft.Build.Graph.UnitTests
2727
/// <summary>
2828
/// Performs SetPlatform negotiation for all project references when opted
2929
/// in via the EnableDynamicPlatformResolution property.
30-
///
30+
///
3131
/// The static graph mirrors the negotiation during build to determine plartform for each node.
3232
/// These tests mirror GetCompatiblePlatform_Tests.cs in order to make sure they both are in sync.
3333
/// </summary>
@@ -351,5 +351,102 @@ public void PlatformIsChosenAsDefault()
351351
GetFirstNodeWithProjectNumber(graph, 2).ProjectInstance.GetPropertyValue("Platform").ShouldBe(GetFirstNodeWithProjectNumber(graph, 1).ProjectInstance.GetPropertyValue("Platform"));
352352
}
353353
}
354+
355+
// Validate configurations are defined in project reference protocol
356+
[Fact]
357+
public void SolutionWithoutAllConfigurations()
358+
{
359+
using (TestEnvironment testEnvironment = TestEnvironment.Create())
360+
{
361+
var firstProjectName = "1";
362+
var secondProjectName = "2";
363+
var thirdProjectName = "3";
364+
TransientTestFolder folder = testEnvironment.CreateFolder(createFolder: true);
365+
TransientTestFolder project1Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, firstProjectName), createFolder: true);
366+
TransientTestFolder project1SubFolder = testEnvironment.CreateFolder(Path.Combine(project1Folder.Path, firstProjectName), createFolder: true);
367+
TransientTestFile project1 = testEnvironment.CreateFile(project1SubFolder, $"{firstProjectName}.csproj",
368+
@"<Project>
369+
<PropertyGroup>
370+
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
371+
<Platform>x64</Platform>
372+
</PropertyGroup>
373+
<ItemGroup>
374+
<ProjectReference Include=""$(MSBuildThisFileDirectory)\..\..\2\2\2.proj"" />
375+
<ProjectReference Include=""$(MSBuildThisFileDirectory)\..\..\3\3\3.proj"" />
376+
</ItemGroup>
377+
</Project>
378+
");
379+
380+
TransientTestFolder project2Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, secondProjectName), createFolder: true);
381+
TransientTestFolder project2SubFolder = testEnvironment.CreateFolder(Path.Combine(project2Folder.Path, secondProjectName), createFolder: true);
382+
TransientTestFile project2 = testEnvironment.CreateFile(project2SubFolder, $"{secondProjectName}.proj",
383+
@"<Project>
384+
<PropertyGroup>
385+
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
386+
<Platforms>AnyCPU;x64</Platforms>
387+
</PropertyGroup>
388+
</Project>
389+
");
390+
391+
TransientTestFolder project3Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, thirdProjectName), createFolder: true);
392+
TransientTestFolder project3SubFolder = testEnvironment.CreateFolder(Path.Combine(project3Folder.Path, thirdProjectName), createFolder: true);
393+
TransientTestFile project3 = testEnvironment.CreateFile(project3SubFolder, $"{thirdProjectName}.proj",
394+
@"<Project>
395+
<PropertyGroup>
396+
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
397+
<Platforms>AnyCPU;x64</Platforms>
398+
</PropertyGroup>
399+
</Project>
400+
");
401+
402+
403+
// Slashes here (and in the .slnf) are hardcoded as backslashes intentionally to support the common case.
404+
TransientTestFile solutionFile = testEnvironment.CreateFile(folder, "SimpleProject.sln",
405+
@"
406+
Microsoft Visual Studio Solution File, Format Version 12.00
407+
# Visual Studio Version 16
408+
VisualStudioVersion = 16.0.29326.124
409+
MinimumVisualStudioVersion = 10.0.40219.1
410+
Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Project1"", ""1\1\1.csproj"", ""{79B5EBA6-5D27-4976-BC31-14422245A59A}""
411+
EndProject
412+
Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""2"", ""2\2\2.proj"", ""{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}""
413+
EndProject
414+
Global
415+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
416+
Debug|x64 = Debug|x64
417+
Release|x64 = Release|x64
418+
EndGlobalSection
419+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
420+
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Debug|x64.ActiveCfg = Debug|x64
421+
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Debug|x64.Build.0 = Debug|x64
422+
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Release|x64.ActiveCfg = Release|x64
423+
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Release|x64.Build.0 = Release|x64
424+
425+
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Debug|x64.ActiveCfg = Debug|Any CPU
426+
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Debug|x64.Build.0 = Debug|Any CPU
427+
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Release|x64.ActiveCfg = Release|Any CPU
428+
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Release|x64.Build.0 = Release|Any CPU
429+
EndGlobalSection
430+
GlobalSection(SolutionProperties) = preSolution
431+
HideSolutionNode = FALSE
432+
EndGlobalSection
433+
GlobalSection(ExtensibilityGlobals) = postSolution
434+
SolutionGuid = {DE7234EC-0C4D-4070-B66A-DCF1B4F0CFEF}
435+
EndGlobalSection
436+
EndGlobal
437+
");
438+
439+
ProjectCollection projectCollection = testEnvironment.CreateProjectCollection().Collection;
440+
MockLogger logger = new();
441+
projectCollection.RegisterLogger(logger);
442+
ProjectGraphEntryPoint entryPoint = new(solutionFile.Path, new Dictionary<string, string>());
443+
444+
// We want to make sure negotiation respects configuration if defined but negotiates if not.
445+
ProjectGraph graphFromSolution = new(entryPoint, projectCollection);
446+
logger.AssertNoErrors();
447+
GetFirstNodeWithProjectNumber(graphFromSolution, 2).ProjectInstance.GetPropertyValue("Platform").ShouldBe("AnyCPU", "Project2 should have followed the sln config to AnyCPU");
448+
GetFirstNodeWithProjectNumber(graphFromSolution, 3).ProjectInstance.GetPropertyValue("Platform").ShouldBe("x64", "Project3 isn't in the solution so it should have negotiated to x64 to match Project1");
449+
}
450+
}
354451
}
355452
}

src/Build/Graph/ProjectInterpretation.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private readonly struct TargetSpecification
6363
{
6464
public TargetSpecification(string target, bool skipIfNonexistent)
6565
{
66-
// Verify that if this target is skippable then it equals neither
66+
// Verify that if this target is skippable then it equals neither
6767
// ".default" nor ".projectReferenceTargetsOrDefaultTargets".
6868
ErrorUtilities.VerifyThrow(
6969
!skipIfNonexistent || (!target.Equals(MSBuildConstants.DefaultTargetsMarker)
@@ -131,6 +131,8 @@ public IEnumerable<ReferenceInfo> GetReferences(ProjectInstance requesterInstanc
131131
allowCollectionReuse: solutionConfiguration == null && !enableDynamicPlatformResolution,
132132
globalPropertiesModifiers);
133133

134+
bool configurationDefined = false;
135+
134136
// Match what AssignProjectConfiguration does to resolve project references.
135137
if (solutionConfiguration != null)
136138
{
@@ -151,6 +153,8 @@ public IEnumerable<ReferenceInfo> GetReferences(ProjectInstance requesterInstanc
151153
{
152154
referenceGlobalProperties.Remove(PlatformMetadataName);
153155
}
156+
157+
configurationDefined = true;
154158
}
155159
else
156160
{
@@ -161,11 +165,16 @@ public IEnumerable<ReferenceInfo> GetReferences(ProjectInstance requesterInstanc
161165
referenceGlobalProperties.Remove(ConfigurationMetadataName);
162166
referenceGlobalProperties.Remove(PlatformMetadataName);
163167
}
168+
else
169+
{
170+
configurationDefined = true;
171+
}
164172
}
165173
}
166174

167-
// Note: Dynamic platform resolution is not enabled for sln-based builds.
168-
else if (!projectReferenceItem.HasMetadata(SetPlatformMetadataName) && enableDynamicPlatformResolution)
175+
// Note: Dynamic platform resolution is not enabled for sln-based builds,
176+
// unless the project isn't known to the solution.
177+
if (enableDynamicPlatformResolution && !configurationDefined && !projectReferenceItem.HasMetadata(SetPlatformMetadataName))
169178
{
170179
string requesterPlatform = requesterInstance.GetPropertyValue("Platform");
171180
string requesterPlatformLookupTable = requesterInstance.GetPropertyValue("PlatformLookupTable");

src/Tasks/Microsoft.Common.CurrentVersion.targets

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1648,7 +1648,6 @@ Copyright (C) Microsoft Corporation. All rights reserved.
16481648
Configuration information. See AssignProjectConfiguration -->
16491649
<Target Name="_GetProjectReferencePlatformProperties"
16501650
Condition="'$(EnableDynamicPlatformResolution)' == 'true'
1651-
and '$(CurrentSolutionConfigurationContents)' == ''
16521651
and '@(_MSBuildProjectReferenceExistent)' != ''">
16531652

16541653
<!-- Allow preset SetPlatform to override this operation -->

0 commit comments

Comments
 (0)