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

I need help! #121

Closed
Adahel opened this issue Apr 14, 2020 · 20 comments
Closed

I need help! #121

Adahel opened this issue Apr 14, 2020 · 20 comments

Comments

@Adahel
Copy link

Adahel commented Apr 14, 2020

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
Copy link
Owner

theraot commented Apr 14, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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

@Adahel
Copy link
Author

Adahel commented Apr 15, 2020

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---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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

@NN---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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

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

@NN---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 15, 2020

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---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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---
Copy link
Collaborator

NN--- commented Apr 15, 2020

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
Copy link
Owner

theraot commented Apr 15, 2020

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
Copy link
Author

Adahel commented Apr 20, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants