[HN Gopher] FSharpPacker - compile F# scripts to executables
       ___________________________________________________________________
        
       FSharpPacker - compile F# scripts to executables
        
       Author : neonsunset
       Score  : 79 points
       Date   : 2024-12-03 10:44 UTC (4 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | Multicomp wrote:
       | Nice work shipping this! I enjoy and prefer f# to c# but never
       | gave scripts much care because I could never do this, fsi and the
       | repl was not enough. Now? Hmmm I have options !
        
       | neonsunset wrote:
       | A few of notes regarding AOT compilation if you would like to
       | have the best experience:
       | 
       | 1. print* functions with "%A" format do not work because
       | "structured output" uses reflection patterns that the linker
       | cannot analyze. You can easily replace them with string
       | interpolation that F# now has. I carry around these bindings:
       | open System            let println s = Console.WriteLine s
       | let print s = Console.Write(x: string)
       | 
       | and use them as                 println $"Hello, {thing}"
       | 
       | 2. AOT compilation is not a scripting environment so accessing
       | fsi args does not work, here's the snippet that I use for it:
       | open System            // Detect fsi, if not - slice
       | appropriately       // You do not need this if you know that you
       | will be       // only compiling the script or only running it
       | with fsi       // just use the offset of 2 or 1 respectively :)
       | let args =         let args = Environment.GetCommandLineArgs()
       | if args[0].Contains "fsi.dll" then args[2..] else args[1..]
       | // Use args in some way       args |> Array.iter println
       | 
       | 3. For quickly publishing script files you may want to define a
       | (fish) shell function like this:                   function fspk
       | set name (string replace '.fsx' '' $argv[1])             fspack
       | $argv[1] -f net9.0 --aot -o . \
       | /p:InvariantGlobalization=true \
       | /p:OptimizationPreference=Size &&             rm -rf ./$name.dbg
       | ./$name.dSYM         end
       | 
       | This will reduce the binary size and will give you just a single
       | executable for every `fspk my_script.fsx`. The binaries do start
       | at ~4MB but beyond that - they scale efficiently with
       | dependencies.
       | 
       | 4. Except what is explicitly noted in repo, other scripting
       | features work like referencing nuget packages or importing files.
       | I did not expect to like this as much as I did, it's incredibly
       | productive and you can just throw a few files together while
       | having fully statically typed scripting environment and built-in
       | package manager.
       | 
       | You can also get Ionide for VS Code for language server,
       | autocomplete and debugging support.
        
         | fire_lake wrote:
         | Given these limitations, isn't it easier to create a small
         | dotnet project?
        
           | neonsunset wrote:
           | It might be! I'd expect that at some point this would be a
           | natural progression.
           | 
           | However, very often you don't need that - you can just
           | compile individual script files which merge together code,
           | package and file references. No need to maintain a separate
           | folder with a separate .fsproj - simply #open some_utils.fsx,
           | #r "nuget: FsHttp" or #r "SomePackage.dll" and 'fspk
           | my_script.fsx'.
           | 
           | Initially, I did not know this existed, but it turned out a
           | friend of mine wrote this tool and I have been using it ever
           | since.
        
       | Alifatisk wrote:
       | I am a huge fan of keeping things as standalone executable, good
       | work!
        
       | raphinou wrote:
       | FSharpPacker works on scripts (with extension .fsx) written with
       | F# and usually run with `dotnet fsi`. For the F# advent calendar
       | [1] I recently blogged about how those scripts are a viable
       | starting point for developing an application in F#. Actually,
       | it's even possible to easily maintain a scripted version and a
       | compiled version of the same F# app, with basically the same
       | code. For those interested, it's at
       | https://www.asfaload.com/blog/fsharp-fsx-starting-point/
       | 
       | 1: https://sergeytihon.com/2024/10/26/f-advent-calendar-in-
       | engl...
        
         | nickpeterson wrote:
         | Any reason to prefer this or fflat (bflat)?
        
           | neonsunset wrote:
           | Fflat does not work on macOS and does not support .NET 9. I
           | had issues with making it work on Windows and Linux too
           | unfortunately.
           | 
           | This one works like a charm.
        
       ___________________________________________________________________
       (page generated 2024-12-07 23:00 UTC)