Skip to content

Move core ProjectReferenceTargets from Managed-only to Common targets#13427

Open
dfederm wants to merge 6 commits into
dotnet:mainfrom
dfederm:projref-targets-fixes
Open

Move core ProjectReferenceTargets from Managed-only to Common targets#13427
dfederm wants to merge 6 commits into
dotnet:mainfrom
dfederm:projref-targets-fixes

Conversation

@dfederm
Copy link
Copy Markdown
Contributor

@dfederm dfederm commented Mar 21, 2026

Summary

Move the core Build/Clean/Rebuild ProjectReferenceTargets protocol from Microsoft.Managed.After.targets into Microsoft.Common.CurrentVersion.targets so it applies to all project types that import the common targets, not just managed languages (C#, VB, F#). This aligns with the static graph spec which prescribes that common protocols be defined in the common targets.

What changed

Targets files

  • Microsoft.Common.CurrentVersion.targets: Now contains the core ProjectReferenceTargets for Build, Clean, and Rebuild, including OuterBuild items, SkipNonexistentTargets items, and the extensibility properties (ProjectReferenceTargetsForBuild, etc.)
  • Microsoft.Common.CrossTargeting.targets: Now contains the cross-targeting outer build protocol (.default dispatch) that was previously inlined in Managed.After.targets
  • Microsoft.Managed.After.targets: Retains only managed-specific extensions: Publish, DeployOnBuild, GetCopyToPublishDirectoryItems, WPF graph isolation, and InnerBuildProperty/InnerBuildPropertyValues

DeployOnBuild refactor

DeployOnBuild handling changed from property-level composition (appending Publish targets to $(ProjectReferenceTargetsForBuild)) to item-level composition (separate ProjectReferenceTargets items). This is functionally equivalent since the static graph engine merges all items with the same Include value, and eliminates a subtle duplication in the old code where ProjectReferenceTargetsForRebuild included publish targets twice.

Documentation

  • Updated stale docs.microsoft.comlearn.microsoft.com URL
  • Converted absolute GitHub links to relative paths
  • Added prose hints for deep-link references into large targets files
  • Fixed typo in SkipNonexistentTargets comment

Testing

Unit tests (11 new, all passing)

New file src/Build.UnitTests/Graph/ProjectReferenceTargetsProtocol_Tests.cs covering:

  • Non-managed project gets core Build/Clean/Rebuild protocol
  • Managed project protocol unchanged after move
  • DeployOnBuild property→item migration
  • Cross-targeting .default dispatch
  • BuildProjectReferences=false and NoBuild=true fallbacks
  • Clean/Rebuild propagation through multi-project chains

Manual validation

Tested with old (VS 18 Canary) vs new (bootstrap) MSBuild:

  • Key result: Non-managed .proj with /graph /isolate — old MSBuild produces MSB4252 isolation violation ("target not specified in ProjectReferenceTargets"), new MSBuild resolves the graph correctly
  • -getItem:ProjectReferenceTargets /p:IsGraphBuild=true on non-managed .proj: old returns empty, new returns full Build/Clean/Rebuild protocol from Microsoft.Common.CurrentVersion.targets
  • C++ graph build binlogs produced for manual inspection

Copilot AI review requested due to automatic review settings March 21, 2026 00:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Moves the static-graph ProjectReferenceTargets protocol for core Build/Clean/Rebuild from managed-only targets into the common MSBuild targets so it applies to all project types that import the common targets, aligning implementation with the static graph spec.

Changes:

  • Added core static-graph ProjectReferenceTargets (Build/Clean/Rebuild) to Microsoft.Common.CurrentVersion.targets.
  • Added cross-targeting (outer build) static-graph ProjectReferenceTargets dispatch protocol to Microsoft.Common.CrossTargeting.targets.
  • Refactored managed DeployOnBuild propagation from property composition to item-based composition and added new unit tests + doc updates.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Tasks/Microsoft.Managed.After.targets Removes core Build/Clean/Rebuild protocol and keeps managed-only Publish/DeployOnBuild extensions.
src/Tasks/Microsoft.Common.CurrentVersion.targets Defines core Build/Clean/Rebuild ProjectReferenceTargets protocol for static graph builds.
src/Tasks/Microsoft.Common.CrossTargeting.targets Defines cross-targeting (outer build) static graph protocol for Build/Clean/Rebuild.
src/Build.UnitTests/Graph/ProjectReferenceTargetsProtocol_Tests.cs Adds unit tests validating protocol behavior across managed/non-managed and cross-targeting scenarios.
documentation/ProjectReference-Protocol.md Updates links and clarifies references to protocol/comment locations in targets files.

Comment thread src/Tasks/Microsoft.Managed.After.targets Outdated
Comment thread src/Build.UnitTests/Graph/ProjectReferenceTargetsProtocol_Tests.cs Outdated
Comment thread src/Build.UnitTests/Graph/ProjectReferenceTargetsProtocol_Tests.cs Outdated
@dfederm dfederm requested a review from a team as a code owner April 9, 2026 18:51
@dfederm dfederm force-pushed the projref-targets-fixes branch from 3dd7d04 to 57fbc44 Compare April 9, 2026 18:56
@dfederm
Copy link
Copy Markdown
Contributor Author

dfederm commented Apr 9, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Commenter does not have sufficient privileges for PR 13427 in repo dotnet/msbuild

Comment thread documentation/ProjectReference-Protocol.md Outdated
Comment thread src/Tasks/Microsoft.Common.CurrentVersion.targets
Comment thread src/Build.UnitTests/Graph/ProjectReferenceTargetsProtocol_Tests.cs Outdated
dfederm pushed a commit to dfederm/msbuild that referenced this pull request May 12, 2026
…of snapshotting protocol XML

Addresses Rainer's review comment on PR dotnet#13427. The test now imports
Microsoft.Common.targets, Microsoft.Common.CrossTargeting.targets, and
Microsoft.Managed.After.targets via $(MSBuildToolsPath) rather than carrying
copy-pasted snapshots of their ProjectReferenceTargets sections. Future drift
between the graph evaluator and the real protocol will now fire these tests
directly instead of leaving them silently stale.

Cross-targeting tests pass a NuGetRestoreTargets stub path because
Microsoft.Common.CrossTargeting.targets imports $(NuGetRestoreTargets)`nunconditionally (no Exists() guard, unlike Common.CurrentVersion.targets).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dfederm pushed a commit to dfederm/msbuild that referenced this pull request May 13, 2026
…of snapshotting protocol XML

Addresses Rainer's review comment on PR dotnet#13427. The test now imports
Microsoft.Common.targets, Microsoft.Common.CrossTargeting.targets, and
Microsoft.Managed.After.targets via $(MSBuildToolsPath) rather than carrying
copy-pasted snapshots of their ProjectReferenceTargets sections. Future drift
between the graph evaluator and the real protocol will now fire these tests
directly instead of leaving them silently stale.

Cross-targeting tests pass a NuGetRestoreTargets stub path because
Microsoft.Common.CrossTargeting.targets imports $(NuGetRestoreTargets)`nunconditionally (no Exists() guard, unlike Common.CurrentVersion.targets).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dfederm dfederm force-pushed the projref-targets-fixes branch from 062f8fd to 8ca1587 Compare May 13, 2026 16:21
dfederm and others added 6 commits May 21, 2026 14:48
Move the core Build/Clean/Rebuild ProjectReferenceTargets protocol from
Microsoft.Managed.After.targets into Microsoft.Common.CurrentVersion.targets
so it applies to all project types that import the common targets, not just
managed languages (C#, VB, F#). This aligns with the static graph spec which
prescribes that common protocols be defined in the common targets.

Extract the cross-targeting outer build protocol (using .default dispatch) into
Microsoft.Common.CrossTargeting.targets where it naturally belongs alongside the
DispatchToInnerBuilds target.

Refactor DeployOnBuild handling from property-level composition (appending
Publish targets to the ProjectReferenceTargetsForBuild property) to item-level
composition (separate ProjectReferenceTargets items). This is functionally
equivalent since the static graph engine merges all items with the same Include
value, and eliminates a subtle duplication in the old code.

Microsoft.Managed.After.targets retains managed-specific extensions: Publish,
DeployOnBuild, GetCopyToPublishDirectoryItems, WPF graph isolation, and the
InnerBuildProperty/InnerBuildPropertyValues definitions.

Also fixes:
- Update docs.microsoft.com URL to learn.microsoft.com
- Convert absolute GitHub links to relative paths in protocol docs
- Add prose hints for deep-link references into large targets files
- Fix typo: GetTargetFrameworksWithPlatformForSingleTargetFrameworks (plural)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix 'managed languaged' typo in Microsoft.Managed.After.targets
- Make _env field readonly in ProjectReferenceTargetsProtocolTests
- Add clarifying comment explaining why outer build includes both protocols

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Rainer Sigwald <raines@microsoft.com>
Add ProjectReferenceTargetsForBuildInOuterBuild and
ProjectReferenceTargetsForCleanInOuterBuild items to
Microsoft.Common.CrossTargeting.targets to preserve the extensibility
points that were previously available in outer builds via
Microsoft.Managed.After.targets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…of snapshotting protocol XML

Addresses Rainer's review comment on PR dotnet#13427. The test now imports
Microsoft.Common.targets, Microsoft.Common.CrossTargeting.targets, and
Microsoft.Managed.After.targets via $(MSBuildToolsPath) rather than carrying
copy-pasted snapshots of their ProjectReferenceTargets sections. Future drift
between the graph evaluator and the real protocol will now fire these tests
directly instead of leaving them silently stale.

Cross-targeting tests pass a NuGetRestoreTargets stub path because
Microsoft.Common.CrossTargeting.targets imports $(NuGetRestoreTargets)`nunconditionally (no Exists() guard, unlike Common.CurrentVersion.targets).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dfederm dfederm force-pushed the projref-targets-fixes branch from 8ca1587 to bab1fb4 Compare May 21, 2026 21:48
@dfederm
Copy link
Copy Markdown
Contributor Author

dfederm commented May 23, 2026

Note: This PR may be blocked until #13855 is merged. Some internal large repos have worked around this issue already by including their own <ProjectReferenceTarget> items and the duplication causes a geometric explosion in large graphs which #13855 fixes.

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