Adopt MSBuild partial ProjectInstance evaluation in CLI hot paths#55271
Conversation
Use ProjectInstance.FromFile/FromProjectRootElement with a ProjectOptions EvaluationStage (Properties or Items) to stop evaluation after the pass that produces the data each site needs, avoiding unnecessary full evaluation. ProjectInstance is uncached and read-only, so partial instances cannot be silently upgraded to full or serve stale state (unlike the mutable, ProjectCollection-cached Project type). - MsbuildProject/ReleasePropertyProjectLocator: stage Properties. - ReferenceListCommand/SolutionAddCommand: stage Items. - Add ProjectInstance overloads of GetRuntimeIdentifiers, GetTargetFrameworks, and GetPropertyCommaSeparatedValues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 008efa7a-b4fc-4f33-9dc7-d37d3f0e93c3
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR updates several dotnet CLI code paths to use MSBuild’s partial (stop-after-pass) project evaluation API via ProjectInstance.FromFile / ProjectInstance.FromProjectRootElement with ProjectOptions.EvaluationStage, avoiding full evaluation when only properties (or items) are needed. The goal is to reduce overhead in CLI hot paths that previously performed more evaluation work than required.
Changes:
- Switch project evaluation in CLI helpers from full evaluation / legacy
ProjectInstanceconstructors toProjectInstance.FromFile/FromProjectRootElementwithEvaluationStageset toPropertiesorItemsas appropriate. - Cache a single
ProjectInstanceevaluation inMsbuildProjectfor repeated property reads (TFM/RID/configuration-related). - Add
ProjectInstanceextension helpers mirroring existingProjectextension helpers for property parsing and TFM/RID extraction.
Show a summary per file
| File | Description |
|---|---|
| src/Cli/dotnet/ReleasePropertyProjectLocator.cs | Uses partial evaluation (Properties stage) when reading PackRelease/PublishRelease-related properties from projects. |
| src/Cli/dotnet/MsbuildProject.cs | Replaces cached Project evaluation with a cached partially-evaluated ProjectInstance for property-only reads. |
| src/Cli/dotnet/Extensions/ProjectInstanceExtensions.cs | Adds ProjectInstance overloads for RID/TFM parsing and comma-separated property parsing. |
| src/Cli/dotnet/Commands/Solution/Add/SolutionAddCommand.cs | Uses Items-stage partial evaluation for reading ProjectReference items and select properties. |
| src/Cli/dotnet/Commands/Reference/List/ReferenceListCommand.cs | Uses Items-stage partial evaluation for listing ProjectReference items. |
Copilot's findings
- Files reviewed: 5/5 changed files
- Comments generated: 0
baronfel
left a comment
There was a problem hiding this comment.
Looks broadly good! I wish we didn't have as much random MSBuild Object Model usage around the codebase, but we can consolidate in a later PR.
|
@baronfel hmm any idea what these failures are about? Pre-existing issue or something from my changes? |
|
AOT build issues? Yeah, those legs shouldn't be running AOT test but are for some reason. I've got a fix in my AOT CLI enablement PR that should land today. |
|
OK yeah, I see that CI is on the floor in this repo. The failures are elsewhere as well: #55272 |
|
OK, now I'm hitting some other unrelated AOT build failures:
|
|
That's only on the windows-arm leg, which is lower prio. What I was gonna do this morning was skip that job and pull in the runtime/linker teams because it seems to be an issue with the linker on ARM specifically. |
|
Maybe someone can let me know when the CI is green again for this PR to get merged. cc @marcpopMSFT |
|
Working through this over at #55144, hopefully ready in the next hour. |
|
Fixed in a better way by #55302. |
Summary
Adopts MSBuild's new partial (stop-after-pass) evaluation API in
dotnetCLI hot paths. Instead of fully evaluating a project just to read a handful of properties orProjectReferenceitems, these sites now useProjectInstance.FromFile/ProjectInstance.FromProjectRootElementwith aProjectOptions.EvaluationStage, stopping evaluation after the pass that produces the data they need.This depends on the MSBuild-side change (dotnet/msbuild#14340, merged), which restricts partial evaluation to
ProjectInstanceand switched the-getProperty/-getItemCLI paths accordingly. The required API arrived here viaMicrosoft.Build18.10.0-1.26363.117.Why
ProjectInstance(notProject)Projectis mutable and cached in aProjectCollection. A partially-evaluated cachedProjectwould either serve stale state or be silently upgraded to a full evaluation on later access.ProjectInstanceis uncached and read-only, so partial instances are trap-proof.Changes
MsbuildProject.GetEvaluatedProjectPropertiesFullPathReleasePropertyProjectLocator.TryGetProjectInstancePropertiesReferenceListCommandItemsProjectReferenceitemsSolutionAddCommandItemsProjectReferenceitems + default project type GUIDAlso adds
ProjectInstanceoverloads ofGetRuntimeIdentifiers,GetTargetFrameworks, andGetPropertyCommaSeparatedValues.Validation
dotnet.csprojbuilds cleanly (0 warnings, 0 errors). Behavior is preserved: all reads occur within their declared evaluation stage, andProjectInstance.FromFilematches the previousLoadProject(FullPath)semantics for these callers (all use a freshProjectCollectionwith empty global properties).