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

Tricky to reference .NET Standard 2.0 components from F# Interactive #3309

Closed
dsyme opened this issue Jul 5, 2017 · 19 comments
Closed

Tricky to reference .NET Standard 2.0 components from F# Interactive #3309

dsyme opened this issue Jul 5, 2017 · 19 comments
Labels
Area-SetupAndDelivery Setup, packages, templates, SDK, delivery channels Bug Impact-Medium (Internal MS Team use only) Describes an issue with moderate impact on existing code.

Comments

@dsyme
Copy link
Contributor

dsyme commented Jul 5, 2017

Referencing a .NET Standard 2.0 component from F# Interactive (fsi.exe) fails with

"netstandard.dll 2.0.0.0" is not part of the fsi.exe application or an error such as 

or

unknown(1,1): error FS3216: type 'Microsoft.EntityFrameworkCore.Design.AnnotationCodeGeneratorDependencies' not found in assembly 'Microsoft.EntityFrameworkCore.Relational, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. A possible cause may be a version incompatibility. You may need to explicitly reference the correct version of this assembly to allow all referenced components to use the correct version.

Repro steps

Provide the steps required to reproduce the problem

  1. Create a .NET Standard 2.0 component

    dotnet new classlib -o -lang F# lib2
    cd lib2
    add code file:
        module Say 
        let hello (t:System.DateTime) = printfn "the time is %A" t
    
    dotnet restore
    dotnet build
    
  2. Reference this from .NET Framework fsi.exe

Release\net40\bin\fsi.exe -r ..\misc\lib2\tplib1.dll
> Say.hello System.DateTime.Now;;

Expected behavior

Works ok and prints the current time

Actual behavior

stdin(1,1): error FS0074: The type referenced through 'System.DateTime' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard'.

Known workarounds

  1. Manually acquire the package NETStandard.Library.NETFramework

  2. Add an explicit reference to packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\lib\netstandard.dll e.g.

#r @"C:\GitHub\dsyme\visualfsharp\packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\lib\netstandard.dll"

Related information

master, Windows, .NET Framework 4.7 or 4.6.1

@dsyme dsyme changed the title Implement #r of .NET Standard 2.0 components from F# Inteactive Can't reference .NET Standard 2.0 components from F# Interactive Jul 5, 2017
@dsyme dsyme added Bug Impact-High (Internal MS Team use only) Describes an issue with extreme impact on existing code. Area-Compiler Area-SetupAndDelivery Setup, packages, templates, SDK, delivery channels labels Jul 5, 2017
@terrajobst
Copy link
Member

terrajobst commented Jul 11, 2017

The best way to get the correct set is to configure the fsi application to include all .NET Standard 2.0 components necessary for .NET Framework 4.6.1 and up. This can be done by setting this property:

<Project>
  <!-- ... -->
  <PropertyGroup>
    <DependsOnNETStandard>true</DependsOnNETStandard>
  </PropertyGroup>
  <!-- ... -->
</Project>

@dsyme
Copy link
Contributor Author

dsyme commented Jul 13, 2017

@cartermp @KevinRansom Given @terrajobst's advice I'd like guidance on this at some point (no huge rush). It seems that including the facade DLLs as part of the compiler seems to be the correct advice, though I think the real concern is auto-referencing them as part of the F# Interactive scripting model.

I understand the reluctance to do this. Perhaps adding just netstandard.dll is sufficient since most other facade DLLs are part of .NET 4.6.1

Anyway, I added a description of the workaround, which is to manually acquire NETStandard.Library.NETFramework and add an explicit reference to the facade DLLs you need:

#r @"packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\lib\netstandard.dll"

Not pretty but it works

@terrajobst
Copy link
Member

though I think the real concern is auto-referencing them as part of the F# Interactive scripting model.

Why would you need to auto-reference them? Presumably F# interfactive is using RefEmit to run code within the current process. The CLR should be able to load the appropriate assemblies on-demand from the fsi directory, no?

I understand the reluctance to do this. Perhaps adding just netstandard.dll is sufficient since most other facade DLLs are part of .NET 4.6.1

