Fable icon indicating copy to clipboard operation
Fable copied to clipboard

Question about compile time file ordering of dependent fable nuget packages

Open ThisFunctionalTom opened this issue 1 year ago • 8 comments

Description

I have a fable compatible nuget packages Constants and Library where Library depends on Constants. When I add package reference to Library in our SPA app and compile it with fable I get F# compiler error while compiling sources of Library that the namespace of Constants is not known.

I executed fable compiler with --verbose flag and have seen that the source files of Library come before the source files of Constants. Both of the package sources can be found in fable_modules so I guess the dependencies resolved correctly.

Can I somehow influence the compile time ordering of files from fable_modules? Am I doing something wrong? How does the Fable order the files from referenced fable nuget packages?

Expected and actual results

I would expect the fable compiler to respect the nuget package dependencies order and sort the files when compiling accordingly. In my case first all the files from Constants should be compiled before the files of Library and at the and the files from the SPA app.

Related information

  • Fable version: 4.18.0
  • Operating system: windows 11

ThisFunctionalTom avatar Jun 07 '24 09:06 ThisFunctionalTom

I just found that there is a project_cracked.json file. In this file the files are in the correct order but in the --verbose log the files are in different order.

ThisFunctionalTom avatar Jun 07 '24 10:06 ThisFunctionalTom

Hello @ThisFunctionalTom,

Are you trying to consume the packages via NuGet or using ProjectReference.

If this is the former, you need to make sure to release a Fable compatible package. The main things being you need to include the F# source files in a fable folder.

In order to do so, you can use the all new shiny Fable.Package.SDK which automate a lot of things for you and guide you.

Or you can do it the manual way by using Fable documentation (in the future it will be updated to use Fable.Package.SDK as it more friendly to use).

MangelMaxime avatar Jun 07 '24 18:06 MangelMaxime

Hi Maxime,

Yes both nuget packages Constants and Library are fable compatible with sources in fable folder. I also find this sources in fable_modules of the SPA app. As I said, I guess it is the order of the files on the command line of F# compiler that is wrong. Here the files of the Constants come after the files of the Library and F# compiler fails because in Library we use Constants.

What's strange is that in the project_cracked.json file the order of the files is correct.

Maybe if you could navigate me where the F# compiler is called in Fable I could maybe find the error myself or maybe find what am I doing wrong.

I could try to reproduce it with some small projects but I am not sure if it will happen again. I would first like to find out how the files on the command line of F# compiler are sorted.

ThisFunctionalTom avatar Jun 08 '24 14:06 ThisFunctionalTom

Could try compiling using --test:MSBuildCracker flag ? This is using MSBuild to resolve the dependencies instead of Buildanlyzer.

Resolution of the project is done by https://github.com/fable-compiler/Fable/blob/main/src/Fable.Cli/BuildalyzerCrackerResolver.fs

Or the new when the flag --test:MSBuildCracker is set https://github.com/fable-compiler/Fable/blob/main/src/Fable.Compiler/MSBuildCrackerResolver.fs

The full projects options should be build here: https://github.com/fable-compiler/Fable/blob/1a1854acfff1cc72dabdda3e946d007e93948755/src/Fable.Compiler/ProjectCracker.fs#L809C5-L809C23

MangelMaxime avatar Jun 08 '24 17:06 MangelMaxime

Perhaps a repro can help figure out what's happening.

Here the the source file logic for Fable-compatible nuget packages. But that doesn't use MSBuild, just parses project XML, so that might explain the difference in package order in project_cracked.json.

My guess is that the dependency order provided by MSBuild might be different than what you expect from just looking at the project. As @MangelMaxime suggested, try using --test:MSBuildCracker to see if that changes anything.

Also, is the package dependency order that you get when compiling with .NET F# (using --verbose) same, or different?

ncave avatar Jun 08 '24 17:06 ncave

I just debuged the Fable Compiler while compiling our SPA app and I think I found the problem.

I think the problem is in sortFablePackages function because it compares package dependencies case sensitive and does not sort dependencies if the casing is different in fsproj file and in nuspec files of fable packages.

match List.tryFindIndexBack (fun (x: FablePackage) -> 
    pkg.Dependencies.Contains(x.Id)) acc with
...

Instead it should probably be

match List.tryFindIndexBack (fun (x: FablePackage) -> 
    pkg.Dependencies |> Set.exists (fun dep -> dep.ToLowerInvariant() = x.Id.ToLowerInvariant())) acc with

I will try to make a pull request if it is OK.

ThisFunctionalTom avatar Jun 09 '24 08:06 ThisFunctionalTom

I think it makes sense, because in the fsproj we can use Fable.Core or fable.core for the name of the dependency and it resolve to the same package. At least, it doesn't seems to break.

MangelMaxime avatar Jun 09 '24 12:06 MangelMaxime

I think I fixed it. The pull request link is above.

ThisFunctionalTom avatar Jun 09 '24 13:06 ThisFunctionalTom