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

Microsoft.AspNetCore.Mvc and Copy Local on System Packages #3448

Open jbuckmccready opened 5 years ago

jbuckmccready commented 5 years ago

The Microsoft.AspNetCore.Mvc package on nuget brings in many dependencies, and those dependencies bring in their own dependencies, most of which are listed under ".NETStandard 2.0". Many of those dependencies are system libraries and paket install adds references for the library using the system path (e.g. C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.1\Facades\System.AppContext.dll for "System.AppContext" if using .NET 4.7.1 on Windows 7).

The problem is that paket also sets "Copy Local" to true for those system libraries even though they are not referenced locally at all and are not copied to the output directory - and this causes Visual Studio to think the project needs to be rebuilt to copy the library into the output directory (despite it being a no-op). This means when building any project all of the projects it depends on must be rebuilt that reference any of these system libraries with Copy Local set to true.

Example:

Project C depends on project B Project B depends on project A Project A has one of these system libraries (e.g. System.AppContext.dll) referenced and Copy Local set to true.

Now right-click->Build on Project C will cause all the projects to be rebuilt even if project A and B had just been built.

I know the Copy Local setting is what causes Visual Studio to perform the rebuild by setting the "MSBuild project build output verbosity" to "Diagnostic" under Visual Studio->Tools->Options->Projects and Solutions.

Setting Copy Local to false would possibly fix the issue but must be done on every single system library package explicitly (which for Microsoft.AspNetCore.Mvc is a lot of transitive dependencies - a pain to maintain).

AspNetCore.Mvc and paket are both very popular and I find it hard to believe everyone is being forced to rebuild all projects that depend on a project that depends on AspNetCore.Mvc due to this issue, is there something I am missing here?

forki commented 5 years ago

Can you please create such a project structure, zip it and upload here?

Am Do., 6. Dez. 2018, 02:29 hat Jedidiah Buck McCready < notifications@github.com> geschrieben:

The Microsoft.AspNetCore.Mvc https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc/ package on nuget brings in many dependencies, and those dependencies bring in their own dependencies, most of which are listed under ".NETStandard 2.0". Many of those dependencies are system libraries and paket install adds references for the library using the system path (e.g. C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.1\Facades\System.AppContext.dll for "System.AppContext" if using .NET 4.7.1 on Windows 7).

The problem is that paket also sets "Copy Local" to true for those system libraries even though they are not referenced locally at all and are not copied to the output directory - and this causes Visual Studio to think the project needs to be rebuilt to copy the library into the output directory (despite it being a no-op). This means when building any project all of the projects it depends on must be rebuilt that reference any of these system libraries with Copy Local set to true.

Example:

Project C depends on project B Project B depends on project A Project A has one of these system libraries (e.g. System.AppContext.dll) referenced and Copy Local set to true.

Now right-click->Build on Project C will cause all the projects to be rebuilt even if project A and B had just been built.

I know the Copy Local setting is what causes Visual Studio to perform the rebuild by setting the "MSBuild project build output verbosity" to "Diagnostic" under Visual Studio->Tools->Options->Projects and Solutions.

Setting Copy Local to false would possibly fix the issue but must be done on every single system library package explicitly (which for Microsoft.AspNetCore.Mvc is a lot of transitive dependencies - a pain to maintain).

AspNetCore.Mvc and paket are both very popular and I find it hard to believe everyone is being forced to rebuild all projects that depend on a project that depends on AspNetCore.Mvc due to this issue, is there something I am missing here?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/fsprojects/Paket/issues/3448, or mute the thread https://github.com/notifications/unsubscribe-auth/AADgNKVWXFEMAW_FHlsPb3DsN7736QLXks5u2HMAgaJpZM4ZFpFD .

jbuckmccready commented 5 years ago

OK I made a minimal reproducing example, it has three projects with ProjectC depending on ProjectB and ProjectB depending on ProjectA. Here's what I determined in testing:

  1. With ProjectA referencing Microsoft.AspNetCore.Mvc and ProjectA set to output xml documentation then right-click->build on ProjectC causes all three projects to be rebuilt (Visual Studio/MSBuild determines that ProjectC must be rebuilt because ProjectB must be rebuilt because ProjectA was rebuilt, and ProjectA was rebuilt due to Copy Local on System.AppContext).
  2. With ProjectA referencing Microsoft.AspNetCore.Mvc and ProjectA NOT set to output xml documentation then right-click->build on ProjectC causes only ProjectA to be rebuilt (Visual Studio/MSBuild determines ProjectA must be rebuilt due to Copy Local on System.AppContext but that it is unchanged so then ProjectB and ProjectC are not rebuilt).
  3. With ProjectA not referencing Microsoft.AspNetCore.Mvc then right-click->build on ProjectC builds the first time but then never has to rebuild after that unless files in the projects change (the expected behavior).

Here's the minimal example: RebuildProblemExample.zip

The example has xml doc output on for ProjectA, you can turn it off by going to the properties on the project under the "Build" tab under "Output".

Does it make sense that paket should not set "Copy Local" to true for packages it finds in a common system path when it adds the reference to the project? System.AppContext.dll is never copied to the project output bin directory on my system but the executable finds the dll OK when it runs.

jbuckmccready commented 5 years ago

As I suspected one work around is to add copy_local: false to all the system packages that path to the .net 4.7.1 system path. This is what I had to add to the paket.references file that references Microsoft.AspNetCore.Mvc:

System.AppContext copy_local: false
System.Console copy_local: false
System.Diagnostics.FileVersionInfo copy_local: false
System.IO copy_local: false
System.IO.FileSystem copy_local: false
System.IO.FileSystem.Primitives copy_local: false
System.Linq copy_local: false
System.Linq.Expressions copy_local: false
System.Reflection copy_local: false
System.Diagnostics.StackTrace copy_local: false
System.Runtime copy_local: false
System.Runtime.Extensions copy_local: false
System.Runtime.InteropServices copy_local: false
System.Runtime.InteropServices.RuntimeInformation copy_local: false
System.Security.Cryptography.Algorithms copy_local: false
System.Security.Cryptography.Encoding copy_local: false
System.Security.Cryptography.Primitives copy_local: false
System.Security.Cryptography.X509Certificates copy_local: false
System.Threading.Thread copy_local: false
System.Xml.ReaderWriter copy_local: false
System.Xml.XmlDocument copy_local: false
System.Xml.XPath copy_local: false

NOTE: I had to add this to the paket.references file for each project that references Microsoft.AspNetCore.Mvc, adding the above to the paket.dependencies file had no effect (and did not error).