Passing build properties with FAKE (F# Make)

Working to compile Simple.Web on Mono this week needed to pass properties to xbuild via build tool "FAKE" (F# Make), although the solution applies equally to Windows/MSBuild.

Note

I'm new to both F# and FAKE having only spent a few hours delving into the source-code; as such it's likely their is a better way of achieving the below. If you are interested in FAKE I suggest hooking yourself up to the Google Group.

Example

In this scenario Sandbox.csproj uses $(VSToolsPath) in it's project file, as xbuild/Mono won't substitute this upon compilation I need to pass our path in as a property. We are also capitalising our build target as FAKE is case-sensitive in this regard.

First of all let's update our script with a parameter that defaults:

#!/bin/bash
TARGET=$1
BUILDTARGETS=$2

if [ -z "$BUILDTARGETS" ]
    then
    BUILDTARGETS="/Library/Frameworks/Mono.framework/Libraries/mono/xbuild/Microsoft/VisualStudio/v9.0"
fi

if [ -z "$TARGET" ]
    then
    CTARGET="Default"
else
    CTARGET=`echo ${TARGET:0:1} | tr "[:lower:]" "[:upper:]"``echo ${TARGET:1} | tr "[:upper:]" "[:lower:]"`
fi

if [ ! -d "$BUILDTARGETS" ]
    then
    echo "BuildTargets directory '${BUILDTARGETS}' does not exist."
    exit $?
else
    export BUILDTARGETS="$BUILDTARGETS"
fi

echo "Executing command: $CTARGET"

mono packages/FAKE.1.64.6/tools/Fake.exe build.fsx target=$CTARGET

Now we need to update our FAKE .fsx file to pass this to the build process. This requires us to first retrieve the environment variable with environVarOrDefault and bypass the usual MSBuildRelease and MSBuildDebug methods going instead directly to MSBuild:

#I @"packages/FAKE.1.64.6/tools"
#r "FakeLib.dll"
open Fake

let buildDir = @"./build/"
let testDir = @"./test"

let fxReferences = !! @"*/*.csproj"
let testReferences = !! @"Tests/**/*.csproj"
let buildTargets = environVarOrDefault "BUILDTARGETS" ""

Target "Clean" (fun _ ->
    CleanDirs [buildDir; testDir]
)

Target "Build" (fun _ ->
    MSBuild buildDir "Build" ["Configuration","Debug"; "VSToolsPath",buildTargets] fxReferences
        |> Log "Build-Output: "
)

Target "BuildTest" (fun _ ->
    MSBuildRelease testDir "Build" testReferences
        |> Log "Test-Output: "
)

Target "Test" (fun _ ->
    !! (testDir  + @"/*.Tests.dll")
        |> xUnit (fun p ->
            { p with
                ShadowCopy = true;
                HtmlOutput = true;
                XmlOutput = true;
                OutputDir = testDir })
)

"Clean"
  ==> "Build"

"Build"
  ==> "BuildTest"

Target "Default" DoNothing

RunParameterTargetOrDefault "target" "Default"

Note: If you are running Mono 2.11 + it is likely that fsi and fsc have been replaced with fsharpi and fsharpc, I suggest you (like me) create two bash scripts to redirect any calls by FAKE (see fsc:here and fsi:here).