The Project System needs a way to know the correct SupportedTargetFrameworks for WinForms and WPF projects so we can display the correct TFM's in the property pages.
Is it possible that this can be done on the SDK side?
https://github.com/dotnet/project-system/issues/5010
cc @nguerrera
cc @vatsan-madhavan @rladuca
cc @dsplaisted
Today we have a static list of supported TFMs here:
What I'm thinking is that the WindowsDesktop SDK could override this somehow to remove the target frameworks that it doesn't support.
Simplest form of that would be to do some Removes
but then I think we want no versions of .NET Standard to be supported, and then we'd have a maintenance problem when say .NETStandard 2.2 came out and wasn't yet removed.
Another way would be for WindowsDesktop SDK to remove all and have its own fixed allow-list. But then it is in the business of taking an update for every version.
Finally, we could make the list above dynamic based on whether the WindowsDesktop SDK has set certain props.
What do you all think would be best?
I don't understand the request for the SDK.
We already have logic for handling TFM < 3.0 && TargetFrameworkIdentifier==.NETCoreApp. What specifically is being requested here?
See _WindowsDesktopFrameworkRequiresVersion30 - currently there is a warning shown when someone tries to use WindowsDesktop SDK and sets TFM < netcoreapp3.0
Today we have a static list of supported TFMs here:
https://github.com/dotnet/sdk/blob/master/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.SupportedTargetFrameworks.props
Simplest form of that would be to do someRemoves
but then I think we want no versions of .NET Standard to be supported, and then we'd have a maintenance problem when say .NETStandard 2.2 came out and wasn't yet removed.
Spoke too soon.. thanks for the context.
The request is that the list of SupportedTargetFramework: https://github.com/dotnet/sdk/blob/master/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.SupportedTargetFrameworks.props
not include target frameworks that aren't supported by windows desktop projects. VS uses these items to populate a retargeting drop-down in property pages.
Remove
-ing these is easy, and doesn't pose maintainability problems.
<SupportedTargetFramework Include=".NETCoreApp,Version=v1.0" DisplayName=".NET Core 1.0" />
<SupportedTargetFramework Include=".NETCoreApp,Version=v1.1" DisplayName=".NET Core 1.1" />
<SupportedTargetFramework Include=".NETCoreApp,Version=v2.0" DisplayName=".NET Core 2.0" />
<SupportedTargetFramework Include=".NETCoreApp,Version=v2.1" DisplayName=".NET Core 2.1" />
<SupportedTargetFramework Include=".NETCoreApp,Version=v2.2" DisplayName=".NET Core 2.2" />
I would expect 3.0+ .NETCoreApp
TFM's to be supported.
If we don't want any version of .NETStandard
to be supported, is there a way we can Remove
them all without having to run a Target
? That would probably be the easiest thing to do... For e.g., if we could coordinate a change with dotnet/sdk and have it define @(_NetStandardSupportedTargets)
in Microsoft.NET.SupportedTargetFrameworks.props
, we could probably use that and easily eliminate .NET Standard TFM's.
Thoughts?
How come this list doesn't include .NETFramework
items? Is that because SDK-style projects "work with, but don't support" .NET Framework?
Good question about .NET Framework. I suppose that is why. @davkean?
I think I like where you were going we could have this:
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.0" DisplayName=".NET Core 1.0" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.1" DisplayName=".NET Core 1.1" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.0" DisplayName=".NET Core 2.0" />
<!-- etc. -->
<SupportedNETStandardTargetFramework Include=".NETStandard,Version=1.0" DisplayName=".NET Standard 1.0" />
<! -- etc. -->
<SupportedTargetFramework Include="@(SupportedNETCoreTargetFramework);@(SupportedNETStandardTargetFramework)" />
Another idea would be to set the metadata with the TargetFrameworkIdentifier and Version separated. I think this would let you do the removes with conditions that match all .NET Standard, though I have to check what is possible in evaluation here. We can't use a target for any of this.
I don't think metadata will work - though I wish that it did.
<!-- Microsoft.NET.Build.Tasks/targets/Microsoft.NET.SupportedTargetFrameworks.props -->
<!-- .NET Standard -->
<ItemGroup>
<SupportedTargetFramework Include=".NETStandard,Version=v1.0" DisplayName=".NET Standard 1.0" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v1.1" DisplayName=".NET Standard 1.1" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v1.2" DisplayName=".NET Standard 1.2" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v1.3" DisplayName=".NET Standard 1.3" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v1.4" DisplayName=".NET Standard 1.4" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v1.5" DisplayName=".NET Standard 1.5" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v1.6" DisplayName=".NET Standard 1.6" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v2.0" DisplayName=".NET Standard 2.0" TargetFrameworkIdentifier=".NETStandard" />
<SupportedTargetFramework Include=".NETStandard,Version=v2.1" DisplayName=".NET Standard 2.1" TargetFrameworkIdentifier=".NETStandard" />
</ItemGroup>
<!-- WindowsDesktop SDK props -->
<ItemGroup>
<SupportedTargetFramework Remove="@(SupportedTargetFramework0)" Condition="'%(TargetFrameworkIdentifier)'=='.NETStandard'" />
</ItemGroup>
error MSB4191: The reference to custom metadata "TargetFrameworkIdentifier" at position 1 is not allowed in this condition "'%(SupportedTargetFramework.TargetFrameworkIdentifier)'=='.NETStandard'"
We should probably do this, IMO, like you described above:
Microsoft.NET.Build.Tasks/targets/Microsoft.NET.SupportedTargetFrameworks.props
<!-- .NET Core -->
<ItemGroup>
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.0" DisplayName=".NET Core 1.0" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.1" DisplayName=".NET Core 1.1" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.0" DisplayName=".NET Core 2.0" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.1" DisplayName=".NET Core 2.1" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.2" DisplayName=".NET Core 2.2" />
<SupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v3.0" DisplayName=".NET Core 3.0" />
</ItemGroup>
<!-- .NET Standard -->
<ItemGroup>
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.0" DisplayName=".NET Standard 1.0" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.1" DisplayName=".NET Standard 1.1" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.2" DisplayName=".NET Standard 1.2" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.3" DisplayName=".NET Standard 1.3" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.4" DisplayName=".NET Standard 1.4" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.5" DisplayName=".NET Standard 1.5" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v1.6" DisplayName=".NET Standard 1.6" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v2.0" DisplayName=".NET Standard 2.0" />
<SupportedNETtandardTargetFramework Include=".NETStandard,Version=v2.1" DisplayName=".NET Standard 2.1" />
</ItemGroup>
<ItemGroup>
<SupportedTargetFramework Include="@(SupportedNETCoreAppTargetFramework);@(SupportedNETtandardTargetFramework)" />
</ItemGroup>
Microsoft.NET.Sdk.WindowsDesktop.props
<ItemGroup>
<SupportedNETCoreAppTargetFramework Remove=".NETCoreApp,Version=v1.0" />
<SupportedNETCoreAppTargetFramework Remove=".NETCoreApp,Version=v1.1" />
<SupportedNETCoreAppTargetFramework Remove=".NETCoreApp,Version=v2.0" />
<SupportedNETCoreAppTargetFramework Remove=".NETCoreApp,Version=v2.1" />
<SupportedNETCoreAppTargetFramework Remove=".NETCoreApp,Version=v2.2" />
<SupportedTargetFramework0 Remove="@(SupportedNETtandardTargetFramework)" />
</ItemGroup>
That works for me.
(I assume the 0 in SupportedTargetFramework0 is a typo.)
That works for me.
(I assume the 0 in SupportedTargetFramework0 is a typo.)
yeah, typo ...
@davkean Any concerns here? Shall we go ahead?
Do we need a separate issue to puzzle out whether to add .NETFramework
to SupportedTargetFramework
items in _Microsoft.NET.Build.Tasks/targets/Microsoft.NET.SupportedTargetFrameworks.props_ ?
Unless we have documented it as unsupported, I'm starting to think that it ought to be supported.
The very first example at How to: Use MSBuild project SDKs shows how to target .NET 4.6 using SDK style project. Additions to the csproj format for .NET Core also describes how to leverage it for .NET Framework. These seem to suggest strongly that the SDK style projects are both supported and encouraged for use by .NET Framework projects.
I assume the project system doesn't use this data for .NET Framework and instead looks in a more classical place for versions of .NET Framework to offer. I'm fine adding it, but if it's not going to be used, it doesn't seem to be high priority.
I assume the project system doesn't use this data for .NET Framework and instead looks in a more classical place for versions of .NET Framework to offer.
If the project system doesn't use it, then I agree that it doesn't matter. We should probably add a comment that .NET Framework is missing because the project system doesn't use it...
.NET Framework is supported by us. In fact, ASP.NET Core 1.x, 2.x projects could even target .NET Framework from File -> New Project.
It already shows the full list:
It is quite possible that the oldest ones in that list don't work so maybe we should get them out of there?
It is quite possible that the oldest ones in that list don't work so maybe we should get them out of there?
If the project system used SupportedTargetFrameworks, this would be so easy ;-)
We can use it for desktop, assuming you won't return < .NET Framework 3.0 for WPF/~WInForms~? It would be great if you return all of the TFMs from all frameworks so that we can switch between .NET Framework -> .NET Core as we've had quite a few bugs on this.
@davkean OK, we can add supported .NET Framework TFMs with the same pattern and WindowsDesktop can remove accordingly there too.
So you're good with this plan?
Yep, does this overlap with the existing infrastructure we already use to retrieve the frameworks?
We can use it for desktop, assuming you won't return < .NET Framework 3.0 for WPF/~WInForms~?
Why not WinForms?
WinForms is supported on .NET Framework 2.0.
Ah, got it. We have the right rules in place for WinForms for that in WindowsDesktop SDK.
@nguerrera We should see if we can do this correctly for WindowsDesktop.WindowsForms (netfx 2.0+) vs. WindowsDesktop.WPF vs. WindowsDesktop (same as WPF).
What's the state of this? Is this ready to be consumed?
Not yet. We have approval to go ahead. I'm a bit slammed on more critical issues. @livarcocc can you possibly see if someone else can pick this up?
I'll go ahead with implementing this in the SDK.
I assume WindowsDesktop would want this in their props (for completeness):
<ItemGroup>
<_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.0" />
<_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.1" />
<_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.0" />
<_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.1" />
<_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.2" />
<_UnsupportedNETStandardTargetFramework Include="@(SupportedNETStandardTargetFramework)" />
<SupportedNETCoreAppTargetFramework Remove="@(_UnsupportedNETCoreAppTargetFramework)" />
<SupportedNETStandardTargetFramework Remove="@(_UnsupportedNETStandardTargetFramework)" />
<SupportedTargetFramework Remove="@(_UnsupportedNETCoreAppTargetFramework);@(_UnsupportedNETStandardTargetFramework)" />
</ItemGroup>
I've created PR #3516 for the SDK side of the changes.
Nice!
We have to obviously wait until an SDK containing this change flows into dotnet/wpf - which can be a few hours or a few days...
I've verified my suggestion for the Windows Desktop props above with VS (16.3 preview). With both the SDK change and that one, Visual Studio only shows netcoreapp3.0 in the drop down.
There was some discussion of adding supported .NET Framework to this above. But given that VS doesn't use that today, I think it is fine to do later. Should we open a separate issue to track that?
Ah I missed that part. I can add that to this change now rather than deferring that work.
Do we have a list of the expected supported .NET Framework TFs?
I don't know. I'm pretty sure older ones and client platform don't work. @dsplaisted Do we have a list?
I'm guessing we should use the same set as what was used for the full framework targeting packs as nupkgs? Where is that?
For WPF and WinForms, the .NET Framework support list can be found indirectly at https://github.com/dotnet/wpf/blob/8a234021a4e697f7e4999c282bde42d2473131f0/packaging/Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.props#L77.
In short,
The exact reference set varies from net30, net35 to net40, net45 etc. , but they are all supported all the way to net48.
dotnet
for TFM net40+dotnet
has trouble finding ref-assemblies for net30, net35. If they are supplied carefully in the projects, they build as well. (I tried this a while back but did not check again now). I think it suffers from https://github.com/microsoft/msbuild/issues/1333There are corner cases that need some special handling. For e.g., if you try to use SplashScreen
with net30
, you'll get an build-error (unsupported), but those are small issues.
@nguerrera @dsplaisted I couldn't find references to any enumeration of valid .NET Framework target framework values in sdk/core-sdk. It seems if we can't locate the reference assemblies we just fail with The reference assemblies for .NETFramework,Version=vX.Y.Z were not found
.
Should I just add the corresponding TF values for https://dotnet.microsoft.com/download/dotnet-framework?
I have a PR out at https://github.com/dotnet/wpf/pull/1578. We will deal with netfx in another round... I don't want to hold the immediately-useful part of the work for the maybe-useful-in-the-future part of the work :-D
@nguerrera I've pushed https://github.com/dotnet/sdk/pull/3516/commits/13ab14b9d38b7be19ac59e650d8ed9b5abd28dc7 to the PR. If that's not what we want, I'll delete the commit.
We should have 3.0 too, right?
3.5 and 4.0 had Client Profile IIRC; is there a way to represent those? Does it matter?
3.0 doesn't appear in the project properties currently when I switch a .NET Core project to a .NET Framework TFM. Starts with 3.5.
Only 4.0 shows as "client profile" in the drop down. I don't think we represent it in the target framework, but perhaps it should be in the display name?
It doesn't work in SDK, but there was net40-client in NuGet. I would exclude it. I think it's ok to exclude some things that can be made to work with some workarounds and only show the things that will actually work when you pick them.
@nguerrera should we take the additional .NET Framework values commit in the SDK PR? Any requested changes (perhaps "client profile" in the 4.0 display name to match the project system)?
3.0 doesn't appear in the project properties currently when I switch a .NET Core project to a .NET Framework TFM. Starts with 3.5.
I think this may depend on what you have installed?
I get this:
Doh, that makes sense. How far back does the rabbit hole go?
The only versions I know of that are not in my screenshot are 1.0, 1.1, and 4.8. I think we can ignore 1.x for sure.
The client profiles don't work, so let's definitely exclude those.
If I pick them:
Severity Code Description Project File Line Suppression State
Error NETSDK1013 The TargetFramework value 'net40-client' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. t C:\Program Files\dotnet\sdk\3.0.100-preview8-013640\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.TargetFrameworkInference.targets 93
Ok, I'll add 2.0 and 3.0 then and we'll not add any client profile versions.
https://support.microsoft.com/en-us/help/17455/lifecycle-faq-net-framework
netfx 2.0 is the oldest supported value. My 2c - I don鈥檛 think we should consider something older than even that.
Currently the dropdown is at least partially based on what targeting packs you have installed (there are no targeting packs for .NET 2.0 and 3.5 though). I think the static list you currently have is fine though, and will be better once we update the SDK to implicitly reference the targeting pack NuGet packages as needed.
When this is in, can you file an issue on dotnet/project-system to actually consume the .NET Framework supported list?
I updated https://github.com/dotnet/wpf/pull/1578 to incorporate netfx tfm exclusions as well.
I've merged #3516 for the SDK side of the fix.