An Open F# conference workshop
If you have an existing project and want to add support for .NET Standard or .NET Core, there are three parts to consider
NOTE The .NET Sdk doesnt support just .NET Core/Standard, but also normal .NET Framework.
That mean you can create a console app/lib to just target net461
(.NET Framework 4.6.1).
Or both, so .net core (netcoreapp2.0
) and net461
Best way is:
If you dont have a project you want to convert, you can try with
https://github.com/fsprojects/FSharpx.Collections
The only rule are:
paket.dependencies
if exists)cd src
mkdir FSharpx.Collections.NetStandard
dotnet new lib -lang F# -n FSharpx.Collections -o .
delete useless source file
Now copy the compile list to new lib from source lib
fix path of Compile/None items
replace
Include="
with
Include="..\FSharpx.Collections\
remove app.config
, useless on .net core
or make it conditional on target framework, if you want to maintain it.
dotnet build
dotnet pack
it. Done.
For tests, dependes on test framework. Here is NUnit
See the avaiable templates list for dotnet new
dotnet new -i "NUnit3.DotNetNew.Template::*"
now let’s create the project.
cd tests
mkdir FSharpx.Collections.Tests.NetStandard
dotnet new nunit -lang F#
Tests can be run with dotnet test
.
Let’s reuse the existing tests now.
First remove the UnitTest1.fs
generated by template.
After that, copy the same test list from source project, and update paths of Compile
items
The dependencies in paket.references
are FsCheck
and FsUnit
.
The FsCheck
has a prerelease version who support .NET Standard, so let’s try use that.
dotnet add package FsCheck --version 3.0.0-alpha1
and FsUnit
dotnet add package FsUnit --version 3.0.0
Now just the project reference to library:
dotnet add reference ..\..\src\FSharpx.Collections.NetStandard\FSharpx.Collections.fsproj
and let’s test it with
dotnet test
And there are errors. Usually because we upgraded version of out dependencies
TIP creating a solution now may help, because vscode can load just these projects From root of repo:
dotnet new sln -n FSharpx.Collections.NetStandard
dotnet sln FSharpx.Collections.NetStandard.sln add src\FSharpx.Collections.NetStandard\FSharpx.Collections.fsproj
dotnet sln FSharpx.Collections.NetStandard.sln add tests\FSharpx.Collections.Tests.NetStandard\FSharpx.Collections.Tests.NetStandard.fsproj
And reload workspace with
> F#: Change Workspace or Solution
Now back to the errors:
The nunit constraint NullOrEmptyStringConstraint
doesnt exists anymore.
Quick fix, ifdef the code based on target framework. Better is to do it based on nunit version (or update the nunit for .net too)
#if NETCOREAPP2_0
#else
let NullOrEmptyString = new NullOrEmptyStringConstraint()
#endif
also #if !NETCOREAPP2_0
can be used, if the project doesnt want to support older compilers
and fix build errors and tests until works :D
Run
dotnet pack -c Release
or dotnet pack -c Release /p:Version=1.2.3
to generate a specific version
The -c Release
with build it in Release
configuration, if needed
Is possibile to make the project target both frameworks (so net461
and netstandard2.0
) using TargetFrameworks
(plural)
And creating the package with just one dotnet pack
, so pratically replacing the old way.
But if you want to just add netstandard, we can use the old way, so no changes needed for .NET Framework
This can be done using a .net cli tool: dotnet-mergenupkg
The idea is to use dotnet mergenupkg
to add the .net standard part of the just built package, to the existing package
Is a .net cli tool, so can be added to any project adding a <DotnetCliToolReference
, but because is a generic tool, can be moved in a shared tools project, because not really related to the project itself
Create a directory tools and change current directory to it.
Create a tools.proj
. It’s just an empty proj with the .net cli tool reference
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<DotNetCliToolReference Include="dotnet-mergenupkg" Version="2.*" />
</ItemGroup>
</Project>
and restore it with
dotnet restore
Now when the current directory is this directory can be executed with dotnet mergenupkg
(no -
sign), like:
dotnet mergenupkg --help
We can now use that to merge the two packages:
dotnet mergenupkg --source ../bin/FSharpx.Collections.1.17.0.nupkg --other ../src/FSharpx.Collections.NetStandard/bin/Release/FSharpx.Collections.1.0.0.nupkg --framework netstandard2.0
And the package now support .NET Standard 2.0 and is ready to be published
The result of this, is in the PR fsprojects/FSharpx.Collections#80
Use paket instead of project references, some info in paket docs