Closed 3F closed 5 years ago
Where did your PackageReferences come from (generated or manual) ? Pinging @nkolev92 , as I'm not the expert here.
FYI, here's what I tried without any issue:
Firstly, Microsoft.Build 15.9.20 depends on NETStandard 2.0.
And I had no issue adding this to my csproj:
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Build" Version="15.9.20" />
</ItemGroup>
Which generated this project.assets.json as expected:
"ClassLibrary1/1.0.0": {
"type": "project",
"framework": ".NETStandard,Version=v2.0",
"dependencies": {
"Microsoft.Build": "15.9.20"
},
"compile": {
"bin/placeholder/ClassLibrary1.dll": {}
},
"runtime": {
"bin/placeholder/ClassLibrary1.dll": {}
}
}
@donnie-msft Thank you for reply!
The problem exactly with other versions. As it was shown in my samples above.
I need to provide netstandard1.1 target platform if we will talk about more specific problem.
Today I still can't through PackageReference
at all. Only for old Reference
this is possible as you can see. Or try it by my examples from MvsSln or here above.
And this is it, Why in the nuget world only identical (according to the minimal version) target platforms are allowed?
Where did your PackageReferences come from (generated or manual) ?
manual.
But initially I was checking via package manager inside VS IDE if you ask.
Here is a complete example for your convenience.
Through PackageReference
- FAILED :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="15.9.20" />
</ItemGroup>
</Project>
D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3>dotnet build
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\ClassLibrary3.csproj : error NU1202: Package Microsoft.Build 15.9.20 is not compatible with netstandard1.1 (.NETStandard,Version=v1.1). Package Microsoft.Build 15.9.20 supports:
D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\ClassLibrary3.csproj : error NU1202: - net46 (.NETFramework,Version=v4.6)
D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\ClassLibrary3.csproj : error NU1202: - netcoreapp2.1 (.NETCoreApp,Version=v2.1)
D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\ClassLibrary3.csproj : error NU1202: - netstandard2.0 (.NETStandard,Version=v2.0)
Restore failed in 252.57 ms for D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\ClassLibrary3.csproj.
Build FAILED.
Through Reference
- Build succeeded:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\microsoft.build.15.9.20\lib\net46\Microsoft.Build.dll</HintPath>
<Private>True</Private>
</Reference>
<!-- MSB3277 -->
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<HintPath>..\packages\system.io.compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
</Project>
D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3>dotnet build
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 48.3 ms for D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\ClassLibrary3.csproj.
ClassLibrary3 -> D:\tmp\_Issues\MvsSln\netstd\ClassLibrary3\ClassLibrary3\bin\Debug\netstandard1.1\ClassLibrary3.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Through PackageReference - FAILED :
The package Microsoft.Build, 15.9.20 supports the following platofrms:
netcoreapp21 netstandard20 net46
Your project is netstandard11.
None of the package frameworks are compatible with netstandard11, so that's why the PackageReference install fails.
See https://nugettoolsdev.azurewebsites.net/5.3.0/framework-compatibility?project=netstandard1.1&package=netstandard2.0 for example.
Through Reference - Build succeeded:
Are you adding those references manually? Then you are merely bypassing NuGet's compatibility checks and there's no guarantee that your project will work at runtime.
Why is your project framework .NET Standard 1.1?
Then you are merely bypassing NuGet's compatibility checks and there's no guarantee that your project will work at runtime.
I fully understand this subset. I'm only describing the difference between coreclr impl and nuget restriction!
For example:
<PackageReference Include="Microsoft.Build" Version="16.3.0" />
error NU1202: Package Microsoft.Build 16.3.0 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package Microsoft.Build 16.3.0 supports:
error NU1202: - net472 (.NETFramework,Version=v4.7.2)
error NU1202: - netcoreapp2.1 (.NETCoreApp,Version=v2.1)
YES, technically API layer in netstandard2.0 is not complete for netcoreapp2.1 implementation. But my question still is not about this.
Moreover, in my example above I'm sure this will work at least for X components without problems after manual MSB3277 fixes.
I mean, it will be useful to be able to solve problems manually like for classical Reference
. However, as I understand, NuGet today still just drops any possible use through PackageReference
. This is what I'm talking about.
What about 16.3.0? just netcoreapp2.1. That is, I can't even for netstandard2.0. Microsoft.Build is just for good example. But this is not only about it.
Why is your project framework .NET Standard 1.1?
Because this is optimal for other related dependencies in today's MvsSln and its related projects.
Moreover, in my example above I'm sure this will work at least for X components without problems after manual MSB3277 fixes.
It's pure luck if it does work. You likely have a runtime that's net46 or higher.
Because this is optimal for other related dependencies in today's MvsSln and its related projects.
Then you should not take dependencies to assemblies that require higher versions of the framework. You will run into runtime problems at some point.
What about 16.3.0? just netcoreapp2.1. That is, I can't even for netstandard2.0. Microsoft.Build is just for good example. But this is not only about it.
That's up to the publisher of the Microsoft.Build package. They only work against the specified framework, it's on them to decide which frameworks their libraries need.
Unfortunately I'm not sure what the question is here.
The compatibility tree you are effectively building will lead to runtime failures at some point. PackageReference and NuGet in general (even packages.config will do the same thing if you try to install the package), will not allow this to happen. It's NuGet's job to not put consumers in situations where their projects will fail. Reference simply does not have as many validations as bringing a package through NuGet does.
Then you should not take dependencies to assemblies that require higher versions of the framework.
net472 -to-> netstandard2.0 ? okay
That's up to the publisher of the Microsoft.Build package.
Yes, of course +lot of other pkgs. Btw, just remembered this: https://github.com/microsoft/msbuild/issues/3581
It's NuGet's job to not put consumers in situations where their projects will fail.
Yeah, thanks again for my additional hours with an urgent fixes in our internal projects like for this and more: https://github.com/NuGet/Home/issues/1521
Reference simply does not have as many validations as bringing a package through NuGet does.
This is other story. I'm talking about this layers. And let's think for a moment when I will try to use local references together with nuget.
Unfortunately I'm not sure what the question is here.
The question was about difference in implementing restrictions. Or okay, just the Ways to solve specific targets manually via PackageReference (options to ignore nu1202 or to force re-targeting).
Unfortunately after almost 5 years I'm still sure for a vsSolutionBuildEvent and GetNuTool projects (that was appeared just to solve your "to not put consumers") at least for the cases like this.
An addition to related issue about partial compatibility of the dependencies that I also already mentioned here:
for projects below, the following direct reference are not needed. But NuGet dependency policy will add this anyway: https://github.com/dependabot/feedback/issues/259#issuecomment-508242665
Because if you really know what are you doing, you can even reduce some required references from you assembly while the dependent library will still reference even missing modules like dlls.
For projects such as vsSolutionBuildEvent it also adds lot of inconvenience to review and merge 100+ dep pkgs. But this is other issue. Just about incompatible ways for our compatibility.
net472 -to-> netstandard2.0 ? okay
That's ok, but you don't seem to be doing this. Your example has netstandard as the pivot and netstandard1.1 to net46 is not ok.
This is other story. I'm talking about this layers. And let's think for a moment when I will try to use local references together with nuget.
Can you be more specific what about the layers you have issues with? NuGet implements that specific table in its framework compatibility checks.
The question was about difference in implementing restrictions. Or okay, just the Ways to solve specific targets manually via PackageReference (options to ignore nu1202 or to force re-targeting).
Reference has been around for a very long time, way before NuGet was ever a thing. Ignoring NU1202 is not the right approach. NuGet cannot force anyone to retarget, but rather it merely spits out an error message saying why it could not resolve.
I apologize, I'm not sure what the overall ask is. :(
In the original part of the issue, you said NuGet does not allow you to match netstandard1.1 to net46,netcoreapp21, netstandard20 and that's expected. The NU1202 is warranted in this case.
That's ok, but you don't seem to be doing this.
error NU1202: Package Microsoft.Build 16.3.0 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package Microsoft.Build 16.3.0 supports:
error NU1202: - net472 (.NETFramework,Version=v4.7.2)
error NU1202: - netcoreapp2.1 (.NETCoreApp,Version=v2.1)
Microsoft.Build 16.3.0 is not compatible with netstandard2.0
-> NU1202: - net472
It seems like I missed it, sorry about that.
Now the package supports:
net472 and netcoreapp2.1
Both of those implement netstandard2.0, but they both have a wider set of APIs available as you said yourself.
netstandard2.0 is not compatible with net472 and netcoreapp2.1. The reverse is true, but not in that direction. https://nugettoolsdev.azurewebsites.net/5.3.0/framework-compatibility?project=netstandard2.0&package=net472.
Now, this mapping specifically is not a perfect match so NuGet will raise an error for every such incompatibility encountered.
In certain cases, NuGet allows authors to provide a fallback framework to get a partial match if possible. NuGet does not own this mapping, it's merely a fallback.
In .NET Core SDK 2.2400 the fallback from netstandard2.0 was net461 In .NET Core sdk 3.0.100, the fallback from netstandard2.0, is now all of the .NET Frameworks.
So if you install the latest SDK you would get the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>_8644</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="16.3.0" />
</ItemGroup>
</Project>
F:\test\8644> dotnet restore
F:\test\8644\8644.csproj : warning NU1701: Package 'Microsoft.Build 16.3.0' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework '.NETStandard,Version=v2.0'. This package may not be fully compatible with your project.
Restore completed in 1.39 sec for F:\test\8644\8644.csproj.
Hope this clears it up. Note that this is a fallback and that's why NU1701 is raised in this case. You still might have runtime issues.
There seems to be confusion around the "X to Y" reference.
.NET 4.7.2 projects "can use" netstandard2.0 assemblies. However, it is not the other way around.
Same for .NET Core 2.1. Both .NET Core 2.1 and .NET 4.7.2 contain more APIs than defined in .NET Standard 2.0, so a .NET Standard 2.0 project cannot use a .NET 4.7.2 or .NET Core 2.1 project/library. (There is a the mentioned fallback workaround for .NET Framework that is dangerous but possible, but will not work for most of MSBuild since it relies on app domains for the .NET Framework part)
Microsoft.Build was explicitly moved to .NET 4.7.2 to be in line with Visual Studio and the .NET Standard part was replaced with a .NET Core specific part to be able to use newer APIs to help with build times.
Sounds like something secret o_0
I don't see problems say for netfx -> netstandard-> netfx ...
Because in general, netstandard it's just ~API. Layer between specific impl.
.NET 4.7.2 projects "can use" netstandard2.0 assemblies.
Yes, of course, because netstd2 covers 472
However, it is not the other way around.
I already mentioned the possible ways above. But if you need again my full example, I'll try tomorrow. just /2 AM on my watch
I think the focus should be on:
However, it is not the other way around. I already mentioned the possible ways above.
What you've shown us are sort of "hacks" where we cannot guarantee no runtime problems.
When restoring netstandard => netfx, NuGet cannot know that it will later be referenced again by netfx, and it might just end up working by accident.
What if NuGet allows netstandard => netfx reference where later that package gets referenced by netcoreapp? Then the runtime would have issues.
There are scenarios where the customer and other tooling are aware of the risks and are willing to take them, so that's why AssetTargetFallback exists and that's why .NET Core 3.0 behaves in the way I suggested earlier.
I think I finally understand your scenario, and .NET Core 3.0 SDK already accounts for that.
Today I still can't through
PackageReference
at all. Only for oldReference
this is possible as you can see.
Perhaps some confusion here is from the fact that References have no validation applied to them. They sometimes accidentally work, even if they aren't explicitly compatible. You may or may not have a runtime error (you are lucky in that you're not having a runtime error).
PackageReference are always validated for TFM compatibility. Thus, you're seeing the error only when using references this way.
Perhaps some confusion here is from the fact that References have no validation applied to them
That's what I was talking about initially. If user still can reference something locally, Why not to provide additional options to be closer to CLR features.
You may or may not have a runtime error (you are lucky in that you're not having a runtime error).
A rocket science in action.
I think I finally understand your scenario,
It seems like. However, it would be nice to have an additional option for manual routes at some specific cases. Just as I said initially.
What you've shown us are sort of "hacks"
I understand your "job to not put consumers" and position with "hacks" because it really may be a big problem for common users. But again, sometimes these can be are a very important hacks like this https://github.com/3F/DllExport
And anyway, "to not put consumers" will never work for 100%. While the any options will just delegates responsibility to the end user.
and .NET Core 3.0 SDK already accounts for that.
I still did not look closer the just released .net core 3. Later I will look into together with important tasks for .NET DllExport. Looks like already soon. Hello to everyone who is still waiting for it. Almost ready to start review. ✋
because it really may be a big problem for common users.
AssetTargetFallback is the solution for not 100% compatible framework. It's something that can be provided by the user or otherwise.
Note that it's not recommended to stray away from the NuGet/SDK imposed restrictions, because if you end up shipping a package that bypasses NuGet/SDK restrictions it might not work for your customers and the tooling would not be able to tell that.
In the .NET Core 3.0 SDK there's a fallback that allows the selection of such assets, but they are not guaranteed to work, so that's why you get a warning.
Note that even the fallbacks are one studied and determined as "likely to work".
netstandard2.0 falling back to net461 is likely to work. netstandard1.1 to net461 will most likely not.
I'd suggest you try the .NET Core 3.0 SDK. :)
And anyway, "to not put consumers" will never work for 100%. While the any options will just delegates responsibility to the end user.
And you can bypass that by setting AssetTargetFallback at your own risk, but consider the risks if you end up shipping that project as a package, that the consumers' machines will not have the same compatibility mappings you did when you built the project. Your package might not even install. :)
Anyway, I'm marking this as a question, as I do not believe a change in the product is warranted here. This is by design and we believe AssetTargetFallback gives customers enough control if need be. Carefully consider if you end up publishing a package with a non-NuGet/SDK specified AssetTargetFallback.
Thanks for clarifying my question! I understood NuGet team with this issue, and partially(yet) I support it.
try the .NET Core 3.0 SDK
We will :) It was planned anyway.
Hi,
Can someone clarify NU1202 restriction? I still don't understand, Why this https://github.com/dotnet/standard/blob/master/docs/versions.md#net-standard-versions is not possible for nuget project?
Just for the cases like this https://github.com/3F/MvsSln/pull/21 and other?
Why/ if I can like this:
But not like this:
this:
but not just this:
Thanks,
// From 2015 (who remember me here) we're still actively using other ways with nuget packages due to some incomprehensible things like above.
And looks like I personally still will use my portable GetNuTool together with vsSolutionBuildEvent scripts. Just because this all works fine <_<