msbuild icon indicating copy to clipboard operation
msbuild copied to clipboard

ProjectReference transitive dependencies

Open joeltankam opened this issue 6 years ago • 9 comments

Steps to reproduce

Let's consider these 3 project files :

ProjectA

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net471</TargetFramework>
  </PropertyGroup>
</Project>

ProjectB

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net471</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\ProjectA\ProjectA.csproj" />
  </ItemGroup>
</Project>

ProjectC

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net471</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\ProjectB\ProjectB.csproj" />
  </ItemGroup>
</Project>

The 3 projects depends on each other as follows : ProjectC -(depends on)-> ProjectB -> ProjectA

Expected behavior

ProjectC should not be able to use elements from ProjectA (public classes for example) since it doesn't reference this project directly.

Actual behavior

ProjectC has access to ProjectA via transitivity as it can be seen in his assets file :

{
      ...
      "ProjectA/1.0.0": {
        "type": "project",
        "framework": ".NETFramework,Version=v4.7.1",
        "compile": {
          "bin/placeholder/ProjectA.dll": {}
        },
        "runtime": {
          "bin/placeholder/ProjectA.dll": {}
        }
      },
      "ProjectB/1.0.0": {
        "type": "project",
        "framework": ".NETFramework,Version=v4.7.1",
        "dependencies": {
          "ProjectA": "1.0.0"
        },
        "compile": {
          "bin/placeholder/ProjectB.dll": {}
        },
        "runtime": {
          "bin/placeholder/ProjectB.dll": {}
        }
      }
      ...
}

As mentioned in https://github.com/dotnet/project-system/issues/2313, it appears that this behavior can be cancelled by using PrivateAssets, from PackageReference dependency assets, when referencing ProjectA :

  <ItemGroup>
    <ProjectReference Include="..\ProjectA\ProjectA.csproj" PrivateAssets="all" />
  </ItemGroup>

Using ExcludeAssets when referencing ProjectB also works :

  <ItemGroup>
    <ProjectReference Include="..\ProjectB\ProjectB.csproj" ExcludeAssets="all" />
  </ItemGroup>

However, these metadatas are originally applicable only for PackageReference and I can't find any documentation of this behavior for ProjectReference (in the ProjectReference item reference for example). So, should this (PrivateAssets or ExcludeAsssets) be really used in ProjectReference tag ?

Environment data

msbuild /version output: 15.9.21.664 Visual Studio : Professional 2017, version 15.9.15

joeltankam avatar Sep 11 '19 09:09 joeltankam