dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.68k stars 1.06k forks source link

PackageReference with condition not being referenced by child project when multi-targeting #16611

Open yhvicey opened 3 years ago

yhvicey commented 3 years ago

Imaging there're two projects, Primary and Primary.Child:

<!-- Primary.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
  </ItemGroup>
  <ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
    <Reference Include="Microsoft.CSharp" />
  </ItemGroup>
</Project>
<!-- Primary.Child.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net452;net472;netcoreapp2.1</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
    <Reference Include="Microsoft.CSharp" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Primary\Primary.csproj" Condition="'$(TargetFramework)' == 'net452'">
      <SetTargetFramework>TargetFramework=net452</SetTargetFramework>
    </ProjectReference>
    <ProjectReference Include="..\Primary\Primary.csproj" Condition="'$(TargetFramework)' == 'net472'">
      <SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
    </ProjectReference>
    <ProjectReference Include="..\Primary\Primary.csproj" Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
      <SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
    </ProjectReference>
  </ItemGroup>
</Project>

And Microsoft.CSharp package (and its assemblies) is not being referenced when building Primary.Child.csproj (net472) referencing Primary.csproj (netstandard2.0):

// Source.cs in Primary.csproj
using Microsoft.CSharp.RuntimeBinder; // No error
// Use some types in Microsoft.CSharp.dll to make sure it won't be optimized
// Source.cs in Primary.Child.csproj
using Microsoft.CSharp.RuntimeBinder;
                       ^
                       // The type or namespace name 'RuntimeBinder' does not exist in the namespace 'Microsoft.CSharp' (are you missing an assembly reference?)
dotnet-issue-labeler[bot] commented 3 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

sfoslund commented 3 years ago

It looks like you're package reference is conditioned on netstandard2.0 but the child project is not targeting netstandard2.1, so I would expect that this is the cause. If not, can you provide a binlog reproducing the issue?

yhvicey commented 3 years ago

With SetTargetFramework I assume Primary.Child.csproj (net472) should be referencing Primary.csproj (netstandard2.0)? As net472 implemented netstandard2.0, will PackageReference be referenced in child project in such case?

Attached with a repro-able example as well as its binlog: Repro.zip

sanmuru commented 1 year ago

@yhvicey Any available solution now? In my case in dotnet/msbuild#8405, Main project do reference the output assembly of correct TFM from Child project, but the files that are copied to local are faulty. I think crew members fixed the reference bug but other tasks in MSBuild were not changed compatibly.

JanKrivanek commented 1 year ago

To supplement the info from @sanmuru - the SetTargetFramework="TargetFramework=netstandard2.0" seems to be ignored completely, the conditioned PackageReferences lead to identical packages resolution within project.asset.json for the root project regardless of the SetTargetFramework presence and its value.

JanKrivanek commented 1 year ago

This falls into scope of nuget - opening issue there: https://github.com/NuGet/Home/issues/12436