Rash thoughts about .NET, C#, F# and Dynamics NAV.


"Every solution will only lead to new problems."

Wednesday, 15. April 2009


Integrating a “FAKE – F# Make” build script into TeamCity

Filed under: F#,FAKE - F# Make,Tools,Visual Studio — Steffen Forkmann at 11:00 Uhr

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:

Create project on your TeamCity Server

Creating a FAKE Project

Now create a new project and add a build configuration:

Create Calculator project

General Settings

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.]

VCS root

Test connection

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:

Choosing build runner

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

Enable triggering when files are checked into VCS

Running the build

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

Running first FAKE build script in TeamCity

You can also inspect the NUnit and FxCop results:

NUnit test results

FxCop results

Tags: , , , , , , ,

Tuesday, 14. April 2009


Writing custom tasks for “FAKE – F# Make”

Filed under: C#,F#,FAKE - F# Make — Steffen Forkmann at 15:37 Uhr

“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

Using custom tasks in FAKE

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: , , , ,

Friday, 10. April 2009


Microsoft TechDays Mai 2009 – Administrieren mit PowerShell

Filed under: TechTalk — Steffen Forkmann at 11:08 Uhr

Seit Herbst 2008 bietet Microsoft TechNet eine neue Veranstaltungsreihe an: den sogenannten Microsoft TechDay. Im Mai wird sich diese Reihe um das Thema „Administrieren mit PowerShell“ drehen.

“Die Windows PowerShell, zeitweise auch bekannt unter den Codenamen Monad und Microsoft Command Shell (MSH), ist eine von Microsoft entwickelte Alternative zum Windows-Kommandozeilenprogramm cmd.exe und zum Windows Script Host.

Die auf dem .NET-Framework in der Version 2.0 basierende Windows PowerShell verbindet die aus Unix-Shells bekannte Philosophie von Pipes und Filtern mit dem Paradigma der objektorientierten Programmierung. Der Benutzer kann wie bisher einfache Befehle an einer Kommandozeile ausführen und miteinander verknüpfen oder aber auch komplexe Skript-Programme mit der eigens dafür entwickelten PowerShell Scripting Language schreiben.”

[Wikipedia]

Folgende Termine stehen zur Auswahl:

  • 05.05.2009: Hamburg
  • 06.05.2009: Düsseldorf
  • 12.05.2009: Stuttgart
  • 15.05.2009: München

Weitere Informationen zur Anmeldung und weiteren geplanten Themen findet man auf der Event-Seite des Microsoft TechDay bzw. auf der Agenda-Seite.

Im Juni wird es dann übrigens eine TechDays-Reihe zu Windows 7 geben. Man darf gespannt sein.

Tags: ,

Sunday, 5. April 2009


Debugging “FAKE – F# Make” build scripts

Filed under: F#,FAKE - F# Make,Tools,Visual Studio — Steffen Forkmann at 19:08 Uhr

This post addresses the No. 1 Feature request for MSBuild: Debugging.

With FAKE builds scripts debugging is no issue. Just write System.Diagnostics.Debugger.Break() somewhere into your build script and start the build. It is nearly as easy as pressing F9 in Visual Studio.

If the build script reaches your Breakpoint it will ask you which Debugger you want to use:

Just in time debugger with FAKE 

If you are editing your build script in Visual Studio you can select that instance otherwise choose a new instance and you are ready to debug:

image

Tags: , , , ,

Saturday, 4. April 2009


Modifying AssemblyInfo and Version via FAKE – F# Make

Filed under: C#,FAKE - F# Make,Tools — Steffen Forkmann at 14:54 Uhr

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"

AssemblyInfo

Tags: , , , , ,

Thursday, 2. April 2009


Adding FxCop to a “FAKE” build script

Filed under: C#,English posts,F#,FAKE - F# Make,NaturalSpec,Tools — Steffen Forkmann at 18:19 Uhr

In the last article I showed how we can use “FAKE – F# Make” to set up a build script which

  1. Cleans up old build outputs
  2. Compiles our main projects
  3. Compiles test projects
  4. Uses NUnit to test our assemblies
  5. 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:

FxCop result viewed with Internet Explorer 8

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
)

Letting the build fail

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: , , , , , ,

Wednesday, 1. April 2009


Getting started with “FAKE – F# Make” – Get rid of the noise in your build scripts.

Filed under: C#,English posts,F#,FAKE - F# Make,Informatik,NaturalSpec,Tools — Steffen Forkmann at 21:02 Uhr

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# April 2010 CTP from the Microsoft F# Developer Center or install Visual Studio 2010.

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
    • FAKE Assemblies
    • NUnit
  • 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\v4.0.30319\" />

    <add key="FSIPath"

      value="[ProgramFiles]\FSharp-2.0.0.0\bin\" />

  </appSettings>

</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:

Hello World from FAKE

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.

After this header 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 “Hello world”). Action can be defined as lambda expressions or methods.

The last line runs the “Default” target – which means it executes the defined action.

Cleaning the last build output

A typical first step in nearly every build scenario is to clean the output of the last build. We can achieve this by modifying the build.fsx 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 path of a temporary build folder.

In the Clean target we want the CleanDir task to clean up this build directory. This simply deletes all files in the folder or creates the directory 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:

Clean is a dependency of Default 

Building the application

In the next step we want to compile our application libraries, 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 = Scan (!+ @"src\app\**\*.csproj")

 

// 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

Again, we defined a new build target named “BuildApp” which compiles all project files given in the property appReferences with 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.

App-Build output 

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 and allows to specify concrete parameters.

The execution order is now Clean ==> BuildApp ==> BuildTest ==> Test ==> Default.

Test output

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 – F# Make” build 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 specific naming rules.

Tags: , , , , ,