Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting netstandard2.x platform specific target frameworks is causing unreasonable pain #64536

Closed
ViktorHofer opened this issue Jan 31, 2022 · 2 comments · Fixed by #64610
Closed

Comments

@ViktorHofer
Copy link
Member

ViktorHofer commented Jan 31, 2022

The toolchain (mostly NuGet) supports platform specific target frameworks since net5.0 but .NETStandard specific platform target frameworks never were and likely never will be supported (we asked the NuGet team and they refused because of technical limitations). During the migration from the old configuration system (which was TargetGroup based) to the Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk package (TargetFrameworks based) we had to trick NuGet to not see target framework platform overloads so that the toolchain doesn't raise errors. At that time, netstandard2.x wasn't the only tfm with a platform overload, others were netcoreapp2.x-, netcoreapp3.x-, netstandard1.x-, net46x-. We had to apply the mentioned trick (or better to say, hack) on every target framework in the TargetFrameworks property.

Nowadays, the only by the toolchain unsupported platform specific target frameworks still in use in our libraries are netstandard2.0 and netstandard2.1. The following libraries still make use of them:

  • Microsoft.Win32.Registry.AccessControl: netstandard2.0-windows;netstandard2.0
  • System.Data.OleDb: netstandard2.0-windows;netstandard2.0
  • System.IO.Ports: netstandard2.0-windows;netstandard2.0-Unix;netstandard2.0
  • System.Net.Http.WinHttpHandler: netstandard2.1-windows;netstandard2.1;netstandard2.0-windows;netstandard2.0
  • System.Runtime.Caching: netstandard2.0-windows;netstandard2.0
  • System.Security.Cryptography.Pkcs: netstandard2.1-windows;netstandard2.1;netstandard2.0-windows;netstandard2.0
  • System.Security.Cryptography.ProtectedData: netstandard2.0-windows;netstandard2.0
  • System.ServiceProcess.ServiceController: netstandard2.0-windows;netstandard2.0
  • System.Text.Encoding.CodePages: netstandard2.0-windows;netstandard2.0
  • System.Threading.AccessControl: netstandard2.0-windows;netstandard2.0

As .NETStandard will continue to be supported by libraries in dotnet/runtime for many years (just my own guess - nothing official), I would like to propose removing the netstandard2.x platform specific target frameworks, which aren't supported by the toolchain, from the above list.

The reason why I feel strongly about removing netstandard2.x platform specific target frameworks is because of the following inconveniences that exist because of the hack to satisfy the toolchain:

  • Visual Studio or any other toolchain that relies on the project-system can't restore solutions with platform specific netstandard2.x projects. Instead the restore must be intentionally disabled via a NuGet.config file per solution file, i.e.
    <!-- This disables restore in VS for projects that target platform specific target frameworks older than net5.0. -->

    That hack is only supported by static graph restore. A normal/legacy restore without static graph will blow up. Besides, any external component which isn't considered by the hack won't be able to interpret the overloaded target frameworks either. In general, the number of issues that have been opened because of IDEs not being able to interpret the overloaded target frameworks, strongly indicate unreasonable pain.
  • The sdk's AppendTargetFrameworkToOutputPath feature which is on by default had to be disabled and instead, OutputPath and IntermediateOutputPath had to be set manually to honor the stripped "suffix".
  • TargetPlatformIdentifier conditions, which is the recommended way to condition based on the platform specific tfms, can't be used in combination with netstandard2.x. In addition to that, the SDK defaults netstandard2.x's platform to Windows. As the TargetFramework "suffix" is stripped from netstandard2.x, we need to rely on a custom property TargetFrameworkSuffix to form conditions that should only apply to either the platform specific or the platform agnostic netstandard2.x tfm whenever both are present. This makes the already complex item conditions in our libraries even harder to read and write.

Alternatives like runtime checks which don't rely on platform specific netstandard2.x target frameworks should be explored, especially because of the number of projects that still use them is very low.

@ericstj @safern

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Jan 31, 2022
@ghost
Copy link

ghost commented Jan 31, 2022

Tagging subscribers to this area: @dotnet/area-infrastructure-libraries
See info in area-owners.md if you want to be subscribed.

Issue Details

The toolchain (mostly NuGet) supports platform specific target frameworks since net5.0 but .NETStandard specific platform target frameworks never were and likely never will be supported (we asked the NuGet team and they refused because of technical limitations). During the migration from the old configuration system (which was TargetGroup based) to the Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk package (TargetFrameworks based) we had to trick NuGet to not see target framework platform overloads so that the toolchain doesn't raise errors. At that time, netstandard2.x wasn't the only tfm with a platform overload, others were netcoreapp2.x-, netcoreapp3.x-, netstandard1.x-, net46x-. We had to apply the mentioned trick (or better to say, hack) on every target framework in the TargetFrameworks property.

