-
Notifications
You must be signed in to change notification settings - Fork 1
Migrate fsproj To .NET CLI
DOESNT WORK WITH PREVIEW1 WITHOUT CHANGES, is not updated, but the procedure is the same
SEE SUAVE AS EXAMPLE
- Suave: https://github.com/SuaveIO/suave/
- Suave .NET Core example: https://github.com/SuaveIO/Suave-CoreCLR-sample
The idea is not to convert everything to project.json
It's possibile to:
- build .NET 4.0/mono package as usual (fake/paket/rake/msbuild)
- build .NETStandard1.5 package with project.json and .NET Core SDK
- add built .NETStandard1.5 to the original package with
dotnet mergenupkg
( https://github.com/enricosada/dotnet-mergenupkg )
- Convert existing fsproj to project.json
- Create a test project to smoke check the library
- add NET Core framework
- Fix all build errors
- add NET Core framework to test project
- add Appveyor build using .NET CLI
- add Travis build using .NET CLI
The idea is to:
- convert fsproj to .NET CLI and
project.json
- build the project with .NET CLI using framework .NET 4.6
- create a smoke test to check .NET 4.6 works
- add .NET Core (
netstandard1.5
) framework - fix errors and recheck with same test project
This project use FsCheck as an example
Other sources are:
Older migrations, using deprecated dnxcore50
framework (but .NET Full => .NET Core errors are the same)
The project.json
it's parallel to .fsproj, you can add it without changing the fsproj
-
cd in the
fsproj
directory -
exec
dotnet new --lang f#
to create a new project withproject.json
( 37bbdcf )Expected:
Created new F# project in e:\github\FsCheck\src\FsCheck.
-
Remove the generated file
Program.fs
(the main of console app) ( 781e72c )Remove also the
"Program.fs",
from the propertycompileFiles
inproject.json
The useful files are:
-
Nuget.config
contains the dev nuget feed of .NET cli and F# -
project.json
the project file, like the old.fsproj
-
-
If it's a library, remove the
"emitEntryPoint": true
fromproject.json
( a762f8d )The
emitEntryPoint
property specify if a project is a console app (true
) or a library (false
or not specified)
Add all the files from fsproj inside the compileFiles
property in project.json
( 99de1c2 )
The source files are these with xml element <Compile />
<Compile Include="Utils.fs" />
to property compileFiles
in project.json
"Utils.fs",
TIP If a file has \\
in path, use /
instead, less problem with escaping json
NOTE All path are relative to project.json
, like msbuild .fsproj
NOTE The <Link>
msbuild property is not supported by project.json
, it use the file system tree, ignore it
Let's add back the .NET 4.6 references
-
Move the
dependencies
property insidenetstandard1.5
( a542f4f )"dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160316", "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23925" } },
into
framework
.netstandard1.5
"frameworks": { "netstandard1.5": { "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160316", "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23925" } }, "imports": [ "portable-net45+win8", "dnxcore50" ] } }
NOTE
project.json
doesnt support comments -
In
project.json
addnet46
insideframeworks
( 0cc9c8a )Now
frameworks
is like"frameworks": { "net46": { }, "netstandard1.5": {
-
Add all framework (GAC) reference of the
.fsproj
toproject.json
( c9e8d64 )Only framework assemblies (no nugets) Except
mscorlib
,FSharp.Core
add all<Reference />
toframeworkAssemblies
undernet46
An example:
From
<Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="System.Xml" />
To
"net46": { "frameworkAssemblies": { "System": "", "System.Core": "", "System.Xml": "" } }
-
Add FSharp.Core and nuget packages ( 84daf2f )
This example use the
FSharp.Core
nuget package, not the GAC version You can use the GAC version insideframeworkAssemblies
, but it's better use the nuget packageAdd a
dependency
property undernet46
with all packages and versionAn example:
"net46": { "dependencies": { "FSharp.Core": "4.0.0.1" }, "frameworkAssemblies": {
Add also the used nuget packages
NOTE the order of properties or packages doesnt matter, but specific version yes
TIP thefsproj
or nugetpackages.config
orpaket.lock
contains the exact version used -
The .NET 4.6 version is ready, build it!
-
cd
in the project directory -
dotnet restore
should restore all packagesExpected output (and exit code 0):
log : Restoring packages for e:\github\FsCheck\src\FsCheck\project.json... info : Committing restore... log : Writing lock file to disk. Path: e:\github\FsCheck\src\FsCheck\project.lock.json log : e:\github\FsCheck\src\FsCheck\project.json log : Restore completed in 2201ms. NuGet Config files used: e:\github\FsCheck\src\FsCheck\NuGet.Config C:\Users\e.sada\AppData\Roaming\NuGet\NuGet.Config Feeds used: https://dotnet.myget.org/F/dotnet-core/api/v3/index.json https://api.nuget.org/v3/index.json https://www.myget.org/F/fsharp-daily/api/v3/index.json
-
dotnet build --framework net46
to compile the project using only the .NET 4.6 frameworkNOTE
dotnet build
build all frameworks insideproject.json
NOTE to build onlynet46
use--framework
, likedotnet build --framework net46
Expected output (and exit code 0):
Compiling FsCheck for .NETFramework,Version=v4.6 Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:13.6352964
-
add ignore of
project.lock.json
(in .gitignore), it should never go inside repository ( 4bfa34c ) -
Check if file
<projectdir>/bin/Debug/net46/<projectdirname>.dll
existsNOTE the name of assembly is always the name of directory with a
project.json
project
TIP if you want to change the name, create a dir with the new name and reference files with relative path inproject.json
-
Let's create a test project to smoke test the library.
It's not the full suite of test, only to check it's working
TIP It's possibile to move it in another directory (like <root>/test
) when the migration is done
TIP You can use also dotnet test
with xunit
, see the page dotnet-test
-
Create in the parent directory a new directory
<projectname>.Dotnetcli.Tests
-
cd
inside that directory -
dotnet new --lang f#
to create the project ( 4409899 ) -
remove
dependencies
and change framework tonet46
-
Add a project reference to the project ( 0fd7fc1 )
In the
project.json
of test project, add the reference to project (in the example isFsCheck
)"frameworks": { "net46" : { "dependencies": { "FsCheck": { "version": "1.0.0", "type": "build" } } } }
-
Build it!
-
in the test project directory
-
dotnet restore
-
dotnet build
The expected output ( see the
FsCheck
project is rebuilt if needed ):Project FsCheck (.NETFramework,Version=v4.6) was previously compiled. Skipping compilation. Compiling FsCheck.Dotnetcli.Tests for .NETFramework,Version=v4.6 Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:05.3692070
-
Run it! with some arguments
a
andb
The built binary is in the
bin/<configuration>/<framework>/<os>/<projectname>.exe
TIP you can execute the .exe directly or use
dotnet run --framework net46 -- a b
Execute:
.\bin\Debug\net46\win7-x64\FsCheck.Dotnetcli.Tests.exe a b
Output:
Hello World! [|"a"; "b"|]
-
Add your specific tests ( 303519c )
-
Build and run the test project to check it's working
-
-
Move back to the project directory
-
If Library, fix in
project.json
thedependencies
of .NET Core framework (netstandard1.5
alias) ( ec177ae )Instead of
Microsoft.NETCore.App
use theNETStandard.Library
NOTE the version of
NETStandard.Library
is1.5
not1.0
(1.5
likenetstandard1.5
)"frameworks": { "net46": { ... }, "netstandard1.5": { "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160316", "NETStandard.Library": "1.5.0-rc2-23925" }, "imports": [ "portable-net45+win8", "dnxcore50" ] }
-
Copy the
net46
nuget dependencies in thedependancies
nodeNOTE it's ok the FSharp.Core package name is different TIP if a package doesnt support netcore, maybe there is a dev built package, ask package team TIP You can add additional nuget feeds inside
Nuget.config
-
The
project.json
is changed, so redodotnet restore
-
Now when can try to build it, do
dotnet build
to build all configurationTIP
dotnet build
build all frameworks
TIP to build onlynetstandard1.5
use--framework
, likedotnet build --framework netstandard1.5
-
Now the build should fail with errors, it's ok
- maybe some reference are missing (for example
System.Xml
is not in standard library anymore) - .NET Desktop <-> .NET Core differences
- maybe some reference are missing (for example
See more info in the Migration-NETCore-Common-Issues
-
Fix all missing packages
You can check all packages used in
project.json.lock
- add packages in the
dependancies
undernetstandard1.5
inproject.json
-
dotnet restore
required becauseproject.json
changed dotnet build
- GOTO 10
TIP version suffix is usually the same of
NETStandard.Library
, so in this example is-rc2-23925
NOTE check thedotnet restore
outputFor example in another conversion (Argu) adding
"System.Xml.XmlDocument": "4.0.0-rc2-23811"
, but got the warningwarn : Dependency specified was System.Xml.XmlDocument (>= 4.0.0-rc2-23811) but ended up with System.Xml.XmlDocument 4.0.1-rc2-23811.
That mean you can change the version inside
project.json
to4.0.1-rc2-23811
directly - add packages in the
-
Fix all code errors ( e983b06 )
NOTE You can use compiler directive
NETSTANDARD1_5
to#if
the code for frameworknetstandard1.5
NOTE each framework define an upper case alias, sonet46
defineNET46
compiler directiveIf you change only the source files (.fs), you can do
dotnet build
onlyFor big missing features, it's easier to #ifdef out the not supported code
#if NETSTANDARD1_5 //netcore #else //else #endif
TIP F# 4.0 syntax help
#if !NETSTANDARD1_5
TIP F# 4.0 syntax help#if PCL || NETSTANDARD1_5
-
If there strange errors, f# netcore is beta, so submit a bug report in the Microsoft/visualfshar repo
-
Add
netstandard1.5
framework anddependancies
( 5ce86a0 )
"frameworks": { "netstandard1.5" : { "dependencies": { "FsCheck": { "version": "1.0.0", "type": "build" }, "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-23925" } }, "imports": [ "portable-net45+win8", "dnxcore50" ] }, "net46" : {
1. `cd` in test project directory
1. `dotnet restore`
1. `dotnet build` to check it's ok (it' optional because `dotnet run` build too)
1. `dotnet run --framework netstandard1.5 -- a b` run with arguments `a` `b`
<a name="#appveyor" />
## Add Appveyor build using .NET CLI
See https://github.com/enricosada/fsharp-dotnet-cli-samples/blob/master/appveyor.yml for a working version
the script download an install the binaries in a subdirectory `.dotnetcli`, and add it to `PATH`
<a name="#travisci" />
## Add Travisci build using .NET CLI
See https://github.com/enricosada/fsharp-dotnet-cli-samples/blob/master/.travis.yml for a working version
the script download an install the binaries in a subdirectory `.dotnetcli`, and add it to `PATH`