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 525 forks source link

Dependency resolution differences between .NET Core and Mono - project.assets.json apparently causing problems #2576

Open rmunn opened 7 years ago

rmunn commented 7 years ago

Description

The dependency resolution process in .NET Core appears to differ from what happens on Mono, which is causing problems with some packages (specifically in this case, the Suave.OAuth 0.9.0-pre2 package).

Repro steps

I don't yet know if this is reproducible on Windows, but I can reproduce this on Linux by the following method:

  1. Clone the https://github.com/fable-compiler/fable-suave-scaffold repo into a folder called withdotnet.
  2. While that clones, start a new Terminal tab or window. In the second tab, create an empty folder called withmono, a sister folder to withdotnet.
  3. In the withmono project, create a new Suave project from the Forge Suave template (I used Ionide in VS Code and chose "New Project" from the menu, then picked the Suave template). Project folder src, project name WithMono.
  4. While Forge is busy creating the withmono project, go to your first Terminal tab (in the withdotnet folder) and edit paket.dependencies. Add nuget Suave.OAuth prerelease to the dependencies. (Suave.OAuth first started supporting .NET Core in 0.9.0, which as of this writing is still a prelease version. If Suave.OAuth 0.9.0 is released by the time you repro this, you can skip the prerelease part of that line.)
  5. Also edit withmono/src/Server/paket.references and add Suave.OAuth to the references file.
  6. Make sure you have .NET Core 1.0.4 installed (for Ubuntu, it's in the dotnet-dev-1.0.4 package).
  7. Still in withdotnet, run mono .paket/paket.exe install to make sure the Suave.OAuth NuGet package dependencies are resolved and the paket.lock file is updated. (The ./build.sh script in the fable-suave-scaffold project just does a restore, not an install, so it will skip the Suave.OAuth package if you haven't done an install, and you won't trigger this bug).
  8. Still in withdotnet, run ./build.sh. This will take a while, so switch back to the other Terminal tab now.
  9. In withmono, edit paket.dependencies and src/WithMono/paket.references to add nuget Suave.OAuth prerelease and Suave.Oauth respectively, just as you did in the withdotnet project.
  10. In withmono, run .paket/paket.bootstrapper.exe to get Paket, then run .paket/paket.exe install to set up the paket.lock file.
  11. In withmono, run ./build.sh. You should see it succeed.
  12. Switch back to the withdotnet tab, which should have failed by now. Scroll up past the hundreds of "Error: ConnectFailure (Connection refused)" messages to find their cause: .NET Core is trying to load the Suave assembly version 2.0.0, but you have 2.1.1 (or later, depending on when you run this repro). See error message below:

Could not load file or assembly 'Suave, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

The root cause of this appears to be in the src/Server/obj/project.assets.json file, where Suave.OAuth is listed as having a dependency on Suave version 2.0.0. This comes from the Suave.OAuth.nuspec file, where the Suave dependency is indeed listed as being "2.0.0". However, the .nuspec specification says that a notation of "1.0" is the equivalent of "\<= 1.0". But the behavior of project.assets.json appears to be different: the fact that project.assets.json lists Suave.OAuth as having a dependency on "Suave": "2.0.0" is the only place I can find where this dependency could be coming from.

Expected behavior

The Suave dependency of "2.0.0" should be treated as in the .nuspec file, and a Suave version of 2.1.1 should satisfy the dependency.

Actual behavior

Under Mono (and I presume under .Net Framework as well), the expected behavior is what I get. But under .Net Core, I cannot get this to work.

Known workarounds

The only workaround I've found so far is to explicitly list Suave 2.0.0 in paket.dependencies under .NET Core. This makes MSBuild happy, because the assembly that it's loading matches the one referenced. But I'm not happy, because Suave 2.1 includes at least one very important security fix. I can use Suave 2.0.0 while developing, but I can't deploy that version of Suave.

Another workaround that I tried, but that failed, was to edit the project.assets.json file by hand and change the "Suave": "2.0.0" line to "Suave": ">= 2.0.0". But this edit was overwritten by Paket when I re-ran ,/build.sh, so that didn't work.

This is probably ultimately caused by a bug in .NET Core, but I have no idea how to create a repro that they will accept.

Possibly-related issues: #2208, #2497, and maybe others. And this could also be a PEBKAC issue: I am still very confused by .NET Core and its build system. The reason I used the fable-suave-scaffold project in my repro above is because the only way I've (so far) succeeded in building anything under .NET Core was to clone fable-suave-scaffold and build it. So I don't actually know how to create a smaller repro project that will demonstrate this problem.

forki commented 7 years ago

are the lock files different?

matthid commented 7 years ago

I cannot reproduce this on windows. Can you send the full output of a clean clone of ./build.sh. There might be some warnings in there when building which might give more insights.

matthid commented 7 years ago

OK I can reproduce, you need to clean again after adding the line to the references file. otherwise nuget thinks nothing has changed for some reason...

matthid commented 7 years ago

I don't think I have good news. AFAICS the following happens:

This means telling paket to generate binding redirects is not helping here.

matthid commented 7 years ago

Hm, I cannot reproduce this with a C# console application without paket :/

matthid commented 7 years ago

Oh this might be a F# Compiler bug :/

matthid commented 7 years ago

Reported upstream here

matthid commented 7 years ago

@rmunn Thanks for reporting this, seems like something which needs to be fixed asap...

matthid commented 7 years ago

Leaving this open because we need to warn or more likely error out if we detect this situation