Solarian Programmer

My programming ramblings

How to create a .NET Core F# application and generate executables for multiple operating systems

Posted on August 13, 2018 by Sol

In this article I will show you how to create a simple F# console application that runs on .NET Core and how to generate executables for various operating systems.

Start by downloading the .NET Core SDK for your operating system from Run the installer and accept the default settings.

Check if everything works, by opening a Terminal (or a Command Prompt on Windows) and execute the next command:

1 dotnet --info

This is what I see on a macOS machine:

 1 ~ $ dotnet --info
 2 .NET Core SDK (reflecting any global.json):
 3  Version:   2.1.302
 4  Commit:    9048955601
 6 Runtime Environment:
 7  OS Name:     Mac OS X
 8  OS Version:  10.13
 9  OS Platform: Darwin
10  RID:         osx.10.13-x64
11  Base Path:   /usr/local/share/dotnet/sdk/2.1.302/
13 Host (useful for support):
14   Version: 2.1.2
15   Commit:  811c3ce6c0
17 .NET Core SDKs installed:
18   2.1.302 [/usr/local/share/dotnet/sdk]
20 .NET Core runtimes installed:
21   Microsoft.AspNetCore.All 2.1.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
22   Microsoft.AspNetCore.App 2.1.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
23   Microsoft.NETCore.App 2.1.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
25 To install additional .NET Core runtimes or SDKs:
27 ~ $

Now, let’s create a simple F# console application named HelloWorld:

1 dotnet new console -lang F# -o HelloWorld

If this is the first time you are creating an app with the dotnet command, the command will print a verbose Welcome message, I suggest to read it carefully. Next time, when you will create a new app with the dotnet command the above message won’t be shown.

The F# source code is in Program.fs:

1 // Learn more about F# at
3 open System
5 [<EntryPoint>]
6 let main argv =
7     printfn "Hello World from F#!"
8     0 // return an integer exit code

In order to build and run the code, go to the application folder and execute the next command:

1 dotnet run

This is what I see on my machine:

1 ~ $ cd HelloWorld
2 ~/HelloWorld $ dotnet run
3 Hello World from F#!
4 ~/HelloWorld $

dotnet run does a lot of work in background and is kinda slow. If you just need to run the application, without modifying the code, there is a faster alternative:

1 dotnet run --no-build

just keep in mind that the above will skip the build phase. If you modify the code, use dotnet run.

An even faster way to start and run the app is to use the full path to the generated dll:

1 dotnet bin/Debug/netcoreapp2.1/HelloWorld.dll

As a side note, on my test machine, dotnet run takes about 2.8 seconds, dotnet run --no-build about 0.8 seconds and dotnet full_path_dll about 0.1 seconds. This is why I’ve presented you the above alternatives.

How about generating an executable from our F# code ? If you need an executable for macOS, Windows or Linux use one of the next commands:

1 dotnet publish -c release -r osx-x64
1 dotnet publish -c release -r win-x64
1 dotnet publish -c release -r linux-x64

If you target Raspberry Pi, use:

1 dotnet publish -c release -r linux-arm

The above will create a portable folder named publish that contains everything you need in order to run the executable.

If you want to see the list of all available targets check

For example, if I want to create a Windows executable from my macOS machine I will use:

1 dotnet publish -c release -r win-x64

The resulting publish folder is in the application folder in bin/release/netcoreapp2.1/win-x64. If I want to send the executable to someone that uses Windows, I will simply zip the publish folder and send it to my client.

Show Comments