I'm struggling to get started with F# on Linux using ProjectScaffold.
Specifically: I can't get a project to work with FsUnit/FsCheck/xunit. I
have F# 3.1 and mono 3.12.1 and I'm on Linux (Ubuntu) x64.
I start "MyProject" with:
$ git clone --depth=1 git#github.com:fsprojects/ProjectScaffold.git
$ cd ProjectScaffold && ./build.sh
Then I add a bit of code to "src/MyProject/Library.fs":
module MyProject.X
let four = 4
And then two tests to "tests/MyProject.Tests/Tests.fs":
module MyProject.Tests.X
open Xunit
open FsUnit.Xunit
open FsCheck
open FsCheck.Xunit
open MyProject.X
[<Fact>]
let ``Two plus two is four.`` () =
2 + 2 |> should equal four
[<Property>]
let ``Sorting a sorted list is idempotent.`` (l: int list) =
let s = List.sort l
s = List.sort s
This code works on Visual Studio where I manually added FsCheck, FsUnit, anx xunit 1.9.2 (it fails with later version
for some reason). My test project on Windows/Visual Studio has this config file:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FsCheck" version="1.0.4" targetFramework="net45" />
<package id="FsCheck.Xunit" version="1.0.4" targetFramework="net45" />
<package id="FsUnit.xUnit" version="1.3.0.1" targetFramework="net45" />
<package id="xunit" version="1.9.2" targetFramework="net45" />
<package id="xunit.runner.visualstudio" version="2.0.0" targetFramework="net45" />
</packages>
So I edit paket.dependencies to add these packages and remove Nunit:
source https://nuget.org/api/v2
nuget FSharp.Formatting 2.8.0
nuget FSharpVSPowerTools.Core 1.7.0
nuget FAKE
nuget FsCheck 1.0.4
nuget FsCheck.Xunit 1.0.4
nuget FsUnit.xUnit 1.3.0.1
nuget xunit 1.9.2
nuget SourceLink.Fake
github fsharp/FAKE modules/Octokit/Octokit.fsx
Then:
$ mono .paket/paket.exe install
...and it fails because NUnit is referenced somewhere, so I delete the references in tests/MyProject.Tests/paket.references and
$ mono .paket/paket.exe install
works, but
$ ./build.sh
fails, at it cannot find references to FsCheck et al. So I assume that I need to add the references manually, so tests/MyProject.Tests/paket.references is now:
FsCheck
FsCheck.Xunit
FsUnit.xUnit
xunit
...built build.sh fails again: it cannot find FsCheck. I could not find in the paket doc how to add a local dependency (MyProject.Tests should reference MyProject), it might be done automatically.
I had this problem and it took a while for me to figure out a fix. For the project file in the Tests directory, I had to change this:
<Reference Include="FsUnit.NUnit">
<HintPath>..\..\packages\FsUnit.1.3.0.1\Lib\Net40\FsUnit.NUnit.dll</HintPath>
<Private>True</Private>
</Reference>
To this:
<Reference Include="FsUnit.NUnit">
<HintPath>..\..\packages\FsUnit\Lib\Net40\FsUnit.NUnit.dll</HintPath>
<Private>True</Private>
</Reference>
Similarly, for NUnit:
<Reference Include="nunit.framework">
<HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
To:
<Reference Include="nunit.framework">
<HintPath>..\..\packages\NUnit\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
The issue is that on mono, the packages don't have the version in the path but under Visual Studio they do. Once I found this fix, I created two .fsproj files for the tests and I modified the build.sh script to swap the mono-compatible one in when under mono via:
#!/bin/bash
if test "$OS" = "Windows_NT"
then
# no changes in here
else
# fix test fsproj file
mv tests/ProjectName.Tests/ProjectName.Tests.fsproj tests/ProjectName.Tests/ProjectName.Tests.fsproj.vs
mv tests/ProjectName.Tests/ProjectName.Tests.fsproj.mono tests/ProjectName.Tests/ProjectName.Tests.fsproj
# leave the script logic for mono in place
# put project files back to avoid git noticing the swap
mv tests/ProjectName.Tests/ProjectName.Tests.fsproj tests/ProjectName.Tests/ProjectName.Tests.fsproj.mono
mv tests/ProjectName.Tests/ProjectName.Tests.fsproj.vs tests/ProjectName.Tests/ProjectName.Tests.fsproj
fi
Once I made these changes the project works fine under both Visual Studio as well as mono.
I am not quite sure, I understand you: Do you have two fsproj files, one for the production code and one for the unit tests? And are you referencing FsCheck in the fsproj?
Plus, I remember an issue, where if you compile against an older version of .net and reference an assembly compiled against a newer version of .net, it will behave as though there was no reference.
Related
I am trying to use .NET Core + Ionide + VS Code + Fake + Paket on macOS High Sierra.
Using the project generator, I have created a Suave application called Test. Ionide seems to have generated the appropriate files. After tweaking the TargetFramework to .NET Core, I can build successfully:
$ ./build.sh
...
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.72
Finished Target: Build
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target Duration
------ --------
Clean 00:00:00.0026904
InstallDotNetCLI 00:00:01.2292511
Restore 00:00:04.2731055
Build 00:00:07.1234434
Total: 00:00:12.7035334
---------------------------------------------------------------------
Status: Ok
---------------------------------------------------------------------
There are now some files in Test/bin, but none of them are .exe, which is what I would expect as output from fsharpc.
Where does Ionide + Fake put the output executable?
My project has OutputType executable:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Test.fs" />
</ItemGroup>
<Import Project="..\.paket\Paket.Restore.targets" />
</Project>
.Net Core compiles all projects (even executable applications) to .dll not .exe that can be run with dotnet PATH_TO_DLL. In the bin folder, in the subfolder for given framework target there should be file YOUR_PROJECT_NAME.dll that can be run with dotnet CLI.
To generate an exe you need to supply a run-time identifier. You can include this in the fsproj with
<PropertyGroup>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
</PropertyGroup>
but you don't need to do that. You can use VSCode's tasks.json file to set up a build task.
My suggestion is just to run the dotnet CLI:
dotnet build -c Release -r win10-x64
This will create an exe in the bin\release\netcoreapp2.0\win10-x64 folder. You can also dotnet publish if you want a self-contained directory to deploy (this can get large). The id for OSX will be something like osx-x64.
By default ionide generates an fsproj file that is targetting net461, and you might also need Fake 5 for dotnetcore. I also suggest you use paket in magic-mode, and commit the .exe to github (if you use git).
Update. With Matt Ward's help I traced this to a bad config file. The following ~/.config/NuGet/NuGet.Config works for me
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" protocolVersion="2" />
</packageSources>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
I can do the following without any problems:
/opt/mono/mono-5.2.0.196-tarball/bin/mono ~/nuget.exe install -version 2.6.4 nunit
However, when I try to compile fsharp under the same installation of Mono, I get the following error. This is in the fsharp4 branch. What might I be doing wrong, please? Many thanks.
Project "/dir/src/fsharp/FSharp.Build-proto/FSharp.Build-proto.fsproj"
(default target(s)): Target CallFsSrGen: Created directory
"obj/proto/./" Tool
/dir/src/fsharp/FSharp.Build-proto/../../../lib/bootstrap/4.0/fssrgen.exe
execution started with arguments:
/dir/src/fsharp/FSharp.Build/FSBuild.txt obj/proto/./FSBuild.fs
FSBuild.resx Target BeforeBuild: Executing: mono
--runtime=v4.0.30319 /dir/src/fsharp/FSharp.Build-proto/../../../.nuget/NuGet.exe restore
packages.config -PackagesDirectory packages Unable to find version
'2.6.4' of package 'NUnit'. Unable to find version '2.6.4' of
package 'NUnit.Runners'. /dir/src/FSharpSource.targets: error :
Command 'mono --runtime=v4.0.30319
/dir/src/fsharp/FSharp.Build-proto/../../../.nuget/NuGet.exe restore
packages.config -PackagesDirectory packages' exited with code: 1.
Task "Exec" execution -- FAILED Done building target "BeforeBuild"
in project
Check what version of NuGet you are using and what NuGet package sources are enabled. Either there no NuGet package sources enabled or you are using a NuGet v2 .exe with a NuGet v3 package source.
If there is no NuGet.Config file that is provided with the FSharp build source code you are using then check the package sources listed in the file ~/.config/NuGet/NuGet.config. I suspect that it only has the v3 package source https://api.nuget.org/v3/index.json which cannot be used with a NuGet.exe (v2). So you would either need to update the nuget.exe to a later version or add the NuGet v2 package source into your NuGet.Config file: https://www.nuget.org/api/v2/
I'm trying to setup a basic FAKE F# project that can run FsUnit but I cannot figure out how to solve the Method not found: 'Void FsUnit.TopLevelOperators.should(Microsoft.FSharp.Core.FSharpFunc`2<!!0,!!1>, !!0, System.Object)' errors.
I have read the following posts that seem to be related, but I'm apparently still not grokking it:
Main github issue
FSharp.Core packaging guidelines
FsUnit unable to test portable library (SO)
Another github issue
I have created a JunkTest library project with the following setup:
paket.dependencies
source https://www.nuget.org/api/v2
nuget FAKE
nuget FSharp.Core
nuget FsUnit
nuget NUnit
nuget NUnit.Console
paket.references
FSharp.Core
FsUnit
NUnit
JunkTest.fs
module JunkTest
open FsUnit
open NUnit.Framework
[<Test>]
let ``Example Test`` () =
1 |> should equal 1 // this does not work
//Assert.That(1, Is.EqualTo(1)) // this works (NUnit)
build.fsx (relevant part)
Target "Test" (fun _ ->
!! (buildDir + "JunkTest.dll")
|> NUnit3 (fun p ->
{p with OutputDir = "TestResults" }
)
)
Output
I see that FSharp.Core.dll is being copied from the local packages directory: Copying file from "c:\Users\dangets\code\exercism\fsharp\dgt\packages\FSharp.Core\lib\net40\FSharp.Core.dll" to "c:\Users\dangets\code\exercism\fsharp\dgt\build\FSharp.Core.dll".
And the nunit3-console execution: c:\Users\dangets\code\exercism\fsharp\dgt\packages\NUnit.ConsoleRunner\tools\nunit3-console.exe "--noheader" "--output=TestResults" "c:\Users\dangets\code\exercism\fsharp\dgt\build\JunkTest.dll"
I have tried to add a app.config file with the in the test project root directory with the following but it doesn't seem to solve the issue (NOTE I am not using Visual Studio - do I need to do anything special for the project to include the app.config file?):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Any and all help is appreciated.
EDIT: The solution was that I was not properly setting up the App.config file to get included in the build. All of the answers that said "just add this to your App.config file" didn't help me because VSCode doesn't add this to the fsproj file automatically.
The part that I added is:
<None Include="App.config" />
In the ItemGroup that contains the other <Compile Include=Foo.fs> lines.
This happens because of FSharp.Core version mismatch. See, your application references one version of FSharp.Core and FsUnit references another version. This means that the FSharpFunc<_,_> type is going to be different (coming from different assemblies) for you and FsUnit, which in turn means that the should function exported by FsUnit is not the same function that your code is looking for, because it has a parameter of a different type.
This is where the bindingRedirect comes in. You're absolutely correctly added it to app.config, but from your question about whether you're doing it correctly, I get a suspicion that you might not. The thing with app.config is, it's not actually the program configuration. Rather, it's the source code for program configuration. At compile time, this file gets copied to bin\Debug\Your.Project.dll.config, and only then it will get picked up at runtime. If you didn't add this file to the fsproj project file (which, I suspect, might be the case), then it's not getting copied to the right place during build, and thus isn't getting picked up at runtime.
Another reason for it still not working may be that you've specified an incorrect version of FSharp.Core in your app.config file. Which brings me to the next point.
Crafting that file by hand is a bit fragile: when you upgrade FSharp.Core to a new version (or Paket does it for you), you may forget to fix it in app.config and even if you don't, it's a bit of a hassle. But Paket can help you with that: if you add the redirects: on options to your paket.dependencies file, Paket will add the bindingRedirect cruft to your app.config automatically:
source https://www.nuget.org/api/v2
nuget FAKE
nuget FSharp.Core redirects: on
nuget FsUnit
nuget NUnit
nuget NUnit.Console
This sounds like an FSharp.Core version mismatch.
The NuGet package you're using ships with FSharp.Core 4.4 (not 4.3.1). I recommend modifying your binding redirect to use 4.4:
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.4.0.0" />
I'm trying to deploy my website from github to Azure but there are some errors showing up every time I try to do it, this is part of the log from Azure:
Command: "D:\home\site\deployments\tools\deploy.cmd"
Handling ASP.NET Core Web Application deployment with MSBuild.
MSBuild auto-detection: using msbuild version '14.0' from 'D:\Program Files (x86)\MSBuild\14.0\bin'.
Restoring NuGet package Microsoft.Extensions.Caching.Abstractions.1.0.0.
Restoring NuGet package Microsoft.Extensions.Caching.Memory.1.0.0.
Restoring NuGet package Microsoft.Extensions.DependencyInjection.1.0.0.
WARNING: Unable to find version '1.0.0' of package 'Microsoft.Extensions.Caching.Abstractions'.
D:\home\.nuget: Package 'Microsoft.Extensions.Caching.Abstractions.1.0.0' is not found on source 'D:\home\.nuget'.
https://api.nuget.org/v3/index.json: Could not find file 'D:\home\.nuget\microsoft.extensions.caching.abstractions\1.0.0\microsoft.extensions.caching.abstractions.1.0.0.nupkg'.
It does that for a lot of Nuget packages that I have, maybe all of them.
Then after the Warning messages, this other message is showed:
Restoring packages for D:\home\site\repository\src\LIGMarine\project.json...
Restoring packages for tool 'BundlerMinifier.Core' in D:\home\site\repository\src\LIGMarine\project.json...
Restoring packages for tool 'Microsoft.AspNetCore.Razor.Tools' in D:\home\site\repository\src\LIGMarine\project.json...
Restoring packages for tool 'Microsoft.AspNetCore.Server.IISIntegration.Tools' in D:\home\site\repository\src\LIGMarine\project.json...
Committing restore...
Writing lock file to disk. Path: D:\home\site\repository\src\LIGMarine\project.lock.json
D:\home\site\repository\src\LIGMarine\LIGMarine.xproj
Restore completed in 5151ms.
And then comes the error messages:
Errors in packages.config projects
Unable to find version '1.0.0' of package 'Microsoft.Extensions.Caching.Abstractions'.
D:\home\.nuget: Package 'Microsoft.Extensions.Caching.Abstractions.1.0.0' is not found on source 'D:\home\.nuget'.
https://api.nuget.org/v3/index.json: Could not find file 'D:\home\.nuget\microsoft.extensions.caching.abstractions\1.0.0\microsoft.extensions.caching.abstractions.1.0.0.nupkg'.
Feeds used:
D:\home\.nuget
D:\home\.nuget: Package 'System.Interactive.Async.3.0.0' is not found on source 'D:\home\.nuget'.
https://api.nuget.org/v3/index.json: Could not find file 'D:\home\.nuget\system.interactive.async\3.0.0\system.interactive.async.3.0.0.nupkg'
This is a resume of the Azure log, I have read about this errors and I have created a Nuget.Config file as I show in the picture, this file is inside the Solution Items folder
This is the code that I have inside the Nuget.Config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
</packageRestore>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<disabledPackageSources />
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>
According to this messages, the Nuget packages cannot be found...
Feeds used:
D:\home\.nuget
D:\home\.nuget: Package 'System.Interactive.Async.3.0.0' is not found on source 'D:\home\.nuget'.
https://api.nuget.org/v3/index.json: Could not find file 'D:\home\.nuget\system.interactive.async\3.0.0\system.interactive.async.3.0.0.nupkg'
Maybe it's not looking for the packages the way it should, I'm not sure what means this path: 'D:\home\.nuget\'
What should I do?
EDIT
These are the packages that are not being found, I don't think these are private packages that cannot be found within https://api.nuget.org/v3/index.json:
Microsoft.Extensions.Caching.Abstractions
Microsoft.Extensions.Caching.Memory
Microsoft.Extensions.DependencyInjection
System.Interactive.Async
System.Linq
System.Linq.Expressions
System.Linq.Queryable
System.Globalization
System.Reflection
System.ObjectModel
System.Resources.ResourceManager
System.Reflection.Extensions
System.Runtime
System.Runtime.Extensions
System.Runtime.InteropServices
Microsoft.Extensions.DependencyInjection.Abstractions
System.Threading.Tasks
System.Threading.Tasks.4.0.11
Microsoft.Extensions.Logging.Abstractions
Microsoft.Extensions.Logging.Abstractions.1.0.0
Microsoft.Extensions.Logging
Microsoft.Extensions.Options
Microsoft.Extensions.Primitives
Remotion.Linq
Newtonsoft.Json
System.Collections
System.Collections.Immutable
System.Diagnostics.Debug
System.Diagnostics.DiagnosticSource
System.Collections.Concurrent
System.ComponentModel
System.Threading
.
I have created a new website in Azure and now it works, it seems that the previous website was deploying a previous application from Github and there were some conflicts, everything works fine now
When I set up a new F# project in Xamarin Studio with a reference to Suave I get an error.
Here are the steps to reproduce the error message:
Create a new solution in Xamarin Studio 6. Type: Console Project in F#
Add the Suave nuget package: Suave 1.1.2
Open Program.fs and add this line on the top of the file: 'open Suave'
After this the word 'open' is decorated with red squiggles and when I move the mouse pointer over it a little pop up appears with this message:
Error: Multiple references to 'FSharp.Core.dll' are not permitted
Why does this error messages come up and how do I remove it?
What I have noticed is that the installation of the Suave nuget package had also caused the installation of the FSharp.Core nuget pakage. Here is the resulting packages.conf file:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="3.1.2.5" targetFramework="net45" />
<package id="Suave" version="1.1.2" targetFramework="net45" />
</packages>
This happens because the Xamarin's F# project template by default references the local copy of FSharp.Core.
Removing the (duplicated) reference should fix the issue.
I just updated Xamarin Studio to ignore the local copy of FSharp.Core if the project contains a reference to a NuGet version. Should be released in XS 6.1 cycle 8.