fsharp/FAKE — pull request #497 by yawaramin (2014-07-06 21:35:02+00:00)
Title: ReFake: an incremental build logic DSL

My effort at creating an incremental build DSL on top of FAKE. For several reasons, as explained in the commit message, I did this by creating a new type of build 'target' that stores more information about the target and its dependencies. The implementation is as simple as possible; there are no lookups of target names to objects happening in the background. The build script writer directly creates target objects using the helper functions, and arranges them into a dependency network at the same time. They then run the topmost target in the network to lazily build whatever needs to be built.

This also allows a pretty elegant way of setting up multiple build configurations in the same script using what I call 'virtual targets'. A simple example:

#r "/path/to/FakeLib.dll"
open Fake.FscHelper
open Fake.ReFake

// Debug configuration is default.
let debug = ref true
let outputPath = ref "bin/Debug/"
let optimize = ref "--optimize-"

// A virtual target that sets up a release configuration and doesn't have any dependencies.
let releaseConfig = vx "Release Configuration" [] (fun _ _ ->
debug := false
outputPath := "../../../build/"
optimize := "--optimize+"
0) // Need to return an exit code from build function

// A file target that depends on 'Main.fs'.
let Main_exe = fx' "Main.exe" [fx "Main.fs"] (fun name deps ->
fxs deps // Gets list of names of input files.
|> fsc (fun ps -> // 'fsc' automatically returns exit code.
{ ps with Output = !outputPath + name
Debug = !debug
OtherParams = [!optimize] }))

// A virtual target that depends on 'Main.exe'.
let debugBuild = vx "Debug Build" [Main_exe] nop
// A virtual target that depends on 'releaseConfig' _and_ 'Main.exe' (list order doesn't matter).
let releaseBuild = vx "Release Build" [releaseConfig; Main_exe] nop
reRunAndExit debugBuild
//reRunAndExit releaseBuild

Because the `releaseConfig` target is a dependency of the `releaseBuild` target, it will always be run before `releaseBuild`; and will thus set up the release parameters.

I'm currently trying to convert the `FakeLib.fsproj` file into a ReFake build script, and am about 80% there. Just ironing out a few referencing issues now.

This is a first effort, so I'd welcome feedback.

Relates to issue #235.