Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions src/Build.UnitTests/Graph/ProjectGraph_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ public void ConstructGraphWithSolution()
* Project types other than "well-known" MSBuild project types:
* Buildable project (wapproj)
* Solution folder
* Project not included in build (also has solution dependencies as a regression test)
*
*/
using (var env = TestEnvironment.Create())
Expand All @@ -708,7 +709,12 @@ public void ConstructGraphWithSolution()
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Project6", "Project6.wapproj", "{CA5CAD1A-224A-4171-B13A-F16E576FDD12}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0392E290-973E-4086-A58E-F927AAA65B9A}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project7", "Project7.csproj", "{28C7025E-2AB6-4962-A001-1E5B2271837C}"
ProjectSection(ProjectDependencies) = postProject
{52B2ED64-1CFC-401B-8C5B-6D1E1DEADF98} = {52B2ED64-1CFC-401B-8C5B-6D1E1DEADF98}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0392E290-973E-4086-A58E-F927AAA65B9A}"
ProjectSection(SolutionItems) = preProject
SomeSolutionItemsFile = SomeSolutionItemsFile
EndProjectSection
Expand Down Expand Up @@ -777,15 +783,15 @@ public void ConstructGraphWithSolution()
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.Build.0 = Debug|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.Deploy.0 = Debug|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|Win32.ActiveCfg = Release|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|Win32.Build.0 = Release|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|Win32.Deploy.0 = Release|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x64.ActiveCfg = Release|x64
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x64.Build.0 = Release|x64
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x64.Deploy.0 = Release|x64
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x86.ActiveCfg = Release|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x86.Build.0 = Release|x86
{CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
{28C7025E-2AB6-4962-A001-1E5B2271837C}.Debug|Win32.ActiveCfg = Debug|x86
{28C7025E-2AB6-4962-A001-1E5B2271837C}.Debug|x64.ActiveCfg = Debug|x64
{28C7025E-2AB6-4962-A001-1E5B2271837C}.Debug|x86.ActiveCfg = Debug|x86
{28C7025E-2AB6-4962-A001-1E5B2271837C}.Release|Win32.ActiveCfg = Release|x86
{28C7025E-2AB6-4962-A001-1E5B2271837C}.Release|x64.ActiveCfg = Release|x64
{28C7025E-2AB6-4962-A001-1E5B2271837C}.Release|x86.ActiveCfg = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
Expand Down Expand Up @@ -814,20 +820,23 @@ public void ConstructGraphWithSolution()
ProjectRootElement project4Xml = ProjectRootElement.Create();
ProjectRootElement project5Xml = ProjectRootElement.Create();
ProjectRootElement project6Xml = ProjectRootElement.Create();
ProjectRootElement project7Xml = ProjectRootElement.Create();

string project1Path = Path.Combine(env.DefaultTestDirectory.Path, "Project1.csproj");
string project2Path = Path.Combine(env.DefaultTestDirectory.Path, "Project2.vcxproj");
string project3Path = Path.Combine(env.DefaultTestDirectory.Path, "Project3.vcxproj");
string project4Path = Path.Combine(env.DefaultTestDirectory.Path, "Project4.vcxproj");
string project5Path = Path.Combine(env.DefaultTestDirectory.Path, "Project5.vcxproj");
string project6Path = Path.Combine(env.DefaultTestDirectory.Path, "Project6.wapproj");
string project7Path = Path.Combine(env.DefaultTestDirectory.Path, "Project7.csproj");

project1Xml.Save(project1Path);
project2Xml.Save(project2Path);
project3Xml.Save(project3Path);
project4Xml.Save(project4Path);
project5Xml.Save(project5Path);
project6Xml.Save(project6Path);
project7Xml.Save(project7Path);

var projectGraph = new ProjectGraph(slnFile.Path);
projectGraph.EntryPointNodes.Count.ShouldBe(4);
Expand Down Expand Up @@ -867,6 +876,9 @@ public void ConstructGraphWithSolution()
project6Node.ProjectInstance.GlobalProperties["Configuration"].ShouldBe("Debug");
project6Node.ProjectInstance.GlobalProperties["Platform"].ShouldBe("x86");
project6Node.ProjectReferences.Count.ShouldBe(0);

// Project not included in the build
Assert.DoesNotContain(projectGraph.ProjectNodes, node => node.ProjectInstance.FullPath == project7Path);
}
}

