Quantcast
Channel: Category Name
Viewing all articles
Browse latest Browse all 10804

Exploring FAKE, an F# Build System for all of .NET

$
0
0

I've been orbiting around F# - but not really jumping in - for a while now. In fact, I looked at F# in 2008 almost 6 years ago and more recently talked to Richard Minerich and Phillip Trelford on Hanselminutes Podcast #311 "Why F#?"

Last week I looked at using ScriptCS, literally C# as a Scripting language, to drive browser automation. Today I'm exploring a make system called FAKE. It's F# Make, a build automation system similar to Make (which is 38 years old next month!) or Rake (which uses Ruby).

Fake is a Domain Specific Language that you can use without knowing F#, but if and when you outgrow it you can keep heading down the F# road. In all cases you've got all of .NET at your command.

Here's their Hello World example, a basic deploy script:

#r "tools/FAKE/tools/FakeLib.dll" // include Fake lib
open Fake


Target "Test" (f _ ->
trace "Testing stuff..."
)

Target "Deploy" (f _ ->
trace "Deploy stuff..."
)

"Test" // define the dependencies
==> "Deploy"

Run "Deploy"

Note that Test depends on Deploy.

FAKE uses F# but you can use it go build whatever. These are some C# OSS projects that use FAKE to build themselves:

FAKE isn't new, it's actually been around for 4 years with 55 contributors so far! It works not only on .NET but also on Linux and Mac under Mono - it works everywhere. Because it's all .NET you can use it on your Continuous Integration Servers like TeamCity or Travis CI.

image

Getting Started with FAKE

Check out their Calculator sample, a .NET project you'll extend to build itself with FAKE. Just download the zip, unblock it, and unzip. Then run build.bat from a developer command prompt.

The build.net is a bootstrapper. It could be powershell or a shell script if you like, of course.

@echo off
cls
"tools\nuget\nuget.exe" "install" "FAKE" "-OutputDirectory" "tools" "-ExcludeVersion"
"tools\FAKE\tools\Fake.exe" build.fsx
pause

This batch file uses NuGet to get FAKE, just as npm install restores node_modules, or gem gets ruby libraries. Then it calls Fake on the build.fsx file. Follow their Getting Started instructions to slowly expand the responsibilities of the build.fsx file.

FAKE has a lot of Helpers in their API documentation. Hundreds, and there's a whole community making others that you can call upon. For example, the built in FileHelper has things like CleanDir to remove files and subdirs.

Here we Clean before we build by making Clean a dependency of Default. BuildDir here is a property that's shared.

// include Fake lib
#r "tools/FAKE/tools/FakeLib.dll"
open Fake

// Properties
let buildDir = "./build/"

// Targets
Target "Clean" (fun _ ->
CleanDir buildDir
)

Target "Default" (fun _ ->
trace "Hello World from FAKE"
)

// Dependencies
"Clean"
==> "Default"

// start build
RunTargetOrDefault "Default"

Jumping to the end of the tutorial, the syntax gets a little more tricky, butu once you get the |> format, it makes sense.

Some cool things to note and file away as interesting at in the script below.

  • the use of !! to include files
  • the use of -- to exclude a file spec after a !! operator
  • Zip is built-in as a helper and zips up the results of the build.
  • the options passed into NUnit
  • The dependency chain
  • #r for referencing .NET DLLs
// include Fake lib
#r "tools/FAKE/tools/FakeLib.dll"
open Fake

RestorePackages()

// Properties
let buildDir = "./build/"
let testDir = "./test/"
let deployDir = "./deploy/"

// version info
let version = "0.2" // or retrieve from CI server

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

Target "BuildApp" (fun _ ->
!! "src/app/**/*.csproj"
|> MSBuildRelease buildDir "Build"
|> Log "AppBuild-Output: "
)

Target "BuildTest" (fun _ ->
!! "src/test/**/*.csproj"
|> MSBuildDebug testDir "Build"
|> Log "TestBuild-Output: "
)

Target "Test" (fun _ ->
!! (testDir + "/NUnit.Test.*.dll")
|> NUnit (fun p ->
{p with
DisableShadowCopy = true;
OutputFile = testDir + "TestResults.xml" })
)

Target "Zip" (fun _ ->
!! (buildDir + "/**/*.*")
-- "*.zip"
|> Zip buildDir (deployDir + "Calculator." + version + ".zip")
)

Target "Default" (fun _ ->
trace "Hello World from FAKE"
)

// Dependencies
"Clean"
==> "BuildApp"
==> "BuildTest"
==> "Test"
==> "Zip"
==> "Default"

// start build
RunTargetOrDefault "Default"

You can do virtually anything and there's a great community out there to help.

Here's a more complex dependency chain with an optional parameter:

// Build order
"Clean"
==> "BuildApp"
==> "BuildTest"
==> "FxCop"
==> "NUnitTest"
=?> ("xUnitTest",hasBuildParam "xUnitTest") // runs the target only if FAKE was called with parameter xUnitTest
==> "Deploy"

There's a rich FAKE world out there with support for Octopus Deploy, all Unit Test systems, Xamarin's xpkg format and much more. Thanks to Steffan Forkmann for helping me explore this. ;)

Related Links


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.



© 2014 Scott Hanselman. All rights reserved.
     

Viewing all articles
Browse latest Browse all 10804

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>