Easy TeamCity integration is one of the major goals for the FAKE build system.
“TeamCity is a Java-based build management and continuous integration server from JetBrains, creators of IntelliJ IDEA and ReSharper.”
[Wikipedia]
In this article I will show you how you can set up a FAKE build script in TeamCity. We will use the CalculatorSample which you can download from the FAKE Download page. If you want to know how this build script works read the “Getting started with FAKE”-tutorial.
Installing TeamCity
You can download the free professional edition of TeamCity from http://www.jetbrains.com/teamcity/. After the installation process (further instructions) you should be ready to configure your first build:

Creating a FAKE Project
Now create a new project and add a build configuration:


Attach a VCS root
The next step is to attach a VCS root. For this sample we will use the Calculator SVN root at http://fake.googlecode.com/svn/trunk/Samples/Calculator/.
[The only issue with this setting is, that you can’t change the path to the F# compiler. It is fixed to c:\Program Files (x86)\FSharp-1.9.6.2\bin\. If your path is different just reinstall F# to this location or use your own Version Control System.]


Choosing a build runner
We can use the Command Line build runner to start the completeBuild.fsx build script via Fake.exe. As the build provides NUnit test results we instruct TeamCity to import them:

If you want you could also add a build trigger to your build script:

Running the build
Now if everything is configured correctly, you can run your build and the output should look like:

You can also inspect the NUnit and FxCop results:

Tags:
Code Quality,
Continuous Integration,
F#,
F-sharp Make,
Fake,
FxCop,
nunit,
TeamCity
“FAKE – F# Make” is intended to be an extensible build framework. That’s why I tried to make it as easy as possible to create custom tasks. This posts shows how we can create a (very simple) custom task in C# which gives a random number.
First of all open Visual Studio and create a new C# class library called my MyCustomTask and create a class called RandomNumberTask:
using System;
namespace MyCustomTask
{
public class RandomNumberTask
{
public static int RandomNumber(int min, int max)
{
var random = new Random();
return random.Next(min, max);
}
}
}
Now compile this project and put the resulting assembly and debug symbols into the tools/FAKE path of your project. Now you can use your CustomTask in the build script:
#light
// include Fake libs
#I "tools\FAKE"
#r "FakeLib.dll"
// include CustomTask
#r "MyCustomTask.dll"
open Fake
// open CustomNamespace
open MyCustomTask
// use custom functionality
let x = RandomNumberTask.RandomNumber(2,13)
sprintf "RandomNumber: %d" x |> trace
You can use every .Net class with FAKE. Just put the assembly in the right folder (tools/FAKE) and include it with the #r command.
If you want to use FAKE standard functionality (like globbing) within your CustomTask project, just reference FakeLib.dll and explore the FAKE namespace.
Tags:
F#,
F-sharp Make,
Fake,
MSBuild,
NAnt
In the last two articles I showed how we can set up FAKE to make an automated build and how we can use it with FxCop. This time we will use FAKE’s AssemblyInfo task in order to set a specific version info to our assemblies.
I assume you have succeeded the CaculatorSample tutorial. If so then just modify your “Build” target to the following:
Target "BuildApp" (fun () ->
AssemblyInfo
(fun p ->
{p with
CodeLanguage = CSharp;
AssemblyVersion = version;
AssemblyTitle = "Calculator Command line tool";
AssemblyDescription = "Sample project for FAKE - F# MAKE";
Guid = "A539B42C-CB9F-4a23-8E57-AF4E7CEE5BAA";
OutputFileName = @".\src\app\Calculator\Properties\AssemblyInfo.cs"})
AssemblyInfo
(fun p ->
{p with
CodeLanguage = CSharp;
AssemblyVersion = version;
AssemblyTitle = "Calculator library";
AssemblyDescription = "Sample project for FAKE - F# MAKE";
Guid = "EE5621DB-B86B-44eb-987F-9C94BCC98441";
OutputFileName = @".\src\app\CalculatorLib\Properties\AssemblyInfo.cs"})
let target = "Build"
// compile all projects below src\app\
let apps = MSBuild buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
)
As you can see modifying your AssemblyInfo.cs file is pretty easy with FAKE. The AssemblyInfo task works for C#, VB.Net and F#. The version parameter can be declared as a property or fetched from a build server like TeamCity:
let version =
let no = System.Environment.GetEnvironmentVariable("BUILD_NUMBER")
if no <> "" && no <> null then no else "0.2"

Tags:
assemblyinfo,
F#,
F-sharp Make,
MSBuild,
NAnt,
TeamCity
In the last article I showed how we can use “FAKE – F# Make” to set up a build script which
- Cleans up old build outputs
- Compiles our main projects
- Compiles test projects
- Uses NUnit to test our assemblies
- Zips the assemblies to a deploy folder.
This time we will improve the same Calculator sample (download here) with a task for FxCop, so please make sure you succeeded with the last article.
“FxCop is a free static code analysis tool from Microsoft that checks .NET managed code assemblies for conformance to Microsoft’s .NET Framework Design Guidelines.”
[Wikipedia]
Setting up FxCop
First of all you have to download and install FxCop. Now open build.fsx from you Calculator sample folder and add a new target “FxCop” to the targets section:
Target "FxCop" (fun () ->
let assemblies =
!+ (buildDir + @"\**\*.dll")
++ (buildDir + @"\**\*.exe")
|> Scan
FxCop
(fun p ->
{p with
// override default parameters
ReportFileName = testDir + "FXCopResults.xml";
ToolPath = @"c:\Program Files (x86)\Microsoft FxCop 1.36\"})
assemblies
)
In the dependencies section modify the dependencies of the “Test” targets:
"Test" <== ["BuildApp"; "BuildTest"; "FxCop"]
That’s it. If you run your build script you will get new *.xml file in the .\test\-folder:

There are a lot of parameters for the FxCop task. Some are described on the project page.
Letting the build fail
If you were using MSBuild before you might know how hard it is to let MSBuild fail your build if FxCop reports any errors or warnings.
With FAKE the only thing you have to do is setting the “FailOnError” parameter:
Target "FxCop" (fun () ->
let assemblies =
!+ (buildDir + @"\**\*.dll")
++ (buildDir + @"\**\*.exe")
|> Scan
FxCop
(fun p ->
{p with
// override default parameters
ReportFileName = testDir + "FXCopResults.xml";
FailOnError = FxCopyErrorLevel.CriticalWarning;
ToolPath = fxCopPath})
assemblies
)
If you activate this option FxCop errors will cause your build to fail. Possible values are:
- FxCopyErrorLevel.Warning
- FxCopyErrorLevel.CriticalWarning
- FxCopyErrorLevel.Error
- FxCopyErrorLevel.CriticalError
- FxCopyErrorLevel.ToolError
- FxCopyErrorLevel.DontFailBuild
The values are cummulative. If you choose FxCopyErrorLevel.CriticalWarning the build will fail for critical warnings, errors, critical errors and FxCop tool errors but not for simple warnings. The default is FxCopyErrorLevel.DontFailBuild.
Tags:
Code Quality,
F#,
F-sharp Make,
Fake,
FxCop,
MSBuild,
NAnt
In this tutorial I will describe how you can set up a complete build infrastructure with “FAKE – F# Make”. You will learn:
- How to automatically compile your C# or F# projects
- How to automatically run NUnit UnitTests on your projects
- How to zip the output to a deployment folder
Install F#
“FAKE – F# Make” is completely written in F# and all build scripts will also be written in F#, but this doesn’t imply you have to learn programming in F#. In fact the “FAKE – F# Make” syntax is very easy to learn. But if you need to you can use the complete power of F# and the .NET Framework.
But in order to get things working we need to install the F# environment. You can download the F# Oktober 2009 CTP from the Microsoft F# Developer Center.
Download Calculator Sample
Now download the latest CalculatorSample-*.zip from the FAKE Download site. This sample includes 3 tiny projects and basically the following structure:
- src\app
- Calculator (Command line)
- CalculatorLib (Class library)
- src\test
- Test.CalculatorLib (NUnit test library)
- tools
- build.bat
- build.fsx
- completeBuild.bat
- completeBuild.fsx
- Calculator.sln
Getting “FAKE – F# Make” started
Open the file tools\FAKE\FakeLib.dll.config and check if the default configuration matches your system environment:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="MSBuildPath"
value="c:\Windows\Microsoft.NET\Framework\v3.5\" />
<add key="FSCPath"
value="c:\Programme\FSharp-1.9.7.8\bin\" />
</appSettings>
<startup>
<supportedRuntime version="v2.0.50727" />
</startup>
</configuration>
If you run the build.bat from the command line then your first FAKE script (build.fsx) will be executed. If everything works fine you will get the following output:

Now open the build.fsx with Visual Studio. It should look like this:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Default target
Target? Default <-
fun _ –> trace "Hello World from FAKE"
// start build
Run? Default
As you can see the code is really simple. The very first lines include the FAKE libraries and are vital in all FAKE build scripts.
Then the Default target is defined. A target definition contains of two important parts. The first is the name of the target (here “Default”) and the second is an action (here a simple trace of a “Hello world” string). The action is defined as a lambda expression.
The last line runs the “Default” target – which means it executes the defined action.
Cleaning the last build output
The first thing in nearly every build scenario is to clean the output of the last build. Please modify the build.fsx file to the following:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
// Targets
Target? Clean <-
fun _ -> CleanDir buildDir
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? Default <- Dependency? Clean
// start build
Run? Default
We introduced some new concepts in this snippet. At first we defined a global property called “buildDir” with the relative directory path of our future build folder.
In the Clean target we want the CleanDir task to clean up our build directory. This simply deletes all files in the old folder or creates it if necessary.
In the dependencies section we say that the Default target is dependent of the Clean target. In other words Clean is a prerequisite of Default and will be run before the execution of Default:
Building the application
In the next step we want to compile our application, which means we want to compile all projects under /src/app with MSBuild.
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
// Targets
Target? Clean <-
fun _ -> CleanDir buildDir
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? BuildApp <- Dependency? Clean
For? Default <- Dependency? BuildApp
// start build
Run? Default
We defined a new build target named “BuildApp” which compiles all project files given in the property appReferences via the MSBuild task. The output will be copied to buildDir.
In order to find the right project files “FAKE – F# Make” scans the folder src/app/ and all subfolders with the given pattern. Therefore a similar FileSet definition like in NAnt or MSBuild (see project page for details) is used.
In addition the target dependencies are modified. Now Default is dependent of BuildApp and BuildApp needs Clean as a prerequisite.
This means the execution order is: Clean ==> BuildApp ==> Default.
Building Test projects
Now our main application will be built automatically and it’s time to build the test application. We use pretty the same concepts as before:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let testDir = @".\test\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
let testReferences = !+ @"src\test\**\*.csproj" |> Scan
// Targets
Target? Clean <-
fun _ –>
CleanDir buildDir
CleanDir testDir
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? BuildTest <-
fun _ ->
let testApps = MSBuildDebug testDir "Build" testReferences
Log "TestBuild-Output: " testApps
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? BuildApp <- Dependency? Clean
For? BuildTest <- Dependency? Clean
For? Default <-
Dependency? BuildApp
|> And? BuildTest
// start build
Run? Default
This time we define a new target “BuildTest”, which compiles all C# projects below src/test/ in Debug mode and we mark the target as a dependency of Default.
As you can see the Clean target is now a dependency of BuildApp and BuildTest, since we also have to clean the test dir. Although the Clean target is referenced twice the “FAKE – F# Make” runtime ensures that it will only be executed once.
The execution order is now Clean ==> BuildApp ==> BuildTest ==> Default.
Testing the test assemblies with NUnit
Now all our projects will be compiled and we can use the NUnit task in order to test our test assemblies:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let testDir = @".\test\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
let testReferences = !+ @"src\test\**\*.csproj" |> Scan
let testAssemblies = !+ (testDir + @"\NUnit.Test.*.dll") |> Scan
let nunitPath = @".\Tools\NUnit\bin"
let nunitOutput = testDir + @"TestResults.xml"
// Targets
Target? Clean <-
fun _ ->
CleanDir buildDir
CleanDir testDir
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? BuildTest <-
fun _ ->
let testApps = MSBuildDebug testDir "Build" testReferences
Log "TestBuild-Output: " testApps
Target? Test <-
fun _ ->
NUnit (fun p ->
{p with
ToolPath = nunitPath;
DisableShadowCopy = true;
OutputFile = nunitOutput})
testAssemblies
Target? Default <-
fun _ -> trace "Hello World from FAKE"
// Dependencies
For? BuildApp <- Dependency? Clean
For? BuildTest <- Dependency? Clean
For? Test <-
Dependency? BuildApp
|> And? BuildTest
For? Default <- Dependency? Test
// start build
Run? Default
Our new target “Test” scans the test directory for test assemblies and runs them with NUnit. The mysterious part (fun p –> …) simply overrides the default parameters of the NUnit task.
The execution order is now Clean ==> BuildApp ==> BuildTest ==> Test ==> Default.
Deploying a zip file
Now we want to deploy a *.zip file containing our application:
// include Fake libs
#I @"tools\FAKE"
#r "FakeLib.dll"
open Fake
// Properties
let buildDir = @".\build\"
let testDir = @".\test\"
let deployDir = @".\deploy\"
let appReferences = !+ @"src\app\**\*.csproj" |> Scan
let testReferences = !+ @"src\test\**\*.csproj" |> Scan
let testAssemblies = !+ (testDir + @"\NUnit.Test.*.dll") |> Scan
let nunitPath = @".\Tools\NUnit\bin"
let nunitOutput = testDir + @"TestResults.xml"
let filesToZip = !+ (buildDir + "\**\*.*") — "*.zip" |> Scan
let zipFileName = deployDir + "Calculator.zip"
// Targets
Target? Clean <-
fun _ -> CleanDirs [buildDir; testDir; deployDir]
Target? BuildApp <-
fun _ ->
let target = "Build"
// compile all projects below src/app/ in Release mode
let apps = MSBuildRelease buildDir target appReferences
// log the output files
Log "AppBuild-Output: " apps
Target? BuildTest <-
fun _ ->
let testApps = MSBuildDebug testDir "Build" testReferences
Log "TestBuild-Output: " testApps
Target? Test <-
fun _ ->
NUnit (fun p ->
{p with
ToolPath = nunitPath;
DisableShadowCopy = true;
OutputFile = nunitOutput})
testAssemblies
Target? Deploy <-
fun _ -> Zip buildDir zipFileName filesToZip
Target? Default <- DoNothing
// Dependencies
For? BuildApp <- Dependency? Clean
For? BuildTest <- Dependency? Clean
For? Test <-
Dependency? BuildApp
|> And? BuildTest
For? Deploy <- Dependency? Test
For? Default <- Dependency? Deploy
// start build
Run? Default
The new target “Deploy” scans the build directory for all files but zip-files. The result will be zipped to \deploy\Calculator.zip via the Zip task.
The execution order is now Clean ==> BuildApp ==> BuildTest ==> Test ==> Deploy ==> Default whereas Default now is only used as a entry point.
What’s next?
Now your build file should look like completeBuild.fsx and you are ready to write your own FAKE scripts. If you have any questions or suggestions feel free to comment on this post.
In the next article I will show how we can add FxCop to our build in order to check the code quality.
Tags:
F#,
F-sharp Make,
Fake,
MSBuild,
NAnt,
Rake