Nowadays, the only platform specific target frameworks still in use in our libraries are netstandard2.0 and netstandard2.1. The following libraries still make use of them:

  • Microsoft.Win32.Registry.AccessControl: netstandard2.0-windows;netstandard2.0
  • System.Data.OleDb: netstandard2.0-windows;netstandard2.0
  • System.IO.Ports: netstandard2.0-windows;netstandard2.0-Unix;netstandard2.0
  • System.Net.Http.WinHttpHandler: netstandard2.1-windows;netstandard2.1;netstandard2.0-windows;netstandard2.0
  • System.Runtime.Caching: netstandard2.0-windows;netstandard2.0
  • System.Security.Cryptography.Pkcs: netstandard2.1-windows;netstandard2.1;netstandard2.0-windows;netstandard2.0
  • System.Security.Cryptography.ProtectedData: netstandard2.0-windows;netstandard2.0
  • System.ServiceProcess.ServiceController: netstandard2.0-windows;netstandard2.0
  • System.Text.Encoding.CodePages: netstandard2.0-windows;netstandard2.0
  • System.Threading.AccessControl: netstandard2.0-windows;netstandard2.0

As .NETStandard will continue to be supported by libraries in dotnet/runtime for many years (just my own guess - nothing official), I would like to propose removing the netstandard2.x platform specific target frameworks, which aren't supported by the toolchain, from the above list.

The reason why I feel strongly about removing netstandard2.x platform specific target frameworks is because of the following inconveniences that exist because of the hack to satisfy the toolchain:

  • Visual Studio or any other toolchain that relies on the project-system can't restore solutions with platform specific netstandard2.x projects. Instead the restore must be intentionally disabled via a NuGet.config file per solution file, i.e.
    <!-- This disables restore in VS for projects that target platform specific target frameworks older than net5.0. -->

    That hack is only supported by static graph restore. A normal/legacy restore without static graph will blow up. Besides, any external component which isn't considered by the hack won't be able to interpret the overloaded target frameworks either. In general, the number of issues that have been opened because of IDEs not being able to interpret the overloaded target frameworks, strongly indicate unreasonable pain.
  • The sdk's AppendTargetFrameworkToOutputPath feature which is on by default had to be disabled and instead, OutputPath and IntermediateOutputPath had to be set manually to honor the stripped "suffix".
  • TargetPlatformIdentifier conditions, which is the recommended way to condition based on the platform specific tfms, can't be used in combination with netstandard2.x. In addition to that, the SDK defaults netstandard2.x's platform to Windows. As the TargetFramework "suffix" is stripped from netstandard2.x, we need to rely on a custom property TargetFrameworkSuffix to form conditions that should only apply to either the platform specific or the platform agnostic netstandard2.x tfm whenever both are present. This makes the already complex item conditions in our libraries even harder to read and write.

Alternatives like runtime checks which don't rely on platform specific netstandard2.x target frameworks should be explored, especially because of the number of projects that still use them is very low.

@ericstj @safern

Author: ViktorHofer
Assignees: -
Labels:

area-Infrastructure-libraries

Milestone: -

@ericstj
Copy link
Member

ericstj commented Jan 31, 2022

I support a change here. @ViktorHofer -- the package/library lifecycle work you kicked off in 6.0 set the stage for this.
We don't get much value out of maintaining netstandard runtime specific implementations. We end up paying a very high cost (infra complexity, reduced surface area, cross-compiling) for supporting out-of-support frameworks and get little benefit of "open ended" framework compatibility of netstandard. We should just move the platform-specific implementations to the oldest in-support concrete framework.

That is not to say we can drop netstandard implementation completely. There is some generic benefit to this. Though we don't explicitly support it, folks do deploy netstandard implementations: roslyn-analyzers, MSBuild tasks, etc. So we should not remove all netstandard implementations if a package had them previously. I don't think dropping platform-specific netstandard implications will have any impact on this scenario.

@safern safern removed the untriaged New issue has not been triaged by the area owner label Feb 1, 2022
@safern safern added this to the 7.0.0 milestone Feb 1, 2022
ViktorHofer added a commit to ViktorHofer/runtime that referenced this issue Feb 1, 2022
Remove the remaining ten .NETStandard runtime specific implementations.
For reasoning please see dotnet#64536.
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Feb 1, 2022
ViktorHofer added a commit that referenced this issue Feb 1, 2022
* Remove .NETStandard runtime implementations

Remove the remaining ten .NETStandard runtime specific implementations.
For reasoning please see #64536.

* Remove infra support for NS platform specific tfms

Also cleaning-up some logic and stop disabling AppendTargetFramework.
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 1, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Mar 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants