Skip to content

Behavioral inconsistency with BuildProjectReferences=false #4677

@dfederm

Description

@dfederm

Steps to reproduce

Download and unzip the following:
repro.zip

Scenario 1

  1. Navigate to c\
  2. Run msbuild
  3. Notice the contents of c\bin include a.txt, b.txt, c.txt
  4. Delete c\bin
  5. Run msbuild /p:BuildProjectReferences=false
  6. Notice the contents of c\bin include b.txt, c.txt. a.txt is missing!

Scenario 2

  1. Open repro.sln
  2. In VS, build the Solution
  3. Notice the contents of c\bin include a.txt, b.txt, c.txt
  4. Delete c\bin
  5. In VS, build just the C project
  6. Notice the contents of c\bin include b.txt, c.txt. a.txt is missing!

Root Cause

The root cause for this issue is because of the following:

  • Target GetCopyToOutputDirectoryItems is called on @(_MSBuildProjectReferenceExistent)
  • @(_MSBuildProjectReferenceExistent) is populated by the _SplitProjectReferencesByFileExistence target, which uses @(ProjectReferenceWithConfiguration)
  • @(ProjectReferenceWithConfiguration) is populated by the AssignProjectConfiguration target. However, the _SplitProjectReferencesByFileExistence does not declare that it depends on AssignProjectConfiguration!!!
  • When building a project, AssignProjectConfiguration happens to execute before _SplitProjectReferencesByFileExistence, so all is good.
  • When BuildProjectReferences=true, project references are recursively built so GetCopyToOutputDirectoryItems will have already been called on the project reference and the results would be cached
  • When BuildProjectReferences=false, project references are not recursively built so the recursive call to GetCopyToOutputDirectoryItems ends up calling _SplitProjectReferencesByFileExistence, which sees that @(ProjectReferenceWithConfiguration) is empty. Effectively this makes GetCopyToOutputDirectoryItems only go "1 level deep" when BuildProjectReferences=false

Other notes:

  • VS adds BuildProjectReferences=false, but because it uses the target result cache within the same build session, GetCopyToOutputDirectoryItems is cached from the dependencies and works correctly. However when building a specific project, the dependencies might not be built and thus would not be populated.
  • A possible fix is just to have _SplitProjectReferencesByFileExistence depend on AssignProjectConfiguration

Environment data

MSBuild version: 16
OS info: Win10

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions