To get started with F#, please refer to the following documents:

Once you have F# installed and operating, refer to the resources below for platform specific techniques, tools, and resources.

This guide includes resources related to cross-platform development with F#. To contribute to this guide, log on to GitHub, edit this page and send a pull request.

Note that the resources listed below are provided only for educational purposes related to the F# programming language. The F# Software Foundation does not endorse or recommend any commercial products, processes, or services. Therefore, mention of commercial products, processes, or services should not be construed as an endorsement or recommendation.

Resources for cross-platform development

Compilation, Command Line Tools and Scripting

You can start F# Interactive using

$ fsharpi

> 1+1;;

val it : int = 2

You’re off! Some common commands are:

fsharpi                            (starts F# interactive)
fsharpc file.fs                    (F# compiler)
xbuild                             (builds .fsproj projects and .sln files)
mono file.exe arg1 ... argN        (runs a compiled F# program)
mkbundle --static file.exe -o file (makes a static native image, including the F# runtime)

Cross-platform users may also be interested in Fable, an F# compiler that emits JavaScript.


Some editors have specific support for F#, either builtin or through addons provided by the F# community:

If running F# Interactive in Emacs or another similar environment, use

> fsharpi --readline-

to turn off console processing.


For most F# documentation, see the documentation pages.

Projects and Build Automation

.fsproj and .sln files

You can use xbuild to build projects and solutions described by the .fsproj and .sln file formats from Visual Studio without change. Xamarin Studio and MonoDevelop can also create and manage .fsproj and .sln files.

Use xbuild to build projects and solutions:

xbuild RocketPart.fsproj
xbuild RocketSolution.sln

Many people doing cross-platform or Mac/Linux development don’t like .sln files because the file format is not very amenable to human editing. If so, you can also create a .fsproj file that brings together a collection of .fsproj files. Example of this can be found on F# Core Engineering

Tooling around F# projects often relies on .fsproj files being present, for example the autocompletion in emacs mode or Vim will not work with out one, except when editing an F# script. These .fsproj files are special XML files, and can therefor be somewhat unwieldy to maintain by hand. To help with this you can use tools such as Xamarin Studio or MonoDevelop to create and maintain them, or command line tools such as Forge (see below).


Forge is a self contained tool for generating and managing projects. It allows the generation of new projects based on an expanding list of templates. It also encapsulates the best practices for those projects in terms of tooling and layout. The generated projects contain .fsproj files, which can in turn be managed via forge as well making sure cross platform builds as well as editor integration works out of the box. Of course forge can also manage the .fsproj files for existing projects.


The F# command-line compiler (fsharpc) can be used with Makefiles in the usual way.


FAKE is a build-and-publish automation utility sometimes used by F# programmers (partly because builds are automated using F# itself, and partly because it is a great tool).

FAKE can be fetched using NuGet.exe, e.g.:

# Get nuget.exe
sudo mozroots --import --sync
curl -L -o nuget.exe

# Get FAKE.exe
mono nuget.exe install FAKE -OutputDirectory lib -ExcludeVersion -Prerelease

Package Repositories and Dependency Management


NuGet is an open-source, cross-platform package management tool with many thousands of packages available. See the documentation. It is used extensively on Windows ecosystem but is growing in its cross-platform use.

For those on Mac/Linux, familiarity with the command-line NuGet.exe utility is highly useful. Get the command line utility like this:

# Get nuget.exe
sudo mozroots --import --sync
curl -L -o nuget.exe

Before using NuGet.exe on Mac/Linux, be sure to run

 mozroots --import --sync

Typical usage is:

mono nuget.exe install                               -- installs from packages.config
mono nuget.exe install packageId -Version    -- installs particular version of particular package

An example packages.config is:

<?xml version="1.0" encoding="utf-8"?>
  <package id="FsUnit" version="" targetFramework="net40" />
 <package id="NUnit" version="2.6.2" targetFramework="net40" />

See also the documentation.

F# project files (.fsproj) can be configure to automatically get NuGet packages during a build. The project file should have a line like this (adjust the ‘…’ to reference a copy of NuGet.targets checked into your project).

<Import Project="...\NuGet.targets" Condition="Exists('...\NuGet.targets')" />

A copy of NuGet.exe should be in that directory with executable permissions set. You may also need to set:

export EnableNuGetPackageRestore=true

It is quite common to check a copy of NuGet.exe into a project, e.g. in lib/NuGet/NuGet.exe.

You can add NuGet support to these IDEs if not already present. See NuGet for MonoDevelop and Xamarin Studio.

See to learn how to make and publish NuGet packages, or look at examples from other F# community projects.


Paket is a dependency manager client for .NET that is very popuar with the F# community. Excellent documentation is available for using Paket with F# on the Paket site.

You can also use Paket specifications as prefixes in F# scripting. For example, see Paket and Suave.

Some tips:

Paket Load Script Generation

Paket has a feature --generate-include-scripts that is very useful for doing cross-patform scripting that references many nuget packages.

Some Examples of Cross-Platform Packages

Some F# and CLI packages are more cross-platform friendly than others. Many will work with no alteration. Here are some of interest:

In the wider F# exosystem there are many cross-platform and/or portable packages and libraries. Here are some examples:

There are a wide range of cross-platform libraries available as part of the core libraries available to F#, for example:

Compatibility guides, documentation and migration assessment tools are also available.

Portable (PCL) Libraries

Portable .NET libraries have access to less core functionality, called a “portable profile”, but can be used across multiple platforms and multiple profiles of .NET. For example, a portable library may be usable on Mac, Linux, Android, iOS, Windows and Windows Store apps (depending on the versions of runtime machinery used and other factors).

See Cross-Platform Portable Class Libraries with .NET are Happening for a perspective on cross-platform portable libraries for Visual Studio users.

F# portable libraries reference FSharp.Core versions such as, with matching mscorlib versions. A binding redirect may be neeeded to ensure bindings to these libraries redirect correctly, e.g. to FSharp.Core

When authoring a Portable library on OSX and Linux, be sure to reference the FSharp.Core nuget package to find the right profile version of FSharp.Core. This is simpler than reying on any specific version incuded with your F# installation.

For more information on FSharp.Core, see the Notes and Guidance on FSharp.Core from the Core Engineering Group of the F# Software Foundation.

Binding Redirects

Applications will almost certainly need to specify “binding redirects” for some or all components where multiple versions of components need to be “unified” to one master version at runtime. This applies particularly to FSharp.Core but also to other components. For instance, see examples of binding redirects for FSharp.Cpre.

Unit Testing

A table of .NET unit testing frameworks can be found here.


Fuchu is a test library for .NET, supporting C# and VB.NET but with a special focus on F#. It draws heavily from Haskell’s test-framework and HUnit. You can read about the rationale and underlying concepts in this blog post, or tests should be first-class values so that you can move them around and execute them in any context that you want. Also, if they are first-class values, then you can take extra care with what the test methods return, making integrations with external libraries much cheaper.

Install-Package Fuchu

Since tests are values, it’s easy to extend the framework to integrate with other tooling, e.g. with FsCheck to use a fuzzing/randomization approach to testing (see below)

Install-Package Fuchu.FsCheck

Fuchu also has an integration with PerfUtil which can be used to automate performance testing and trending in a continuous integration environment.

Install-Package Fuchu.PerfUtil


FsCheck is a tool for testing .NET programs automatically. The programmer provides a specification of the program, in the form of properties which functions, methods or objects should satisfy, and FsCheck then tests that the properties hold in a large number of randomly generated cases.


NUnit is an open-source, cross-platform unit-testing framework for F# and other .NET languages. It is written in C# and has been completely redesigned to take advantage of many .NET language features, for example custom attributes and other reflection related capabilities. Also xUnit is a good alternative for NUnit.

Some guides to using F# and NUnit together are:


FsUnit is often used by F# programmers as an DSL to access popular unit testing frameworks. An FsUnit NuGet package is available.

Continuous Integration builds

Using Travis and AppVeyor

Perhaps the simplest way to regularly build and test your work across multiple platforms is to use Travis.

You can automate the build and test of all commits and pull requests to GitHub projects on Linux and OSX by using Travis. This is very easy to arrange, just add a .travis.yml file to your project root (example, example ), and register the project in your Travis account.

Setting the language to “objective-c” causes Travis to use an OSX machine for build.

Travis is free for open source projects.

To also automate your build and test on Windows, AppVeyor is a good choice. Here is an example configuration file.

Miscellaneous Notes on Open Source and Cross Platform Development

Testing on multiple platforms

If you are Windows developers, you can set up a Vagrant box in order to test your libraries and tools on Mono (though often a Travis build is simpler, see above) A detailed guide of setting up Vagrant is available here.

Dos and Don’ts

Developing Cross-Platform and Multi-Targeting Type Providers

F# type providers are compile-time components that must execute on your machine during build and development.

A type provider executing on Mac/Linux can expose some small differences in the implementation of .NET, for example in the System.Type implementation. The ProvidedTypes API can normally be adjusted to account for these.

To help isolate the problem, try the following:

Switching to command-line compilations will help localize the problem.

Having trouble?