theraot / Theraot

Backporting .NET and more: LINQ expressions in .net 2.0 - nuget Theraot.Core available.
MIT License
162 stars 30 forks source link

I need help! #121

Closed Adahel closed 4 years ago

Adahel commented 4 years ago

I need help from a more experienced developer. To do an F# language upgrade in .NET 4.0 I compiled FSharp.Core 4.5.0.0, with Theraot.Core and with minor adaptations, but when I try to access the Async module I get the following error: "FS0074 The type referenced through 'System. Runtime.ExceptionServices.ExceptionDispatchInfo 'is defined in an assembly that is not referenced. You must add a reference to assembly 'Theraot.Core'". The problem is that Theraot.Core is referenced in the project. My biggest fear is having to rewrite Theraot.Core in F#, because it is big. Why rewrite in F#? To become one with the FSharp.Core. FSharp.Core 4.5.0.0 .NET 4.0 download: http://www.mediafire.com/file/capffldzevj909q/FSharp.Core.dll/file

theraot commented 4 years ago

If I understand correctly...

You have a custom build of FSharp.Core that references Theraot.Core (which would be the one on the link).

Then you have a project that uses this FSharp.Core. It makes sense that this project needs a reference to Theraot.Core. Now, you say the project has such reference, and regardless you get an error tell you otherwise.

Well, is it the same Theraot.Core? If your project is loading Theraot.Core for .net 4.5 it will not find ExceptionDispatchInfo there. The reason why it is not included is because the standard library does, if the .NET 4.5 build of Theraot.Core had it, it would conflict. So make sure you are referencing the same one you used to compile FSharp.Core.

Now, something you can try is using ilMerge (or similar) to merge Theraot.Core in your custom build of FSharp.Core. That way, the projects using it do not need to add an extra reference to Theraot.Core because your custom build of FSharp.Core would include it.

Adahel commented 4 years ago

Well, is it the same Theraot.Core?

Yes.

If your project is loading Theraot.Core for .net 4.5 it will not find ExceptionDispatchInfo there.

Theraot FSharpLu FSharpLu by Microsoft.

Now, something you can try is using ilMerge (or similar) to merge Theraot.Core in your custom build of FSharp.Core.

I'll try, if it works or not, I'll send a comment.

Adahel commented 4 years ago

I'll try, if it works or not, I'll send a comment.

It does not work and many bugs appear. This link shows what happens: https://stackoverflow.com/questions/13915057/how-to-merge-f-and-c-sharp-assemblies-with-ilmerge-so-that-all-types-would-be-a It looks like I'm going to have to rewrite Theraot.Core in F#: I will cry.

NN--- commented 4 years ago

Won't it be simpler to use F# with .NET Core ? What is the reason you need .NET Framework 4.0 ?

Adahel commented 4 years ago

Won't it be simpler to use F# with .NET Core ?

Yes, but why is there Theraot.Core?

What is the reason you need .NET Framework 4.0 ?

XNA (not monogame) and Windows XP.

NN--- commented 4 years ago

Ok, so the problem is that you don't have ExceptionDispatchInfo in your FSharp.Core you build with Theraot.Core. Right ? Perhaps you don't define the required defines correctly ?

Adahel commented 4 years ago

I believe it is because of the compiler that is linear: It loads System dll first, similar, FSharp.Core and lastly Theraot.Core. To work, Theraot.Core would have to be loaded before FSharp.Core which is not happening.

NN--- commented 4 years ago

Didn’t you say that you have your own FSharp.Core ? Then if it has dependency in Theraot.Core , it must load the dependency first.

Adahel commented 4 years ago

Didn’t you say that you have your own FSharp.Core ? Then if it has dependency in Theraot.Core , it must load the dependency first.

Why don't you test it?

Adahel commented 4 years ago

Remember that FSharp.Core is vital for the language, Theraot.Core is a third-party library. How does the compiler handle this?

NN--- commented 4 years ago

Ok. So it is not custom made FSharp.Core.dll. Maybe there is a way to change IL and change the order of loading or compile your own FSharp.Core.dll ?

