Document SetTargetFramework bin/obj clash on single-targeting ProjectReferences#853
Document SetTargetFramework bin/obj clash on single-targeting ProjectReferences#853ViktorHofer wants to merge 5 commits into
Conversation
…References Setting SetTargetFramework metadata on a ProjectReference to a non-multi-targeting project injects a path-neutral TargetFramework global property, forking a redundant project instance that shares the same OutputPath/IntermediateOutputPath as the solution-rooted build. The project is built twice, causing a bin/obj clash under parallel builds. Adds AP-23 to the msbuild-antipatterns catalog and a matching Common Causes and Fixes section plus global-properties note to the check-bin-obj-clash skill. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Skill Coverage Report
Uncovered:
|
There was a problem hiding this comment.
Pull request overview
This PR updates the dotnet-msbuild plugin documentation to explicitly warn against using SetTargetFramework metadata on ProjectReference items that point to single-targeting projects, because it can fork a redundant MSBuild project instance that writes to the same bin/ and obj/ paths and causes parallel-build clashes.
Changes:
- Adds a new msbuild anti-pattern (AP-23) documenting why
SetTargetFrameworkis harmful onProjectReferenceto single-targeting projects, with BAD/GOOD examples and guidance on when it is appropriate (multi-targeting only). - Updates the msbuild-antipatterns SKILL pointer and quick-reference checklist to include AP-23.
- Extends
check-bin-obj-clashdocumentation with a new “Common Causes and Fixes” subsection for this scenario and clarifies theTargetFrameworkglobal-property table row with the single-targeting exception.
Show a summary per file
| File | Description |
|---|---|
| plugins/dotnet-msbuild/skills/msbuild-antipatterns/SKILL.md | Updates the “additional anti-patterns” pointer to include AP-23. |
| plugins/dotnet-msbuild/skills/msbuild-antipatterns/references/additional-antipatterns.md | Adds AP-23 documentation and includes it in the quick-reference checklist. |
| plugins/dotnet-msbuild/skills/check-bin-obj-clash/SKILL.md | Documents SetTargetFramework→single-targeting ProjectReference as a common bin/obj clash cause; updates global-property notes for TargetFramework. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 0
|
/evaluate |
Skill Validation Results
[1] Model: claude-opus-4.6 | Judge: claude-opus-4.6 🔍 Full Results - additional metrics and failure investigation steps
▶ Sessions Visualisation -- interactive replay of all evaluation sessions |
Refine AP-23 and the check-bin-obj-clash guidance to reflect two additional cases: (1) the clash only occurs when the injected TFM equals the single-targeting project's own TFM (path-neutral); injecting a DIFFERENT TFM changes the output path and is a valid override, and (2) for framework-incompatible references (e.g. .NETFramework test project -> single-targeting .NETCoreApp), SkipGetTargetFrameworkProperties=true and ReferenceOutputAssembly=false are also required. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SkipGetTargetFrameworkProperties=true and ReferenceOutputAssembly=false are required whenever the referencing and referenced projects target incompatible frameworks, independent of single- vs multi-targeting and independent of SetTargetFramework. Decouple that rule from the SetTargetFramework override case in both AP-23 and the check-bin-obj-clash skill. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When SkipGetTargetFrameworkProperties=true bypasses P2P negotiation, the referencing project's TargetFramework global property can flow into a single-targeting referenced project and build it under the wrong TFM/output path. Guard with either SetTargetFramework (pin) or UndefineProperties=TargetFramework (strip), not both. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
check-bin-obj-clash: extend ClashTest with a single-targeting ToolLib and a ConsumerApp that references it with redundant same-TFM SetTargetFramework, forking a second ToolLib instance that builds to the same bin/obj (verified: ToolLib builds twice). Adds rubric items for identifying and fixing it. msbuild-antipatterns: LibB now references LibA with redundant same-TFM SetTargetFramework; adds a rubric item for detecting AP-23 in the static review scenario. Both eval.yaml and eval.vally.yaml updated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Skill Validation Results
[1] Model: claude-opus-4.6 | Judge: claude-opus-4.6 🔍 Full Results - additional metrics and failure investigation steps
▶ Sessions Visualisation -- interactive replay of all evaluation sessions |
|
✅ Evaluation passed for |
|
/evaluate |
Skill Validation Results
[1] (Plugin) Quality unchanged but weighted score is -3.7% due to: tokens (97914 → 171199) Model: claude-opus-4.6 | Judge: claude-opus-4.6 🔍 Full Results - additional metrics and failure investigation steps
▶ Sessions Visualisation -- interactive replay of all evaluation sessions |
|
✅ Evaluation passed for |
Summary
Documents that
SetTargetFrameworkmetadata must not be set on aProjectReferencepointing to a non-multi-targeting (single-targeting) project.Setting
SetTargetFramework="TargetFramework=<tfm>"on such a reference injectsTargetFrameworkas a global property on the referenced project. For a single-targeting project that property is path-neutral — the project already resolves tobin\<config>\<tfm>\/obj\<config>\<tfm>\on its own — so it does not change the output path; it only forks a distinct MSBuild project instance(project, {TargetFramework=<tfm>}). Meanwhile the solution/graph builds the same project as(project, {}). Both share the sameOutputPath/IntermediateOutputPath, so the project is built twice to the same location — a bin/obj clash under parallel builds.The P2P protocol itself correctly omits the
TargetFrameworkglobal property for non-multi-targeting references;SetTargetFrameworkoverrides that safe default and reintroduces the clash.Motivated by dotnet/sdk#55109 (review).
Changes
msbuild-antipatterns: new AP-23 with BAD/GOOD examples, mechanism, detection, and whenSetTargetFrameworkis legitimate (multi-targeting only); added to the quick-reference checklist; updated the SKILL.md pointer to "AP-16 through AP-23".check-bin-obj-clash: new "Common Causes and Fixes" subsection cross-referencing AP-23, a note on theTargetFrameworkrow in the global-properties table, and an extended USE FOR clause for discoverability.