An F# eXchange 2018 workshop
In a sample1
directory, run
mkdir sample1 && cd sample1
Now let’s create a console app
RUN
dotnet new console -lang f#
let’s open code to inspect it, run
code .
A normal console app is:
sample1.fsproj
: the project file.Program.fs
: the source fileOpen the Program.fs
in the editor
This is the entrypoint of the of the program, the main
and the args passed to the console app
When ionide is started, make the F# PROJECT EXPLORER
visible on bottom-left corner of code.
This contains the projects loaded
Now, let’s build it. It can be done in the the terminal
TIP code has an embedded terminal. Open it with View -> Integrated Terminal
run
dotnet build
This compile the project and show the output:
Microsoft (R) Build Engine version 15.6.82.30579 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 37,31 ms for E:\fsharpx\sample1\sample1.fsproj.
sample1 -> E:\fsharpx\sample1\bin\Debug\netcoreapp2.0\sample1.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.23
So the output is bin/Debug/netcoreapp2.0/sample1.dll
To run it:
dotnet bin/Debug/netcoreapp2.0/sample1.dll
Now let’s pass some arguments. First change the program to print the arguments.
DO add to the main
printfn "%A" argv
Now another time, compile and execute. Run:
dotnet build
dotnet bin/Debug/netcoreapp2.0/sample1.dll a b --other a
A faster way to do it, is use dotnet run
command, who does the same thing
dotnet run -- a b
What if i want to use my app in another machine?
Two possibilities of deployment:
framework dependent
(FDD)
dotnet app.dll
self contained
(SCD)
app.exe
or app
)Run
dotnet publish
This create the bin/Debug/netcoreapp2.0/publish/
directory
who can be copied in another machine, and run with
dotnet sample1.dll
Run
dotnet publish --runtime win-x64 --output out
and that directory out
contains sample1.exe
you can run directly as out\sample1.exe 1 2 3
Doing the same for osx
dotnet publish --runtime osx-x64 --output outosx
Or linux, run
dotnet publish -r linux-x64 -o outlinux -c Release
NOTE on linux .net core apps has some requirements, like the libunwind
package installed (see docs)
NOTE to know your local os runtime id (called RID
like osx-64
), just do dotnet --info
Runtime Environment:
OS Name: Windows
OS Version: 10.0.16299
OS Platform: Windows
RID: win10-x64
NOTE is possibile to bundle these deps as local copies, ref https://github.com/dotnet/core/blob/master/Documentation/self-contained-linux-apps.md
NOTE the runtime can be specified also in the fsproj
<RuntimeIdentifiers>win10-x64;osx-x64</RuntimeIdentifiers>
To run it in debugging, without any setting, just:
Debug
Let’s configure VS Code to build/debug this project VSCode use tasks to run things.
> Tasks: Configure Default Build Task
create task.json from template
.NET Core
If there are no error, default behavior is not show message. you can override with
"presentation": {
"reveal": "always"
},
To run it:
> Tasks: Run Build Task
build
So now the default run build use that
If there is an error, are shown in PROBLEMS
tab
You can move between errors with
> Go to Next Problem
Now, to debug
F# PROJECT EXPLORER
Debug
Or you can create a launch.json
with info about debug with:
> Debug: continue
.NET Core
program
path to output assemblynow F5
and > Debug: continue
will run as usual
For example we need to parse the command line arguments We want to use Argu library
to manage the packages in the project, we can use the dotnet add
and dotnet remove
commands
dotnet add package Argu
this add a packagereference to the project
<PackageReference Include="Argu" Version="3.7.0" />
and restore the project (download the package).
We can now use argu to manage command line args First declaring the arguments
open Argu
type CLIArguments =
| Port of tcp_port:int
with
interface IArgParserTemplate with
member s.Usage =
match s with
| Port _ -> "specify a primary port."
and doing the parsing in the main
let parser = ArgumentParser.Create<CLIArguments>(programName = "sample1")
try
let args = parser.Parse argv
match args.GetAllResults() with
| [Port p] -> printfn "set port %i" p
| _ -> ()
0 // return an integer exit code
with
| :? ArguParseException as ex ->
printfn "%s" ex.Message
1
| ex ->
printfn "Internal Error:"
printfn "%s" ex.Message
2
to check is working:
dotnet run -- --help
dotnet run -- --port 81
NOTE by default configuration, the --help
raise an exception in Argu.
Try with debugging, you can see the ex.ErrorCode
is HelpText
The sdk support multi target framework as first class.
Change from
<TargetFramework>netcoreapp2.0</TargetFramework>
to the PLURAL, the is an s
at end ( <– PLURAL )
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
You can add all tfm you want netcoreapp2.0;net452;net462
etc.
Same for libraries
Now just restore
dotnet restore
and to build all frameworks, just dotnet build
Use dotnet build -f netcoreapp2.0
to build just one.
All commands (test
, etc) have a --framework
of -f
parameter
You can conditionally add msbuild items (like Compile
, PackageReference
or ProjectReference
) with the attribute Condition=" '$(TargetFramework)' == 'netcoreapp2.0' "