-
-
Notifications
You must be signed in to change notification settings - Fork 38
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
[Feature Request] Add additional compiler directives #206
Comments
I think compiler directives can be set in the |
Everything you put into the fsproj files alters the published nuget package. As Fable uses standard compilers like -> Transpiling a project with conditions works but downstream projects referencing the published nuget package will not be transpilable |
Indeed, we can set the compiler directives in the Hello, I remember talking about this problem with @Freymaurer. I don't remember if this was somewhere in public or in private. What is causing issues like you mentioned is the fact that you have a single Project that depends on different libraries for the different runtime:
This works fine for compiling However, you don't only expect to use the output of In theory there are 2 ways to solve this problem:
Personally, I prefer the second solution because it doesn't do anything strange to the dependencies. For example, Another issue, I see is that it is possible to have a difference between the DLL API (used for intellisense) vs the actual API available for the runtime. In theory, it should not be too problematic because DLL API is a the same or at worth a subset of the target specific API available. But it means that all the target specifics helpers that you put in place, cannot be accessed to the end user. The DLL compile only 1 versions of the code, it can't decide to expose the JS or Python APIs based on compilers directives. This would be possible if Fable, was able to hooks into the TargetFramework of .NET but the person wanted to do that does not seems active anymore and we didn't get an answer from NuGet/MSBuild team. (I tried to ask again for news on the subject). Is there a reason why you can't use After writing these notes, Fable is not the only one in a similar position. For example, Avalonia a cross platform UI solution has similar problems. They need to provide supports for iOS, Android, Desktop, and it seems like they do it via different packages:
They do have however, one benefit which is to have different frameworks registered on NuGet to target the runtimes too:
|
I think you don't see this issue because when compiling the DLL you will use But this also means that if we were to set the I feel like not using one package per target, is creating a path where a lot of edge cases are pilling up. |
Hey @MangelMaxime, thanks for your detailed answer and thoughts about this. I agree with everything you said, but using one package per target comes with its own set of problems. Especially code duplication and maintainability of so many parallel packages. I am currently try-forcing my approach in https://github.com/nfdi4plants/ARCtrl. For this, I copied the Thoth.Js and Thoth.Py code into https://github.com/fslaborg/FsSpreadsheet and added the compiler directive conditions. If this works, I would like to merge the framework specific packages on an even lower level. I feel like having this functioning on a low level will make everything in the dependant packages easier. Will keep you updated here, if you don't deem it too cluttering. |
It should not lead to more code duplication because you can re-use your sources files. Each project can include the sources files they need and a source file can be included several times. This is what I am doing for Fable.Form, where I need to support several renderer library like React, Sutil, Fable.Lit, FuncUI, and it doesn't lead to more code duplication than if I was to inline everything in a single package. Plus the DX, is easier I can switch across different solution files, to have the IDE/Packages setup needed for the target I want. If I want to work for Sutil, I open Without that, if I wanted to develop a specific target I would need to either manually edit the By doing so, we are mimicking how IDE natively support MultiTarget framework (in their case via IDE GUI settings):
The problem is that now you are forking the ecosystem, in the linked PR I see fork of the following libraries:
|
And there are others ways of supporting multi target project at least for Thoth.Json. Work started to create a Thoth.Json.EveryWhere (need to find a name), which don't rely on a native parser but instead use a full F# parser based on Thoth.Parser. This way people could use the native libraries if they care about performance or the custom parser for cross compatibility. |
Something I want to say, is that I have the tendency to be a purist or really safe when it comes to these decision because once we let the Jinn out of the bottle it is difficult to go back. In theory, going the way you are asking to @HLWeil should not cause too much problem because I think the situation where there is a disconnect between the DLL information and the actual code available at runtime are problem invalid/non supported use cases. For this reason, I am also asking for feedback from the F# community because this is something that don't only impact Thoth.Json but will probably shape some future libraries too because people with mimic what will be done here. |
For new people joining the discussion here is a summary.
The situation we are trying to solve is the following: We have a library
<PackageReference Condition="'$(FABLE_COMPILER_PYTHON)' == 'true'" Include="Thoth.Json.Python" Version="0.2.0" />
<PackageReference Condition="'$(FABLE_COMPILER_JAVASCRIPT)' == 'true'" Include="Thoth.Json.JavaScript" Version="0.1.0" /> Warning However, it can lead to issues if you are using lock files because then depending on what target you are trying to build then the dependency list is not stable and so the lock file will change each time. Rendering the lock file not useful.
Meaning that
Because of that, when compiling the To solve this issue there are 3 visions:
Pros
Cons
namespace Thoth.Json.JavaScript
#if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT || !FABLE_COMPILER
// your F# code goes here
#endif Pros
Cons
Pros
Cons
What are your thoughts on the problem and how would you like the problem to be solved? PS: I tried to be objective when presenting the different situations but this is always a difficult exercise to do when you have an opinion. So please, be gentle in the comments 😇 |
Time to revive ionide/FsAutoComplete#1065 |
@HLWeil You are saying that Python fable transpilation fails. But do you have a similar problem when compiling to JavaScript ? |
Hey Maxime! Thanks for your input! Maybe i can add some more information on why we have troubles following your suggested way "Mimic how TargetFramework works by creating multiple package specialised for each target". One of the main goals of our library is to create js/py and dotnet code, which should all be easy to use from their respective native language. Therefore we have one main type which should be imported for js and py users (let's call it
Can you point me to the relevant code here? I looked over the Fable.Form repo but could not find it 😅 (Thanks for all your work again 🙂 ) |
Sry that was not well put. From what I've seen, the |
I made an example repo to demonstrate how it would works. If you want we could have a call so I explain it to you, and perhaps we can adapt it to your project. https://github.com/MangelMaxime/fable-example-multi-targets As statement in the README, I have an issue running the generated Python code but I don't know how to fix that issue. |
Closing as we decided to go with the multi projects approach. |
Implementation of the discussed concept can be seen in nfdi4plants/ARCtrl#446. |
We stumbled across a very intricate, general problem with Fable. The base problem is, that python fable transpilation fails, if emitted javascript code is referenced somewhere down the line.
In order to fix this, we use conditional dependencies in https://github.com/nfdi4plants/ARCtrl/blob/main/src/Json/ARCtrl.Json.fsproj:
This works in the repository, when calling the published package on nuget and also the javascript package in npm and the python package in pypi work.
However, a downstream library depending on the nuget package cannot be transpiled to js or python, as the dependencies to
Thoth.Json.Python
andThoth.Json.JavaScript
are not included in the nuget package. Fable therefore does not include these dependencies.I looked at this from many different angles, and the only working solution I found is the following:
https://github.com/CSBiology/DynamicObj/pull/38/files
Always use compiler directives for js and py only code, even on the lowest level. To still have intellisense, one can also include the
!FABLE_COMPILER
as anor
case:#if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT || !FABLE_COMPILER
We use Thoth.Json in many places, would it be possible to add these directives to the js and py parts of the repo?
The text was updated successfully, but these errors were encountered: