Running targets in "FAKE - F# Make"
To see the available Target APIs in FAKE, please see the API-Reference for the Target module.
Command line interface for the target module
If you use the Fake.Core.Target module and call Target.runOrDefault or Target.runOrList in your build script you will have the following CLI options:
|
Please refer to the general FAKE 5 runner command line interface or the Fake.Core.CommandLineParsing documentation
This means you can - for example - run fake run build.fsx --list
or fake build --list to list your targets.
To run a target MyTarget you could use fake run build.fsx -t MyTarget or fake build target MyTarget (or the other way around fake run build.fsx target MyTarget)
All parameters after -- or target <target> are given to the target as paramters. Note that this feature needs to be enabled by using Target.runOrDefaultWithArguments instead of Target.runOrDefault!
Note that the ordering of the parameters matters! This means the following are invalid (which is different to pre FAKE 5 versions):
1.fake run -t Target build.fs- because of ordering fake will assume-tto be the script name.
2.fake build -v- It will not run FAKE in verbose mode but give the parameter-vto the target parameters. This is because there is no-vin the above CLI.In general you should use the command-line in a way to not be broken when new parameters are added. Use longer forms in your scripts and shorter forms on your shell!
Running specific targets
FAKE has a special param "target" which can be used to run specific targets in a build.
We assume the following build script (build.fsx):
#r "paket:
nuget Fake.Core.Target //"
open Fake.Core
Target.initEnvironment()
// *** Define Targets ***
Target.create "Clean" (fun p ->
Trace.trace " --- Cleaning stuff --- "
)
Target.create "Build" (fun _ ->
Trace.trace " --- Building the app --- "
)
Target.create "Deploy" (fun _ ->
Trace.trace " --- Deploying app --- "
)
open Fake.Core.TargetOperators
// *** Define Dependencies ***
"Clean"
==> "Build"
==> "Deploy"
// *** Start Build ***
Target.runOrDefault "Deploy"
Previous versions of FAKE 5 used
(fun () -> ...)instead of(fun _ -> ...). We decided to change the syntax here to introduce some parameters or other features at a later point. Using the current parameter object is not supported yet.
Now we have the following options:
fake run build.fsx -t "Build"=> starts the Build target and runs the dependency Cleanfake run build.fsx -t "Build" --single-target=> starts only the Build target and runs no dependenciesfake run build.fsx -s -t Build=> starts only the Build target and runs no dependenciesfake run build.fsx=> starts the Deploy target (and runs the dependencies Clean and Build)
Script with arguments
If you don't call Target.initEnvironment() before you use the Environment module,
then FAKE will only use system and inline environment variables
(e.g. Windows: set mything=123) instead of parsing the command line -e params.
If you want multiple environment arguments, you can do -e a=1 -e b=2.
Example:
let args = Target.getArguments() // use this at the top of your script instead of `Target.initEnvironment()`
// So some stuff depending on the args
match args with
| Some args ->
Trace.tracefn "Arguments: %A" args
| None ->
// This case happens when no execution is requested (for example `--list` for listing targets)
// Even for empty arguments `Some [||]` is given, read docs for `Target.GetArguments()`
// never execute any side-effects outside of targets when `None` is given.
// NOTE: IDE will only show targets defined in this code-path, so never define targets based on arguments or environment variables.
()
// Set your own variable/s based on the args
let myVerbose, myArg =
match args with
| Some args ->
// Or use Fake.Core.CommandLineParsing here: https://fake.build/core-commandlineparsing.html
args |> Seq.contains "--myverbose",
args |> Seq.contains "--arg"
| None -> false
Target.create "Default" (fun _ ->
if myArg then
printfn "do something special"
)
// Feature is opt-in in order to provide good error messages out of the box
// see https://github.com/fsharp/FAKE/issues/1896
Target.runOrDefaultWithArguments "Default"
Everything after the target will be interpreted as argument for the target:
fake run build.fsx target MyTarget --arg=>--argwill be contained inargsfake build -t MyTarget --arg=>--argwill be contained inargs, because--argis not a valid argument for theFake.Core.Target(see command line spec above)
Targets with arguments
Example:
Target.create "MyTarget" (fun p ->
// Access arguments given by command-line
Trace.tracefn "Arguments: %A" p.Context.Arguments
)
// Feature is opt-in in order to provide good error messages out of the box
// see https://github.com/fsharp/FAKE/issues/1896
Target.runOrDefaultWithArguments "Deploy"
Everything after the target will be interpreted as argument for the target:
fake run build.fsx target MyTarget --arg=>--argwill be contained inp.Context.Argumentsfake build -t MyTarget --arg=>--argwill be contained inp.Context.Arguments, because --arg is not a valid argument for theFake.Core.Target(see command line spec above)
You can access the arguments from every target executed along the way.
Setting build status
You can set the build status automatically using Target.updateBuildStatus. To do this you need to use the Target.WithContext functions to run a target and retrieve the context information:
Example:
#r "paket:
nuget Fake.Core.Target //"
open Fake.Core
Target.initEnvironment()
// *** Define Targets ***
Target.create "Clean" (fun p ->
Trace.trace " --- Cleaning stuff --- "
)
Target.create "Build" (fun _ ->
Trace.trace " --- Building the app --- "
)
Target.create "Deploy" (fun _ ->
Trace.trace " --- Deploying app --- "
)
open Fake.Core.TargetOperators
// *** Define Dependencies ***
"Clean"
==> "Build"
==> "Deploy"
// *** Start Build ***
let ctx = Target.WithContext.runOrDefault "Deploy"
Target.updateBuildStatus ctx
Target.raiseIfError ctx // important to have proper exit code on build failures.
Final targets
Final targets can be used for TearDown functionality. These targets will be executed even if the build fails but have to be activated via Target.ActivateFinal().
Target.createFinal "CloseSomePrograms" (fun _ ->
// close stuff and release resources
()
)
// Activate Final target somewhere during build
Target.activateFinal "CloseSomePrograms"
Build failure targets
Build failure targets can be used to execute tasks after a build failure.
These targets will be executed only after a build failure but have to be activated via activateBuildFailure().
Target.createBuildFailure "ReportErrorViaMail" (fun _ ->
// send mail about the failure
()
)
// Activate Build Failure Target somewhere during build
Target.activateBuildFailure "ReportErrorViaMail"
Using FAKE's parallel option
Since multithreading is beneficial (especially for large projects) FAKE allows to specify the number of threads used for traversing the dependency tree. This option of course only affects independent targets whereas dependent targets will still be executed in order.
Setting the number of threads
The number of threads used can be set using the environment variable parallel-jobs or using the --parallel parameter.
This can be achieved in various ways where the easiest one is to use the parameter:
fake run *YourBuildScript* --parallel 8
Note that the dependency tree will be traversed as usual whenever setting parallel-jobs to a value <= 1 or omiting it entirely.
Issues
- Running targets in parallel is of course only possible when the target-functions themselves are thread-safe.
- Parallel execution may also cause races on stdout and build-logs may therefore be quite obfuscated.
- Error detection may suffer since it's not possible to determine a first error when targets are running in parallel
Due to these limitations it is recommended to use the standard sequential build whenever checking for errors (CI, etc.) However when a fast build is desired (and the project is e.g. known to build successfully) the parallel option might be helpful
Example
When using this parallel option, Fake resolves the build dependency hierarchies from the described paths and builds independend paths as parallel if you have multiple CPUs available. For example this dependency tree:
"Task 1"
==> "Task A2"
==> "Task 3"
"Task 1"
==> "Task B2"
==> "Task 3"
"Task C2"
==> "Task 3"
"Task 3"
==> "Task A4"
"Task 3"
==> "Task B4"
...would be treated as follows:

This is in addition to that that MSBuild may use multiple threads when building one solution having multiple independent project-files.
Soft dependencies
Typically you will define dependencies among your targets using the ==> and <== operators, and these
dependencies define the order in which the targets are executed during a build.
You can also define soft dependencies among targets using the ?=> and <=? operators. For example, you might
say that target B has a soft dependency on target A:
"A" ?=> "B"
// Or equivalently
"B" <=? "A"
With this soft dependency, running B will not require that A be run first. However it does mean that if A is run (due to other dependencies) it must be run before B.
Example
// *** Define Targets ***
Target.create "Clean" (fun _ ->
Trace.trace " --- Cleaning stuff --- "
)
Target.create "Build" (fun _ ->
Trace.trace " --- Building the app --- "
)
Target.create "Rebuild" ignore
// *** Define Dependencies ***
"Build" ==> "Rebuild"
"Clean" ==> "Rebuild"
// Make sure "Clean" happens before "Build", if "Clean" is executed during a build.
"Clean" ?=> "Build"