Skip to content

[Regression] .NET 6 SDK will no longer copy the netstandard facades to the publish directory for net461 apps #18101

@joperezr

Description

@joperezr

cc: @dsplaisted @marcpopMSFT @andschwa @ericstj

Repro Steps

  1. Create a new netstandard lib
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

</Project>
  1. Create a new net461 Console app that references it:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net461</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\reproLib\reproLib.csproj" />
  </ItemGroup>

</Project>
  1. Publish the project with dotnet publish

Expected
Because the net461 project is referencing a netstandard library, tooling should inject all of the netstandard facades onto the publish directory to ensure the application will be able to run as expected. This is what happens with .NET 5.0 and previous sdks.

Actual
bin directory does get the facades injected, but the publish directory won't when you use a 6.0 SDK, which means that if the app tries to run in a machine that only has .NET 461 installed, the app will likely crash at runtime.

Problem

I took a look and the issue here seems to be caused by this change which basically changed the way we calculate the items to be copied to the publish directory and added an additional filter to check if the ResolveCopyLocal item had the Private metadata set to false. When we are injecting the netstandard facades to resolveCopyLocal item, we explicitly set Private to false, which is why they are now all getting excludded from the publish directory. Here is where we set the metadata to false and the explanation of why we do it:

<ItemGroup Condition="'@(_NETStandardLibraryNETFrameworkLib)' != ''">
<!-- Put each facade assembly in two separate items: Reference with Private set to false, which means it won't be
copied locally, and ReferenceCopyLocalPaths, which will be copied locally. The reason for this split is to
workaround https://github.com/dotnet/core-setup/issues/2981 by ensuring that the facades are written
to the deps.json with a type of "referenceassembly" instead of "reference".
The exception is netfx.force.conflicts.dll, which shouldn't be copied local. So it isn't included in
ReferenceCopyLocalPaths.
When we add the Reference items, we use the simple name as the ItemSpec, and refer to the full path
to the DLL via the HintPath metadata. This is so that if we're replacing a simple Reference,
the OriginalItemSpec of the resolved reference will match to the Reference that was replaced,
and VS won't show a warning icon on the reference. See https://github.com/dotnet/sdk/issues/1499
-->
<ReferenceCopyLocalPaths Include="@(_NETStandardLibraryNETFrameworkLib)" Condition="'%(FileName)' != 'netfx.force.conflicts'">
<Private>false</Private>
</ReferenceCopyLocalPaths>

This regression has a potential of great impact, so we should consider how we can fix it before 6.0 ships, whether the solution is to not set Private item to false or if the solution is instead to change the new filter on the publish items.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions