My second step in learning a new programming language is understanding the build system for the project: how to get an actual working program from my code.
My approach to this step for F# in particular is interesting. It isn't interesting because I don't understand it. It is interesting because I have an emotional reaction to it. I'll explain that later.
The fundamental component of the F# build system is the FSPROJ file. This is automatically created when you use the CLI to create a new project. An FSPROJ file is just an XML file telling the .NET SDK which SDK to use, which files to compile, and what other packages are needed for this project to build correctly. Below is the default FSPROJ file from the default Hello World project:
<project sdk="Microsoft.NET.Sdk"> <propertygroup> <outputtype>Exe</outputtype> <targetframework>netcoreapp3.1</targetframework> </propertygroup> <itemgroup> <compile include="Program.fs"> </compile></itemgroup> </project>
The first thing to know about F# project files is that they are part of MSBuild. MSBuild is the build utility that is used for C# and F# projects in the .NET space. To really dig into the project file, one needs to fully understand MSBuild. This post will not cover MSBuild.
The basics of the FSPROJ file are pretty easy to understand. The very first line specifies the SDK that should be used when building this project. The default entry will use the "default" SDK that you have specified on your workstation. (For the purposes of getting introduced to the language, this is fine.) Next up in the file you have the <PropertyGroup> tag. This grouping of elements tells the SDK what type of output to create (i.e. an executable, class library, etc.) along with the version of the framework to target. (If you are familiar with C# projects, you realize that there are many other options for this grouping. For the purposes of starting with F#, this is sufficient.) The last grouping is the <ItemGroup> section. This section lists the files that are included in this particular project.
I noticed that the FSPROJ file differs from the C# CSPROJ file in that the F# file lists the code files that are included in the project, where a CSPROJ does not. It turns out there are some peculiarities with having multiple F# code files in a project. I have not yet gotten that aspect figured out, so I will plan on an additional post once I understand that better.
The other oddity that I've noticed is that the only difference that I can see on the surface between an FSPROJ file and a CSPROJ file are the names (although the paragraph above points to another difference). I'm not sure why the two languages have differently named project files that come from the same build system. A quick internet search didn't reveal an obvious answer, so I'm still trying to figure that out.
And here begins my emotional reaction. <rant>The following paragraph is a mini-rant. Feel free to skip to the end.</rant> I am still getting over the removal of project.json from .NET Core! I completely understand why they did it, but I don't like, and I don't think I agree with it. Had they left project.json, it could have been a universal project file for both C# and F#. How cool would that be?!? Ok. I'm done.
For a basic application, the default project file works well. Most of the interaction I'm going to have with it is through the CLI tools for building, running, and adding references to my projects. This cursory understanding is enough to dive into the other areas of learning, but I know where to look if I need to do something more sophisticated.