Expand Down
74 changes: 35 additions & 39 deletions src/Build/Graph/GraphBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ private static void AddEdgesFromSolution(IReadOnlyDictionary<ConfigurationMetada
Dictionary<string, ImmutableDictionary<string, string>> globalPropertiesForProjectConfiguration = new(StringComparer.OrdinalIgnoreCase);

IReadOnlyList<ProjectInSolution> projectsInSolution = solution.ProjectsInOrder;
var newEntryPoints = new List<ProjectGraphEntryPoint>(projectsInSolution.Count);
List<ProjectGraphEntryPoint> newEntryPoints = new(projectsInSolution.Count);
Dictionary<string, IReadOnlyCollection<string>> solutionDependencies = new();

foreach (ProjectInSolution project in projectsInSolution)
{
Expand All @@ -332,11 +333,43 @@ private static void AddEdgesFromSolution(IReadOnlyDictionary<ConfigurationMetada
}

newEntryPoints.Add(new ProjectGraphEntryPoint(project.AbsolutePath, projectGlobalProperties));

if (project.Dependencies.Count > 0)
{
// code snippet cloned from SolutionProjectGenerator.GetSolutionConfiguration

List<string> solutionDependenciesForProject = new(project.Dependencies.Count);
foreach (string dependencyProjectGuid in project.Dependencies)
{
if (!solution.ProjectsByGuid.TryGetValue(dependencyProjectGuid, out ProjectInSolution dependencyProject))
{
ProjectFileErrorUtilities.ThrowInvalidProjectFile(
"SubCategoryForSolutionParsingErrors",
new BuildEventFileInfo(solution.FullPath),
"SolutionParseProjectDepNotFoundError",
project.ProjectGuid,
dependencyProjectGuid);
}

// Add it to the list of dependencies, but only if it should build in this solution configuration
// (If a project is not selected for build in the solution configuration, it won't build even if it's depended on by something that IS selected for build)
// .. and only if it's known to be MSBuild format, as projects can't use the information otherwise
if (dependencyProject.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
{
solutionDependenciesForProject.Add(dependencyProject.AbsolutePath);
}
}

if (solutionDependenciesForProject.Count > 0)
{
solutionDependencies.Add(project.AbsolutePath, solutionDependenciesForProject);
}
}
}

newEntryPoints.TrimExcess();

return (newEntryPoints, GetSolutionDependencies(solution));
return (newEntryPoints, solutionDependencies);

SolutionConfigurationInSolution SelectSolutionConfiguration(SolutionFile solutionFile, IDictionary<string, string> globalProperties)
{
Expand Down Expand Up @@ -367,43 +400,6 @@ ProjectConfigurationInSolution SelectProjectConfiguration(
var partiallyMarchedConfig = projectConfigs.FirstOrDefault(pc => pc.Value.ConfigurationName.Equals(solutionConfig.ConfigurationName, StringComparison.OrdinalIgnoreCase)).Value;
return partiallyMarchedConfig ?? projectConfigs.First().Value;
}

IReadOnlyDictionary<string, IReadOnlyCollection<string>> GetSolutionDependencies(SolutionFile solutionFile)
{
var solutionDependencies = new Dictionary<string, IReadOnlyCollection<string>>();

foreach (var projectWithDependencies in solutionFile.ProjectsInOrder.Where(p => p.Dependencies.Count != 0))
{
solutionDependencies[projectWithDependencies.AbsolutePath] = projectWithDependencies.Dependencies.Select(
dependencyGuid =>
{
// code snippet cloned from SolutionProjectGenerator.AddPropertyGroupForSolutionConfiguration

if (!solutionFile.ProjectsByGuid.TryGetValue(dependencyGuid, out var dependencyProject))
{
// If it's not itself part of the solution, that's an invalid solution
ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(
dependencyProject != null,
"SubCategoryForSolutionParsingErrors",
new BuildEventFileInfo(solutionFile.FullPath),
"SolutionParseProjectDepNotFoundError",
projectWithDependencies.ProjectGuid,
dependencyGuid);
}

// Add it to the list of dependencies, but only if it should build in this solution configuration
// (If a project is not selected for build in the solution configuration, it won't build even if it's depended on by something that IS selected for build)
// .. and only if it's known to be MSBuild format, as projects can't use the information otherwise
return dependencyProject?.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat
? dependencyProject.AbsolutePath
: null;
})
.Where(p => p != null)
.ToArray();
}

return solutionDependencies;
}
}

private static List<ConfigurationMetadata> AddGraphBuildPropertyToEntryPoints(IEnumerable<ProjectGraphEntryPoint> entryPoints)
Expand Down