-
Notifications
You must be signed in to change notification settings - Fork 822
Support .NET Standard 2.0 code generation #3215
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
Conversation
I checked the repro in https://github.com/dotnet/cli/issues/6863#issuecomment-309066947 by manually replacing the F# compiler binaries in the directory |
@cartermp This is a high priority change since F# support in the .NET 2.0 SDK is broken for .NET Standard 2.0 programming without it Currently we only have .NET Standard 1.x creation/consumption/testing in this repro. I will look at adding .NET Standard 2.0 testing, but the change is very important and I think it should likely be integrated faster. Do you know how we go about getting this into the .NET SDK? Does it draw from "master" or another branch? thanks |
@enricosada I finally understand what you mean about the dependency basis for .NET Standard 2.0 programming being manifestly much simpler. |
@@ -37,7 +37,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and | |||
|
|||
<PropertyGroup> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' " >mscorlib</TargetProfile> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' " >netcore</TargetProfile> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' AND ($(TargetFramework.StartsWith(netcoreapp1.)) OR $(TargetFramework.StartsWith(netstandard1.)))" >netcore</TargetProfile> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TargetFramework property is an alias. One can have a project where TargetFramework=Foo but map it to some real targetframework (see dotnet/project-system#1938 (comment) for an example of this). You could instead check that TargetFrameworkIdenitifier == .NETStandard.NETCore and TargetFrameworkVersion >= v2.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied this from further down in the existing file. So I should change all occurrences?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just looked at cases down the line and yes I think those should be modified too. TargetFramework is not even canonical - net46 and net4.6 both map to the same framework. So some of the checks below will be broken even for the regular cases. In general, we should avoid interpreting the targetframework property directly.
Note that if you need to do a bunch of version comparisons, you can do something like this and then msbuild lets you do direct integer comparisons - _TargetFrameworkVersionWithoutV > 2.0
@@ -37,7 +37,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and | |||
|
|||
<PropertyGroup> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' " >mscorlib</TargetProfile> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' " >netcore</TargetProfile> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' AND ($(TargetFramework.StartsWith(netcoreapp1.)) OR $(TargetFramework.StartsWith(netstandard1.)))" >netcore</TargetProfile> | |||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' AND !$(TargetFramework.StartsWith(netcoreapp1.)) AND !$(TargetFramework.StartsWith(netstandard1.))" >netstandard</TargetProfile> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also do you want the TargetProfile to be netstandard for netcoreapp2.0? I assume TargetProfile controls what core assembly is used? If so, the core assembly for netcoreapp2.0 is still System.Runtime.dll (netstandard.dll will simply type forward to System.Runtime in the reference assemblies set for netcoreapp2.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the core assembly for netcoreapp2.0 is still System.Runtime.dll
To double check - when you compile a netcoreapp2.0, you reference a System.Runtime.dll which contains an actual type definition for System.Object, not a forwarder? Yes, then in that case we want --targetprofile:netcore
. Thanks!
We should really get rid of the targetprofile
flag and infer it (we are much closer to doing that after this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes System.Runtime has the actual definition for System.Object in netcoreapp2.0 refs
@srivatsn Updated. Will do a manual test in a bit. |
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' AND ($(TargetFramework.StartsWith(netcoreapp1.)) OR $(TargetFramework.StartsWith(netstandard1.)))" >netcore</TargetProfile> | ||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' AND !$(TargetFramework.StartsWith(netcoreapp1.)) AND !$(TargetFramework.StartsWith(netstandard1.))" >netstandard</TargetProfile> | ||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' != '.NETFramework' " >netcore</TargetProfile> | ||
<TargetProfile Condition=" '$(TargetFrameworkIdentifier)' == '.NETStandard' AND '$(TargetFrameworkVersion)' >= 'v2.0'" >netstandard</TargetProfile> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will work - msbuild's >= only works if the string is an integer so you need to strip off the v from the version before doing the comparsion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srivatsn I switched to CompareTo on strings
@@ -53,7 +53,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and | |||
</PropertyGroup> | |||
|
|||
<PropertyGroup Condition=" '$(DisableImplicitSystemValueTupleReference)' != 'true' "> | |||
<_FrameworkNeedsValueTupleReference Condition=" $(TargetFramework.StartsWith(netcoreapp1.)) or $(TargetFramework.StartsWith(netstandard1.)) ">true</_FrameworkNeedsValueTupleReference> | |||
<_FrameworkNeedsValueTupleReference Condition=" ('$(TargetFrameworkIdentifier)' == '.NETStandard' or '$(TargetFrameworkIdentifier)' == '.NETCoreApp') and $(TargetFrameworkVersion.CompareTo("v2.0")) < 0 ">true</_FrameworkNeedsValueTupleReference> | |||
<_FrameworkNeedsValueTupleReference Condition=" '$(TargetFramework)' == 'net40' or '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'net461' or '$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'net47' ">true</_FrameworkNeedsValueTupleReference> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please change this line as well - It sounds like basically anything higher than 4.0
@srivatsn I updated the code to use _TargetFrameworkVersionWithoutV, could you double check again? thanks
I think it is anything up to 4.7 but not beyond. System.ValueTuple will be in the .NET framework after that. But we should double check while we're here |
@srivatsn @dsyme i think @KevinRansom said in #2983 (comment) we need
|
OK, this is ready, assuming it stays green. I've tested it manually with
on the .NET Standard 2.0 and .NET Core 2.0 project in the repro in https://github.com/dotnet/cli/issues/6863#issuecomment-309066947 I don't believe we can add automated testing until @KevinRansom is back online and helps bring in the .NET Core 2.0 runtime and .NET Standard 2.0 libraries. It depends on what F# project compilation testing is already in place for the .NET SDK build and test. |
@dsyme about testing i'll try to send here a PR tomorrow. I also sent dotnet/cli#6914 to cli, with same repro of @ncave of https://github.com/dotnet/cli/issues/6912 |
@dsyme @enricosada I can confirm this PR fixes dotnet/cli#6912. Thanks @dsyme! |
@dsyme this PR may be quite a bit bigger than is necessary. Some of the changes here I have in a separate PR related to getting FSI working on FSI. Anyway I am working on this, I don't think we need a netstandard option. I expect that we will deprecate the netcore too fairly quickly, now that we no longer build portable libraries. FSC works fine on netstandard 2.0 too if you do what we do for dotnetcli. And yes it is supported, C# uses the same trick and is likely to continue using for the forseeable future. Since the fsharp.net sdk redeploys the compiler in the FSharp.Compiler.Tools nuget package, just replace the two .json files there to unblock it. FSI does require a couple of changes to work on dotnet 2.0, because apparently we rely on a bug that was fixed, that causes us to stack overflow. The thing stopping me checking in my fixes are that I am struggling to rework the testing, and other stuff that keeps cropping up. Kevin |
@dsyme ... Hmmm you merged it? |
@KevinRansom AFAICS it's the right change now that "netstandard.dll" replaces "mscorlib.dll" and "System.Runtime.dll" when generating .NET Standard 2.0 libraries. At least I don't see anything else we can do. I do agree that wee should be able to get rid of the
The rest of the PR is just removing very crazy old checks about mscorlib versions being less than "4" - they are dangerous cruft now that the "netstandard" library uses version number 2.0.0.0 Let me know if you have trouble integrating. |
@KevinRansom give me a ping later on if you want to discuss |
See https://github.com/dotnet/cli/issues/6863#issuecomment-309066947
I believe these are the changes that are required to support .NET Standard 2.0 code generation.
The flag
--targetprofile:netstandard
needs to be provided to instruct the compiler that we are generating code under the assumption that theprimary
assembly isnetstandard.dll
. I believe we could infer the--targetprofile
flag with a bit more work but it's beyond the scope of this PR, though some other changes I've made have made this easier.I have removed some old assembly version checking code that hacked away on version numbers to report error messages. These errors aren't particularly useful and with .NET Standard 2.0 using version
2.0.0.0
they would fire in all sorts of wrong ways. We weren't actually testing these in our test suite, and hardcoding this logic in the compiler is not a good idea anymore.@KevinRansom note the update to the SDK file