When I add the example xUnit2 target to my FAKE build file, I'm getting this error:
error FS0001: This expression was expected to have type
string option
but here has type
string
Target Example from FAKE xunit2 documentation
Target "Test" (fun _ ->
!! (testDir ## "xUnit.Test.*.dll")
|> xUnit2 (fun p -> {p with HtmlOutputPath = (testDir ## "xunit.html")})
)
The Visual Studio is highlighting the (testDir ## "xunit.html") section of the code.
I understand that it's expecting two parameters, but I don't know enough F# yet to figure out how to fix the problem:
Prior to including the xUnit target, my FAKE build was working fine.
I've added open Fake.Testing.XUnit2 to the build file and I get no error with the xUnit2 reference.
Any help would be appreciated.
So the error is that the type of HtmlOutputPath is
HtmlOutputPath : string option
In Fake I believe that ## does Path.Combine so testDir ## "xunit.html should have type string.
To get the types to match, you can use
HtmlOutputPath = Some(testDir ## "xunit.html")
This suggests that the documentation for FAKE is incorrect.
Related
I'm trying to use FAKE to build my F# project.
The build.fsx looks like below and works fine.
#r "packages/FAKE/tools/FakeLib.dll"
open Fake
Target "Default" (fun _ ->
trace "Hello World from FAKE"
)
RunTargetOrDefault "Default"
Then I want to use fsc from FAKE. Following the official tutorial, I added one line open Fake.FscHelper and get below error message:
#r "packages/FAKE/tools/FakeLib.dll"
open Fake
open Fake.FscHelper
// this value is not a function and can not be applied
// union case FscParam.Target: TargetType -> FscParam
Target "Default" (fun _ ->
~~~~~~~~~~~~~~~~
trace "Hello World from FAKE"
)
RunTargetOrDefault "Default"
I appreciate if anyone can give me any advice.
I'm using VS Code on Mac with Mono 4.2.1.
And my paket.lock looks like below:
NUGET
remote: https://www.nuget.org/api/v2
specs:
FAKE (4.21.0)
FSharp.Core (4.0.0.1)
FsUnit (2.0.0)
FSharp.Core (>= 3.1.2.5)
NUnit (3.0.1)
NUnit (3.0.1)
This happens because the module FscHelper defines a constructor called Target (see source), and that constructor conflicts with the Target function from the TargetHelper module. There is an issue filed about it.
Until the issue is fixed, there are three ways to work around this ambiguity:
Don't open FscHelper, just use all its innards in a qualified manner (e.g. FscHelper.Compile etc.)
Re-alias the TargetHelper.Target function in the local scope:
open Fake
open Fake.FscHelper
let Target = TargetHelper.Target
Target "Default" (fun _ ->
trace "Hello World from FAKE"
)
Reorder the open statements:
open Fake.FscHelper
open Fake
And since you're using this helper, note that the documentation for it is outdated. In particular, the Fsc task is deprecated in favor of the Compile task (see source).
Change the order of the open statements
#r #"packages/FAKE/tools/FakeLib.dll"
open Fake.FscHelper
open Fake
Target "a" (fun _ ->
["a.fs"] |> Compile []
The order of your open statements determines the precedence of the name resolution with the later opened modules and namespaces taking precedent.
I am working through the Embedding F# Interactive example from http://fsharp.github.io/FSharp.Compiler.Service/interactive.html but am having an issue with the following line throwing an exception:
let fsiSession = FsiEvaluationSession.Create(fsiConfig, allArgs, inStream, outStream, errStream)
The exception thrown is:
"An unhandled exception of type 'System.Exception' occurred in FSharp.Compiler.Service.dll
Additional information: Error creating evaluation session: StopProcessing null"
My project is being run from VS2015 Enterprise Update 1, setup as a simple F# console app, with Target F# runtime being F# 4.0 with the Target Framework as 4.6. The version of FSharp.Compiler.Service downloaded from nuget is 2.0.0.2.
The Program.Fs file code I am running is here (a direct port of the example):
open System
open System.IO
open System.Text
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.FSharp.Compiler.Interactive.Shell
[<EntryPoint>]
let main argv =
let sbOut = new StringBuilder()
let sbErr = new StringBuilder()
let inStream = new StringReader("")
let outStream = new StringWriter(sbOut)
let errStream = new StringWriter(sbErr)
// Build command line arguments & start FSI session
let argv = [| "C:\\fsi.exe" |]
let allArgs = Array.append argv [|"--noninteractive"|]
let fsiConfig = FsiEvaluationSession.GetDefaultConfiguration()
let fsiSession = FsiEvaluationSession.Create(fsiConfig, allArgs, inStream, outStream, errStream)
/// Evaluate expression & return the result
let evalExpression text =
match fsiSession.EvalExpression(text) with
| Some value -> printfn "%A" value.ReflectionValue
| None -> printfn "Got no result!"
evalExpression "42+1" // prints '43'
Console.ReadLine() |> ignore
0 // return integer
Any thoughts would be appreciated.
The key to your problem is found at Compiler Services: Notes on FSharp.Core.dll
If doing dynamic compilation and execution you may also need to
include an FSharp.Core.optdata and FSharp.Core.sigdata, see below for
guidance.
When you build the application the output directory with FSharp.Core.dll is missing two files:
FSharp.Core.optdata
FSharp.Core.sigdata
You will need to find these two files and the correct versions of the files that agree with FSharp.Core.dll and copy them to the build output directory.
How to find the files using Visual Studio
From menu View -> Solution Explorer
Expand Project
Expand References
Right click FSharp.Core and select properties.
The Full Path gives the directory that should have at least the three files.
Use a file explorer to open the directory in Full Path.
Copy the two files
FSharp.Core.optdata
FSharp.Core.sigdata
to the build directory.
How to find the build directory using Visual Studio
From menu View -> Solution Explorer
Select Project
Press F4 to open the Properties Page
The Project Folder with \bin\Debug is the default when debugging with VS.
Change location of fsi.exe
Now that you have the two needed files you will also need to change the location of fsi.exe
let argv = [| "C:\\fsi.exe" |]
because I doubt that fsi.exe is in the root of your C drive.
I want to automate the build process of my project using FAKE which requires me to run a grunt task.
In particular, I want to create a target that runs the grunt build task in a subfolder of the solution folder. Due to my lack of F# knowledge, I was not able to pass multiple parameters to the static Exec method of the Shell class. https://fsharp.github.io/FAKE/apidocs/fake-processhelper-shell.html
This is what I have got so far:
Target "RunGrunt" (fun _ ->
let errorCode = Shell.Exec "grunt" "build" "\Frontend"
()
)
This fails with the following error message:
build.fsx(38,23): error FS0003: This value is not a function and cannot be applied
If I remove the last 2 parameters, it works, but fails to find grunt at runtime:
System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at Fake.ProcessHelper.start(Process proc) in C:\code\fake\src\app\FakeLib\ProcessHelper.fs:line 22
at Fake.ProcessHelper.asyncShellExec#424-2.Invoke(Process _arg1) in C:\code\fake\src\app\FakeLib\ProcessHelper.fs:line 428
at Microsoft.FSharp.Control.AsyncBuilderImpl.callA#851.Invoke(AsyncParams`1 args)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.FSharp.Control.AsyncBuilderImpl.commit[a](Result`1 res)
at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously[a](CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout)
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
at FSI_0001.Build.clo#34-6.Invoke(Unit _arg5) in D:\Development\Repos\FMVEAv2\Fmvea2-frontend\build.fsx:line 36
at Fake.TargetHelper.runSingleTarget(TargetTemplate`1 target) in C:\code\fake\src\app\FakeLib\TargetHelper.fs:line 483
Grunt is included in the path variable. (it works if called from the command line)
My questions are:
How can I pass multiple parameters to the Shell.Exec method?
How to run grunt, without including the complete path to it?
Both problems are now solved.
John pointed out in a comment to use tuple style instead of curried form which results in the following code:
Shell.Exec( "grunt","build","\FrontEnd")
FAKE provides a method to find a file on the path. http://fsharp.github.io/FAKE/apidocs/fake-processhelper.html
The target definition therefore looks like this:
Target "RunGrunt" (fun _ ->
let grunt = tryFindFileOnPath if isUnix then "grunt" else "grunt.cmd"
let errorCode = match grunt with
| Some g -> Shell.Exec(g, "build", "FrontEnd")
| None -> -1
()
)
neftedollar made a good point in the comments about cross platform compatiblity: Using the EnvironmentHelper to determine the platform and search for the correct executable of grunt.
I have 2 files: Asm.fs, AsmTest.fs
Asm.fs
namespace Assembler
[<Measure>] type ln
[<Measure>] type col
[<Measure>] type port
type Addr = int<ln> * int<col> * int<port>
module Asm =
let emptyAddr : Addr = (-1<ln>, -1<col>, -1<port>)
AsmTest.fs
module Assembler.Tests
[<Test>]
let someTest() =
let x = Asm.emptyAddr
When I debug someTest() code, I get that x = null, what am I doing wrong?
P.S. files in the different projects visual studio projects. Asm.fs in the Assembler project and AsmTest.fs in the AssemblerTest project.
I found an interesting behavior. My problem will be resolved, if I add some file (even empty) to the Assembler project. Can anyone explain this behavior?
The debugger sometimes has issues showing the correct values. For me however, having exactly the same Asm.fs and AsmTest.fs like this:
module Assembler.Tests
open NUnit.Framework
[<Test>]
let someTest() =
let x = Asm.emptyAddr
Assert.IsNotNull x
the test passes and if I set a breakpoint at the assertion, x is correctly shown as {(-1, -1, -1)}
As the code that you show does not compile as it is (Block following this let is unfinished. in someTest), could you try my test above and/or show your complete test method?
Using your code I can reproduce the behaviour. If I set my projects to console applications, my test will fail as well. So, it seems that for console projects, not having any other file or an [<EntryPoint>] surprisingly skips the initialization of module values. For me, the compiler at least issues a warning Main module of program is empty where I use x in the test. The solution to the problem is therefore:
make sure you treat warnings as errors
have an [<EntryPoint>] for console applications
use library projects for libraries
I am trying to set up a tiny F# console app with FSharp.Data referenced in the solution. I got the following error at runtime :
An unhandled exception of type 'System.TypeInitializationException' occurred in Anot_F1.exe
for this code (error in line 4) :
1 open FSharp.Data
2 type Anot_lines = CsvProvider<"anot1.csv",Separators=";">
3 let ll = Anot_lines.Load("anot1.csv")
4 for r in ll.Rows do
5 printfn "%A" r.ToString
In debug mode after line 3, I can see that the variable ll contains the proper Headers but does not show the rows.
My CSV file is :
tline;tcol;bline;bcol;anot
3;1;4;16;"Barack Obama has ... The US president"
3;1;3;12;"Barack Obama"
3;18;3;26;"ratcheted"
4;102;4;109;"agencies"
4;289;4;306;"financial pressure"
4;1;4;320;"The US president ...ure on the regime"
4;1;4;16;"The US president"
I am new to F# and especially have no experience on using type providers.
Any help greatly appreciated.
The issue is with line 3, you're using a method that loads CSV data from a URL. You need to use the GetSample() method. Also note that the "%A" format placeholder can print any value and doesn't require a ToString() call.
let ll = Anot_lines.GetSample()
for r in ll.Rows do
printfn "%A" r