True, but customers loading pre-.NET Standard 2.0 components will get pretty bad/unactionable error messages (assembly load errors, type load errors, missing member errors).

@dsyme
Copy link
Contributor Author

dsyme commented Jul 13, 2017

Why would you need to auto-reference them?

In the F# compilation stages being run in F# Interactive prior to RefEmit we need to follow the type forwarders to emit correct code (to understand that [netstandard]System.Int32 --> [mscorlib]System.Int32 etc.), to determine type equality etc.

True, but customers loading pre-.NET Standard 2.0 components will get pretty bad/unactionable error messages (assembly load errors, type load errors, missing member errors).

I agree this is technically possible, which is why I included the whole lot in my currently doomed PR. My estimate is that this doesn't actually happen much yet, for two reasons

  1. For .NET Standard 1.x components there is often a .NET Framework version in the package - or portable versions. This is what people reference if it is there. Basically most F# scripters probably aren't referencing any .NET Standard 1.x components at all.

    I think it will be much more common for nuget packages to only have .NET Standard 2.0 components - because a .NET Standard 2.0 is often completely adequate replacement for the .NET Framework version.

  2. Versions (e.g. 4.0.0.0) of some assemblies like System.IO are shipped in the implementation assemblies of .NET Framework 4.6.1. F# Interactive will happily resolve to these implementation assemblies as a last resort even if System.IO 4.1.2.0 was requested in a reference and regardless of version. While this is not "sound", I suspect the forwarders in these implementation assemblies are adequate for most .NET Standard 1.x components

@terrajobst
Copy link
Member

terrajobst commented Jul 13, 2017

Strike what I said earlier; I was only thinking of runtime. In order to compile the F# code to IL you of course need to load the facades. This is proof I'm not nearly as smart as many people believe (and most don't even think that highly of me to begin with 😏 )

@cartermp cartermp added this to the VS 2017 Updates milestone Jul 14, 2017
@dsyme dsyme added Impact-Medium (Internal MS Team use only) Describes an issue with moderate impact on existing code. and removed Impact-High (Internal MS Team use only) Describes an issue with extreme impact on existing code. labels Jul 25, 2017
@dsyme dsyme changed the title Can't reference .NET Standard 2.0 components from F# Interactive Tricky to reference .NET Standard 2.0 components from F# Interactive Aug 5, 2017
@dsyme
Copy link
Contributor Author

dsyme commented Sep 1, 2017

@terrajobst @cartermp @KevinRansom

I'll close this, since the decision was not to ship the 100 facade DLLs as part of F# Interactive, but rather apply the workaround (which feels dubious to me, but anyway...) and wait for .NET 4.7.1 to become widely spread

Workaround is:

  1. Manually acquire the package NETStandard.Library.NETFramework
  2. #r @"packages/NETStandard.Library.NETFramework.2.0.0/build/net461/lib/netstandard.dll"

Perhaps there is a better way then acquiring NETStandard.Library.NETFramework.

@dsyme dsyme closed this as completed Sep 1, 2017
@dsyme
Copy link
Contributor Author

dsyme commented Feb 8, 2018

I believe the fact that F# Interactive doesn't play well with .NET Standard 2.0 yet is starting to bite people https://twitter.com/isaac_abraham/status/961580320897355776

@cartermp @KevinRansom Anything we can do here?

@lambdakris
Copy link

HI, I was trying to use a script file within a new sdk project while targeting net471 which depends on Newtonsoft.Json. Is the right thing to do here to depend on the net45 Newtonsoft.Json.dll or on the netstandard2.0 Newtonsoft.Json.dll?

If I reference the netstandard2.0 version, I get messages like "The type 'Enum' is required here and is unavailable. You must add a reference to assembly 'netstandard, Version=2.0.0.0...'.

I tried looking for a NETStandard.Library.NETFramework package under C:\Users{username}.nuget\packages in case it is automatically acquired by the net sdk 2.x, but did not find it. Then I installed the NETStandard.Library.NETFramework package from nuget into the project, however, this did not result in the NETStandard.Library.NETFramework package being added under the .nuget/packages folder under my home folder or anywhere else that I could track down.

