sdk: The dotnet store is incorrectly including BCL assemblies when targeting .NET Core 3.1

Using the following store manifest that only includes Newtonsoft.Json

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
  </ItemGroup>
</Project>

I execute the following command to create a store for .NET Core 2.1:

dotnet store --manifest .\manifest.xml -f netcoreapp2.1 -o ./store2.1 -r linux-x64 --skip-optimization

the store artifact.xml contains only Newtonsoft.Json as expected.

<StoreArtifacts>
  <Package Id="Newtonsoft.Json" Version="9.0.1" />
</StoreArtifacts>

But then creating the store for .NET Core 3.1 using the command:

dotnet store --manifest .\manifest.xml -f netcoreapp3.1 -o ./store3.1 -r linux-x64 --skip-optimization

Creates a store with a lot of runtime and system dlls which bloat the package store and also those assembles fail to the store optimization.

<StoreArtifacts>
  <Package Id="Microsoft.CSharp" Version="4.0.1" />
  <Package Id="Newtonsoft.Json" Version="9.0.1" />
  <Package Id="runtime.any.System.Collections" Version="4.0.11" />
  <Package Id="runtime.any.System.Diagnostics.Tools" Version="4.0.1" />
  <Package Id="runtime.any.System.Globalization" Version="4.0.11" />
  <Package Id="runtime.any.System.IO" Version="4.1.0" />
  <Package Id="runtime.any.System.Reflection" Version="4.1.0" />
  <Package Id="runtime.any.System.Reflection.Extensions" Version="4.0.1" />
  <Package Id="runtime.any.System.Reflection.Primitives" Version="4.0.1" />
  <Package Id="runtime.any.System.Resources.ResourceManager" Version="4.0.1" />
  <Package Id="runtime.any.System.Runtime" Version="4.1.0" />
  <Package Id="runtime.any.System.Runtime.Handles" Version="4.0.1" />
  <Package Id="runtime.any.System.Runtime.InteropServices" Version="4.1.0" />
  <Package Id="runtime.any.System.Text.Encoding" Version="4.0.11" />
  <Package Id="runtime.any.System.Text.Encoding.Extensions" Version="4.0.11" />
  <Package Id="runtime.any.System.Threading.Tasks" Version="4.0.11" />
  <Package Id="runtime.unix.System.Diagnostics.Debug" Version="4.0.11" />
  <Package Id="runtime.unix.System.IO.FileSystem" Version="4.0.1" />
  <Package Id="runtime.unix.System.Private.Uri" Version="4.0.1" />
  <Package Id="runtime.unix.System.Runtime.Extensions" Version="4.1.0" />
  <Package Id="System.Dynamic.Runtime" Version="4.0.11" />
  <Package Id="System.IO.FileSystem.Primitives" Version="4.0.1" />
  <Package Id="System.Linq" Version="4.1.0" />
  <Package Id="System.Linq.Expressions" Version="4.1.0" />
  <Package Id="System.ObjectModel" Version="4.0.12" />
  <Package Id="System.Reflection.Emit" Version="4.0.1" />
  <Package Id="System.Reflection.Emit.ILGeneration" Version="4.0.1" />
  <Package Id="System.Reflection.Emit.Lightweight" Version="4.0.1" />
  <Package Id="System.Reflection.TypeExtensions" Version="4.1.0" />
  <Package Id="System.Runtime.Serialization.Primitives" Version="4.1.1" />
  <Package Id="System.Text.RegularExpressions" Version="4.1.0" />
  <Package Id="System.Threading" Version="4.0.11" />
  <Package Id="System.Threading.Tasks.Extensions" Version="4.0.0" />
  <Package Id="System.Xml.ReaderWriter" Version="4.0.11" />
  <Package Id="System.Xml.XDocument" Version="4.0.11" />
</StoreArtifacts>

This change in behavior seems to make the dotnet store command a broken experience.

@nguerrera We have talked about dotnet store in the past. Can you shed any light on why this is happening now?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 43 (22 by maintainers)

Most upvoted comments

@normj The NullReferenceException should be fixed in the 3.1.400 SDK release.

@niklr For the Lambda side the ball is in my court now to update the Lambda tooling to use the work around added in 3.1.400. I hope to get to that soon just juggling a few things right now. I think the issue is still worth leaving open as I think the current fix in 3.1.400 is a work around that requires users of the dotnet store command to do extra work and hopefully there will be a fix someday that doesn’t require any extra work.

Friendly ping on this to get some attention. This is breaking some of our scenarios for .NET Core 3.1.

@slavanap We’ve released a new patch. You can download 3.1.401 here: https://dotnet.microsoft.com/download/dotnet-core/3.1

@ppittle 3.1.400 will release together with Visual Studio 2019 version 16.7. I don’t think we’ve announced when that will be, but you can see the previews we’ve released so far here: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview

VS Mac 8.7 currently includes .NET 3.1.302.

I expect VS Mac 8.7 will at some point include .NET 3.1.400 since Visual Studio 2019 16.7 will be doing so.

This is a result of changes we made in .NET Core 3. We no longer use PackageReferences to represent .NET Core Framework. This is discussed here: https://github.com/dotnet/designs/pull/50

The old version of NewtonSoft.Json has dependencies to packages which are part of .NET Core. Because we don’t represent .NET Core as a PackageReference anymore, the dotnet store logic no longer knows to exclude them from the store.

The ideal fix to this would likely be https://github.com/NuGet/Home/issues/7344, and possibly additional changes in dotnet store to use it.

Possible workarounds:

  • Use a later version of NewtonSoft.Json (or in general, use packages that don’t have these older dependencies, which will generally be the case if the package was built for .NET Core 2.0 or .NET Standard 2.0 or higher).
  • Exclude each unneeded package from the manifest by adding the following
  <Target Name="AddPackagesToPrune" AfterTargets="PrepforRestoreForComposeStore">
    <ItemGroup>
      <PackagesToPrune Include="Microsoft.CSharp" />
      <PackagesToPrune Include="System.Collections" />
      <PackagesToPrune Include="System.Diagnostics.Debug" />
      <PackagesToPrune Include="System.Dynamic.Runtime" />
      <PackagesToPrune Include="System.Globalization" />
      <PackagesToPrune Include="System.IO" />
      <PackagesToPrune Include="System.Linq" />
      <PackagesToPrune Include="System.Linq.Expressions" />
      <PackagesToPrune Include="System.ObjectModel" />
      <PackagesToPrune Include="System.Reflection" />
      <PackagesToPrune Include="System.Reflection.Extensions" />
      <PackagesToPrune Include="System.Resources.ResourceManager" />
      <PackagesToPrune Include="System.Runtime" />
      <PackagesToPrune Include="System.Runtime.Extensions" />
      <PackagesToPrune Include="System.Runtime.Serialization.Primitives" />
      <PackagesToPrune Include="System.Text.Encoding" />
      <PackagesToPrune Include="System.Text.Encoding.Extensions" />
      <PackagesToPrune Include="System.Text.RegularExpressions" />
      <PackagesToPrune Include="System.Threading" />
      <PackagesToPrune Include="System.Threading.Tasks" />
      <PackagesToPrune Include="System.Xml.ReaderWriter" />
      <PackagesToPrune Include="System.Xml.XDocument" />
    </ItemGroup>
    <PropertyGroup>
      <PackagesToPrune>$(PackagesToPrune);@(PackagesToPrune)</PackagesToPrune>
    </PropertyGroup>
  </Target>

Note that if there is a PackageToPrune which is not part of the dependency graph, you will get a NullReferenceException from one of the tasks.