Skip to content

Introduce mode for project graph construction to load entire graph #13717

Merged
AlesProkop merged 3 commits into
dotnet:mainfrom
jeffkl:project-graph-mode
Jun 22, 2026
Merged

Introduce mode for project graph construction to load entire graph #13717
AlesProkop merged 3 commits into
dotnet:mainfrom
jeffkl:project-graph-mode

Conversation

@jeffkl

@jeffkl jeffkl commented May 8, 2026

Copy link
Copy Markdown
Contributor

Enables accurate NuGet package dependency resolution across all target frameworks and configurations.

Context

NuGet Package Manager needs to resolve package dependencies for restore operations. The current ProjectGraphMode.Default only loads projects needed for a specific build, which would require separate graph constructions for each target framework. By providing a complete graph that includes all outer and inner builds regardless of SetTargetFramework constraints, NuGet can efficiently perform package resolution in a single pass. This is especially important for multi-targeted projects where different frameworks may have different dependencies.

Changes Made

Introduced a new ProjectGraphOptions struct because project graph construction happens in a constructor and adding a new overload seemed like a worse design. This way we can add new options to the struct and not keep having to modify the constructor.

var projectGraph = new ProjectGraph(
    new ProjectGraphOptions
    {
        EntryPoints = [new ProjectGraphEntryPoint("path")],
        Mode = ProjectGraphMode.Full
    });

In the new ProjectGraphMode.Full mode:

  • SetTargetFramework metadata is ignored during graph construction
  • All outer and inner builds are evaluated, regardless of framework filters
  • This provides a complete view of the dependency graph needed for restore operations
  • Note: Using the "full" graph for an actual build would technically overbuild, but it's the correct mode for package resolution

Testing

Added unit test demonstrating that ProjectGraphMode.Full loads all target framework instances even when SetTargetFramework would normally filter them.

Had to fix a few tests that were broken. These tests are marked as inactive and it wasn't caught.

Notes

@jeffkl jeffkl self-assigned this May 8, 2026
@jeffkl jeffkl changed the title [Draft]: Introduce mode for project graph construction to load entire graph Introduce mode for project graph construction to load entire graph May 26, 2026
@jeffkl jeffkl marked this pull request as ready for review May 26, 2026 17:15
Copilot AI review requested due to automatic review settings May 26, 2026 17:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new options-based construction API for ProjectGraph and introduces a new “Full” graph-construction mode intended to load/evaluate the entire project graph (ignoring SetTargetFramework constraints during construction) for restore scenarios.

Changes:

  • Added ProjectGraphOptions (and ProjectGraphMode) and a new ProjectGraph(ProjectGraphOptions, ...) constructor.
  • Threaded graph mode through GraphBuilder/ProjectInterpretation and added logic to ignore SetTargetFramework in Full mode.
  • Added a new unit test intended to validate Full-mode behavior with multitargeting + SetTargetFramework.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Build/Microsoft.Build.csproj Includes the new ProjectGraphOptions.cs in the build.
src/Build/Graph/ProjectInterpretation.cs Adds Full-mode reference enumeration behavior (ignoring SetTargetFramework).
src/Build/Graph/ProjectGraphOptions.cs Introduces ProjectGraphOptions and ProjectGraphMode public API surface.
src/Build/Graph/ProjectGraph.cs Adds an options-based constructor and routes existing constructors through it.
src/Build/Graph/GraphBuilder.cs Passes graph mode into reference parsing to enable mode-specific behavior.
src/Build.UnitTests/Graph/ProjectGraph_Tests.cs Adds a new test intended to cover Full-mode graph construction behavior.

Comment thread src/Build/Graph/ProjectInterpretation.cs
Comment thread src/Build/Graph/ProjectInterpretation.cs Outdated
Comment thread src/Build/Graph/ProjectGraphOptions.cs
Comment thread src/Build/Graph/ProjectGraphOptions.cs Outdated
Comment thread src/Build/Graph/ProjectGraph.cs
Comment thread src/Build.UnitTests/Graph/ProjectGraph_Tests.cs Outdated
Comment thread src/Build.UnitTests/Graph/ProjectGraph_Tests.cs Outdated
@JanProvaznik

Copy link
Copy Markdown
Member

/review

@JanProvaznik

Copy link
Copy Markdown
Member

MSBuild triage: @jeffkl could you please elaborate in the description on the business value?

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Expert Code Review (command) failed. Please review the logs for details.

ChangeWave Discipline — LGTM

No ChangeWave is required. The new behavior activates only when the caller explicitly constructs new ProjectGraphOptions { Mode = ProjectGraphMode.Full }. The default value is ProjectGraphMode.Default = 0, so every existing call site — including all callers of new ProjectGraph(...) — receives exactly the same behavior as before. There is no scenario in which an existing build changes behavior without a deliberate code change by the consuming developer. ChangeWaves exist to protect users from implicit behavioral changes; this PR introduces no such change.

Comment thread src/Build/Graph/ProjectInterpretation.cs
Comment thread src/Build.UnitTests/Graph/ProjectGraph_Tests.cs Outdated
Comment thread src/Build.UnitTests/Graph/ProjectGraph_Tests.cs Outdated
@jeffkl jeffkl force-pushed the project-graph-mode branch 2 times, most recently from ea44811 to 7c558fe Compare June 16, 2026 18:20
Comment thread src/Build/Graph/ProjectInterpretation.cs
Comment thread src/Build/Graph/ProjectInterpretation.cs Outdated
@jeffkl jeffkl force-pushed the project-graph-mode branch from 7c558fe to 001f854 Compare June 17, 2026 15:56

@AlesProkop AlesProkop left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@AlesProkop AlesProkop merged commit 30ce7c4 into dotnet:main Jun 22, 2026
14 checks passed
DustinCampbell pushed a commit to DustinCampbell/msbuild that referenced this pull request Jun 22, 2026
…otnet#13717)

Enables accurate NuGet package dependency resolution across all target
frameworks and configurations.

### Context

NuGet Package Manager needs to resolve package dependencies for restore
operations. The current ProjectGraphMode.Default only loads projects
needed for a specific build, which would require separate graph
constructions for each target framework. By providing a complete graph
that includes all outer and inner builds regardless of
SetTargetFramework constraints, NuGet can efficiently perform package
resolution in a single pass. This is especially important for
multi-targeted projects where different frameworks may have different
dependencies.

### Changes Made

Introduced a new ProjectGraphOptions struct because project graph
construction happens in a constructor and adding a new overload seemed
like a worse design. This way we can add new options to the struct and
not keep having to modify the constructor.

```csharp
var projectGraph = new ProjectGraph(
    new ProjectGraphOptions
    {
        EntryPoints = [new ProjectGraphEntryPoint("path")],
        Mode = ProjectGraphMode.Full
    });
```

In the new ProjectGraphMode.Full mode:
- SetTargetFramework metadata is ignored during graph construction
- All outer and inner builds are evaluated, regardless of framework
filters
- This provides a complete view of the dependency graph needed for
restore operations
- Note: Using the "full" graph for an actual build would technically
overbuild, but it's the correct mode for package resolution

### Testing

Added unit test demonstrating that ProjectGraphMode.Full loads all
target framework instances even when SetTargetFramework would normally
filter them.

Had to fix a few tests that were broken. These tests are marked as
inactive and it wasn't caught.

### Notes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants