fsprojects / Paket

A dependency manager for .NET with support for NuGet packages and Git repositories.
https://fsprojects.github.io/Paket/
MIT License
2.02k stars 520 forks source link

Paket generates odd binding redirects #3845

Open FilippoPolo opened 4 years ago

FilippoPolo commented 4 years ago

Description

When referencing MathNet.Symbolics, paket generates an assembly binding redirect for System.Runtime.Numerics to 4.0.2.0. I can't see any reason for this. MathNet.Symbolics uses 4.3.0.0. In fact, I don't even see that version of System.Runtime.Numerics on NuGet.

Repro steps

  1. Create a new F# class library project targeting netstandard2.0.
  2. Initialize paket, set redirects:on, and set it to reference MathNet.Numerics.
  3. Add an App.config file to the project.
  4. Run paket install.

This contains an example of the problem: test.zip

Expected behavior

I expect paket not to generate assembly binding redirects in this case. If they are needed, I expect the redirect for System.Runtime.Numerics to target 4.3.0.0.

Actual behavior

An assembly binding redirect is generated in app.config for System.Runtime.Numerics to a version that isn't referenced anywhere, and doesn't appear to even exist on NuGet. This may cause errors at later points.

Known workarounds

Disable redirects in paket, I suppose?

inosik commented 4 years ago

The version in the binding redirect is the assembly version, which isn't necessarily the same as the package version. System.Runtime.Numerics 4.3.0.0 has a binary for netstandard1.3, which has an assembly version of 4.0.2.0. So the binding redirect is correct.

Anyways, libraries don't need binding redirects. The final application does. See this question on SO: https://stackoverflow.com/questions/48377474/do-binding-redirects-in-app-config-for-class-libraries-do-anything

FilippoPolo commented 4 years ago

If the binding is correct, then why does the compiler emit MSB3277 "Found conflicts between different versions of the same dependent assembly that could not be resolved"?

Regarding redirects in libraries, the repro sample is simplified, but in the real case I have a large repository that includes both libraries and executables. They share a paket.dependencies file in the repository root. This file has redirects:on, so redirects are generated for all projects regardless of whether they are libraries or executables. Is there any way to tell paket to only generate redirects for executables?

inosik commented 4 years ago

It's hard to tell without seeing the full picture. Does the warning complain about this particular assembly? Does the project contain an App.config file? Does it contain an entry for this assembly? Which framework does the project target?

Paket should create binding redirects in any App.config file it finds. Maybe try to set redirects to force?

FilippoPolo commented 4 years ago

If it helps, the repro which is linked in the original post demonstrates the problem exactly.

To answer your questions:

I don't think setting redirects to force should make any difference. My problem isn't that redirects are absent; it's that they are wrong. If I delete them, the warning goes away. Just in case, I have tried switching to force, and I observed no difference.

inosik commented 4 years ago

It looks like MSBuild resolves to System.Runtime.Numerics 4.0.1.0, which is included in the .NET Standard, instead of the assembly in the System.Runtime.Numerics package (version 4.0.2.0), for which Paket generates the assembly redirect.

FilippoPolo commented 4 years ago

Interesting. If I run msbuild with verbose log, I find this:

Could not locate the assembly "System.Runtime.Numerics, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.

It looks like this causes MSBuild to fall back to 4.0.1.0, with the warning.

Any idea why it wouldn't find the assembly? It's a dependency of MathNet.Symbolics, so paket should have downloaded it somewhere?