CalculatorSample-0.16.472.15.zip Documentation-0.16.472.15.zip FAKE-0.16.472.15.zip
What is "FAKE - F# Make"?
Introduction
Modern build automation systems are not limited to simply recompile programs if source code has changed. They are supposed to get the latest sources from a source code management system, build test databases, run automatic tests, check guidelines, create documentation files, install setup projects and much more. Some companies are even deploying virtual machines, which are created during a nightly build process. In order to simplify the writing of such build scripts and to provide reusability of common tasks most build automation systems are using a domain-specic language (DSL). These tools can be divided into tools using external DSLs with a custom syntax like make, tools using external DSLs with an XML based syntax like MSBuild or Apache Ant and tools using internal DSLs which are integrated in a host language like Rake, which uses Ruby.
FAKE - An internal DSL
"FAKE - F# Make" is a build automation system, which is intended to combine the advantages of the above mentioned tools but to provide a better tooling support. Due to its integration in F#, all benets of the .NET Framework and functional programming can be used, including the extensive class library, powerful debuggers and integrated development environments like Visual Studio 2008 or SharpDevelop, which provide syntax highlighting and code completion.
The new language was designed to be succinct, typed, declarative, extensible and easy to use. For instance custom build tasks can be added simply by referencing .NET assemblies and using the corresponding classes.
Articles
- Getting started with "FAKE - F# Make" (This tutorial shows you how to build the CalculatorSample project.)
- Adding FxCop to a "FAKE" build script
- Debugging "FAKE – F# Make" build scripts
- Modifying AssemblyInfo and Version via "FAKE – F# Make"
- Writing custom tasks for "FAKE – F# Make"
- Integrating a "FAKE – F# Make" build script into TeamCity
- Integrating a "FAKE – F# Make" build script into CruiseControl.NET
- FAKELib namespace documentation
Main Features
- Simple build infrastructure
- Easy systax
- Full power of .NET Framework
- Predefined tasks:
- Clean task
- NUnit support
- xUnit.net support
- NCover support
- FxCop support
- ExecProcess task (To run tools via the command line)
- MSBuild task (to compile *.csproj and *.fsproj or run MSBuild scripts)
- XMLRead task
- VSS task (Get sources from Visual Source Safe)
- SVN task (Get sources from Subversion)
- XCopy task
- Zip task
- AssemblyInfo task
- Simple TeamCity integration (see Integrating a "FAKE – F# Make" build script into TeamCity)
- FinalTarget feature (to release resources even if build fails)
- Extensible platform (Write your own tasks)
- Easy debugging
- Intellisense support (when using Visual Studio)
Using FAKE
Targets
Targets are the main unit of work in a Fake script. Targets have a name (usually given as a symbol or a string) and a action (given as a code block).
// This target cleans the build and deploy folders Target "Clean" (fun () -> CleanDir "./build/" CleanDir "./deploy/" )
Dependencies
You can define prerequisites for tasks:
// Target Default is dependent from target Clean and BuildApp // Fake will run these targets before Default "Default" <== ["Clean"; "BuildApp"]
Running targets
You can execute targets with the "run"-command:
// Exceutes Default target run "Default"
Final targets
Final target can be used for TearDown functionality. These targets will be executed even if the build fails but have to be activated via ActivateFinalTarget().
// FinalTarget will be excuted even if build fails FinalTarget "CloseSomePrograms" (fun () -> // close stuff and release resources )
// activate FinalTarget somewhere during build ActivateFinalTarget "CloseSomePrograms"
UnitTests
NUnit
Target "NUnitTest" (fun () ->
let testAssemblies =
!+ (testDir + @"\Test.*.dll")
|> Scan
NUnit
(fun p ->
{p with
ToolPath = nunitPath;
DisableShadowCopy = true;
OutputFile = testDir + @"TestResults.xml"})
testAssemblies
)xUnit.net
Target "xUnitTest" (fun () ->
let testAssemblies =
!+ (testDir + @"\Test.*.dll")
|> Scan
xUnit
(fun p ->
{p with
ShadowCopy = false;
HtmlPrefix = testDir})
testAssemblies
)FileSets
Fake uses similar include patterns as NAnt and MSBuild.
Includes
// Includes all `*`.csproj-Files under \src\app // Includes with !+ operator !+ "src/app/**/*.csproj"
// Includes all `*`.csproj-Files under \src\app and \test // Multiple includes with ++ operator !+ "src/app/**/*.csproj" ++ "test/**/*.csproj"
Excludes
// Includes all files under \src\app // but excludes `*`.zip files !+ "src/app/**/*.*" -- "*.zip"
Scan vs. ScanImmediately
Fake provides two scan methods: Scan and ScanImmediately.
Scan is a lazy method and evaluates the FileSet as late as possible ("on-demand"). If the FileSet is used twice, it will be reevaluated.
The following code defines a lazy FileSet:
// Includes all `*`.csproj-Files under \src\app
// lazy scan
let apps =
!+ "src/app/**/*.csproj"
|> ScanScanImmediately scans the FileSet immediatly at time of its definition and memoizes it:
// Includes all files under \src\app but excludes `*`.zip files
// eager scan ==> All files memoized at the time of this definition
let files =
!+ "src/app/**/*.csproj"
-- "*.zip"
|> ScanImmediatelyPredefined Tasks
FAKE provides a lot of predefined tasks. Some of them are listed below:
Sample script
This sample script
- Assumes Fake is located at tools\FAKE
- Cleans the build and deploy paths
- Builds all C# projects below src\app\ and puts the output to .\build
- Builds all NUnit test projects below src\test\ and puts the output to .\build
- Uses NUnit to test the generated Test.*.dll's
- Zips all generated files to deploy\MyProject-0.1.zip
#light
// Include FAKE libraries
#I "tools\FAKE"
#r "FakeLib.dll"
open Fake
// properties
let projectName = "MyProject"
let version = "0.1"
let buildDir = "./build/"
let deployDir = "./deploy/"
let nunitPath = "./Tools/NUnit/bin"
// files
let appReferences = !+ "src/app/**/*.csproj" |> Scan
let testReferences = !+ "src/test/**/*.csproj" |> Scan
// Targets
Target "Clean" (fun () ->
CleanDir buildDir
CleanDir deployDir
)
Target "BuildApp" (fun () ->
let apps = MSBuild buildDir "Build" appReferences
Log "AppBuild-Output: " apps
)
Target "BuildTest" (fun () ->
let testApps = MSBuild buildDir "Build" testReferences
Log "TestBuild-Output: " testApps
)
Target "Test" (fun () ->
let testAssemblies =
!+ (buildDir + "*.Test.dll") |> Scan
let output = buildDir + "TestResults.xml"
NUnit (fun p ->
{p with
ToolPath = nunitPath;
DisableShadowCopy = true;
OutputFile = output})
testAssemblies
)
Target "BuildZip" (fun () ->
let artifacts = !+ (buildDir + "/**/*.*") -- "*.zip" |> Scan
let zipFileName = deployDir + sprintf "%s-%s.zip" projectName version
Zip buildDir zipFileName artifacts
)
Target "Default" DoNothing
// Dependencies
"BuildApp" <== ["Clean"]
"Test" <== ["BuildApp"; "BuildTest"]
"BuildZip" <== ["Test"]
"Default" <== ["BuildZip"]
// start build
run "Default"