Ultimately I am typically unblocked by referencing the net45 version of assemblies, but I was just wondering if I should be able to reference netstandard2.0 assemblies or not...

@smoothdeveloper
Copy link
Contributor

Starting to hit this on libraries that I can't use in FSI anymore.

Until this is fixed, could we have guidelines setup for library authors so they keep shipping binaries for full .NET framework along side netstandard ones? otherwise this is kind of splitting the ecosystem between libraries that work in FSI and those which don't.

@aaron-comyn
Copy link

aaron-comyn commented Jun 8, 2018

We are seeing an issue with using Roslyn via FSI, despite using the NETStandard.Framework.Library workaround: code that compiles and runs in a .Net Core console application errors in FSI due to missing types ("type 'Microsoft.CodeAnalysis.CSharp.CSharpCompilation' not found in assembly 'Microsoft.CodeAnalysis.CSharp, Version=2.8.0.0, ...").

I have made a gist that shows how to provoke the issue: https://gist.github.com/aaron-comyn/e178636def80d898f61ce4eeead21b3b

The issue is present with the last years worth of Roslyn releases, using the same references as an operational .Net Core application. We're using FSI to introduce new datatypes into running production systems, so this issue is a bit of a 'showstopper' wrt .Net Core (System.CodeDom does not support the platform). FSI not running on .NET Standard/Core is a pain point :)

[Side note: the NETStandard.Framework.NETLibrary package is marked as deprecated... kinda confusing for FSI users who require this workaround...]


We can add EPPlus and Microsoft.Exhange.WebServices.NETStandard (unofficial .net core port of EWS), to the list. Both work fine compiled and error in FSI ( EPPlus throws a security error).

@haraldsteinlechner
Copy link

what is the status of this issue? is @dsyme 's workaround still the way to go? If so, by using the explicit reference i get problems alà DateTime is not compatible with DateTime. Somehow i get wrong system symbols resolved randomly. I can post a repro if relevant.

@cartermp
Copy link
Contributor

cartermp commented Nov 1, 2018

The workaround is not appropriate, no. When #5850 is completed, then FSI will be able to understand packages and work with .NET Standard in a cross-platform way. Additionally, when VS 2019 is eventually shipped, it will have .NET Framework 4.7.1. (or 4.7.2, don't quite recall), which can understand .NET Standard "natively". The core issue is that FSI within VS has to target .NET Framework 4.6 today, and 4.6 has no notion of .NET Standard. Referencing 100 facade .dlls manually may work for you, but I can't say I'd recommend it.

@OnurGumus
Copy link
Contributor

@dsyme even with. Net 4.7.2 similar issue hapenning with canopy

@smoothdeveloper
Copy link
Contributor

@OnurGumus, until this is resolved, maybe canopy project can ship .net framework assemblies as well?

I believe you can still use older versions of the nuget for .net framework if that helps.

@KevinRansom
Copy link
Member

@OnurGumus can you provide a repro, that fails on .NET 4.7.2, I believe it should work there fine.

@OnurGumus
Copy link
Contributor

@KevinRansom
See the attached zip file which
canopy.zip
only contains source but no binaries then

just call

dotnet tool install --tool-path .paket Paket
.paket\paket install
dotnet fsi test.fsx

@OnurGumus
Copy link
Contributor

Though let me elaborate, I am targeting .net core 3.0 SDK preview 5. It's just my machine has .net 4.7.2 sdk installed too.

@cartermp
Copy link
Contributor

It's worth noting that this is about reference .NET Standard components from the FSI that is bundled within Visual Studio, not dotnet fsi. I think it's worth filing a separate bug for dotnet fsi though, since that should work.

@KevinRansom
Copy link
Member

I haven't run the repro, but I can imagine what is going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-SetupAndDelivery Setup, packages, templates, SDK, delivery channels Bug Impact-Medium (Internal MS Team use only) Describes an issue with moderate impact on existing code.
Projects
None yet
Development

No branches or pull requests

9 participants