fflat - F# native script compiler on bflat
# install the dependencies (on a debian-based system)
apt install -y libc++-dev
# install the global tool
dotnet tool install --global fflat
see ./Dockerfile for a self-contained example
fflat script.fsx # about 1.4M, no debug/globalization/symbols
fflat script.fsx --small # about 1MB, no reflection/exceptions, no printfn!run fflat --help for a list of options
arm64 executable
fflat script.fsx --arch arm64 # 1.4MB and runs on raspberry pi! 👍using fflat to as an interface to the F# compiler
fflat ./mylibrary.fsx build-il --watch ## quickly recompiles mylibrary.dll on every change fflat ./helloworld.fsx --small --os windows ## ... etcfflat script.fsx [--small] build-sharedMAIN:
<script> .fsx script file path (first argument)
SUBCOMMANDS:
build <options> compile to native with bflat [default]
build-il <options> compile to IL (using fsc)
build-shared <options>
compile to shared library
Use 'fflat <subcommand> --help' for additional information.
OPTIONS:
--verbose, -v verbose output
--version version of application
--ldflags <string> <ldflags>
--noreflection disable reflection
--arch <unknown|arm|arm64|x64|x86|wasm32|loongarch64>
<x64|arm64>
--os <unknown|windows|linux|uefi>
<linux|windows|uefi>
--optimize <none|prefersize|blended|preferspeed>
<preferspeed|prefersize>
--small, -s omits most useful features like reflection, exceptions, but produces smaller binaries
--output, -o <outputFile>
output executable path
--help display this list of options.Why?
there is almost a 1000x difference in startup time for dotnet fsi scripts using nuget!
there is also FSharpPacker for .fsx scripts, which compiles .fsx scripts to native executables using the standard MSBuild pipeline (PublishAOT), but bflat can produce significantly smaller executables or even omit the .NET runtime/GC all together.
What's the smallest executable I can get?
there is a sample in ./samples/zerolib_16kb.fsx that produces a 16kb executable with the
zerolib standard library. This excludes almost all of .NET and the F# core library. however it's not very useful and you'll have to write implementations for even basic features like for loops.
TypeInitialization_Type_NoTypeAvailableerrors
don't use --small, --small will crash if your script uses any
reflection features.
there's many untrimmable features in the F# core library like printfn, quotations and linq. substituting all printfn calls with stdout.WriteLine will produce significantly smaller binaries as well.
Have fun!