Another option is to make a small loader application without FSharp.Core dependency which will load first Theraot.Core and then load your assembly .

Adahel commented 4 years ago

Ok. So it is not custom made FSharp.Core.dll.

Source code: https://github.com/Adahel/FSharp.Core

NN--- commented 4 years ago

Ok, I see you added the reference to Theraot.Core (any reason for not using NuGet ?) , then it means when .NET loads FSharp.Core , it must first load Theraot.Core , isn't it ?

Adahel commented 4 years ago

Ok, I see you added the reference to Theraot.Core (any reason for not using NuGet ?) , then it means when .NET loads FSharp.Core , it must first load Theraot.Core , isn't it ?

I use nuget, I just didn't upload the package. I don't know why Theraot.Core is being loaded later.

NN--- commented 4 years ago

You can try changing the output IL instead of having:

Your program -> FSharp.Core , Theraot.Core

to do:

Your program -> FSharp.Loader -> FSharp.Core -> Theraot.Core

Perhaps it loads alphabetically and you can make a test with A.dll name ?

Adahel commented 4 years ago

Perhaps it loads alphabetically and you can make a test with A.dll name ?

My time is up for now. I believe that loading FSharp.Core is hardcoded by the compiler. I believe that the only solution is to rewrite Theraot.Core in F#.

NN--- commented 4 years ago

It can be hard coded by compiler but you still can manually change the output IL and change the order of dependencies.

The compiler is open source too, so you can easily to compile the F# compiler and add Theraot.Core to the hard coded list. Another option is slightly change the IL of the F# compiler with the required dependency, or interpcept in runtime and inject Theraot.Core to the list.

NN--- commented 4 years ago

You can use Fusion Log viewer ( https://docs.microsoft.com/en-us/dotnet/framework/tools/fuslogvw-exe-assembly-binding-log-viewer ) or Process Monitor or any other tool and see what is the exact order of loading assemblies.

theraot commented 4 years ago

I do not think the problem is the merging, but an F# compiler limitation. However, I said ilMerge (or similar), there are other options to merge assemblies such as dnSpy and .NET Reactor.


Won't it be simpler to use F# with .NET Core ?

Yes, but why is there Theraot.Core?

The Theraot.Core nuget include builds for .NET Framework (2.0 onward), .NET Core and .NET Standard.

What is the reason you need .NET Framework 4.0 ?

XNA (not monogame) and Windows XP.

I don't think XNA on Windows XP can work with .NET Core anyway.


It looks like I'm going to have to rewrite Theraot.Core in F#: I will cry.

You can do something like this:

image

[FSharp.CoreEx] -> [FSharp.Core]
[FSharp.CoreEx] -> [Theraot.Core]
[YourApp] -> [FSharp.CoreEx]
[YourApp] -> [FSharp.Core]
[YourApp] -> [Theraot.Core]

Where FSharp.CoreEx is a new assembly that provides the parts that FSharp.Core is missing or replacements/workarounds for those that FSharp.Core have but are incomplete or incompatible. Pretty much like the relationship between Theraot.Core and mscorelib. In this scenario you would still be using the default build of FSharp.Core (no additional dependencies added) and it can continue to load first.


I do not know if @NN--- loader idea would work.


And of course there is messing with the F# compiler. Well, I don't want to go there.

Adahel commented 4 years ago

As a programmer I decide to go the easy way. I rewrote in F# some classes from Theraot.Core: (IReadOnlyCollection IReadOnlyDictionary IReadOnlyList) in F# (ExceptionDispatchInfo) in F# Now I have a fully functional FSharp.Core 4.5.0.0, I am very happy: https://www.nuget.org/packages/FSharp.Core.net40/ Unfortunately now my FSharp.Core and Theraot.Core are in conflict. I'll have to say goodbye to Theraot.Core at least until my project is more mature. My project is priority for now. Maybe I will launch a nuget of Theraot.Core compatible with my FSharp.Core. In the future, when I have more experience, I will study the compiler. Thank you for your help.