-
Notifications
You must be signed in to change notification settings - Fork 4
Reference | Recipe
Recipe body is computation expression of type recipe. This computation returns Recipe type and is very similar to async computation. Both regular code (such as assignments/binding, loops and conditional expressions) and do! notation can be used in recipe* body.
Defining recipe is similar to defining a regular function:
let downloadFile name = recipe {
let! fileData = WebClient.DownloadStringAsync name
return fileData.Length
}
recipe {
let! result = downloadFile "main.cpp"
...
}
Notice let-bang operator must be used for calling recipe or async functions.
If recipe does not return a value do!
operator should be used.
Execution options and settings could only be accessed from within recipe computation:
recipe {
// HOWTO get the target name of currently executing rule
let! name = getTargetFile()
let filename = name.FullName
// which has a shortcut:
let filename = getTargetFullName()
// HOWTO get execution options
let! opts = getCtxOptions()
let rootPath = opts.ProjectRoot
...
}
"verinfo.txt" ..> recipe {
let! envver = getEnv "VER"
let ver = envver |> function | Some x -> x | _ -> "v0.1"
do! writeText <| sprintf "$version: %s" ver
let! isDebug = getVar "DEBUG" |> Recipe.map (function | Some x -> x | _ -> "0")
}
Recipe.map is internal function that allow to map a result value of recipe.
In case one artifact depends on the other, for example application executable is statically linked to utility assembly, you usually request xake
to build dependency by calling builltin need
recipe:
"app.exe" ..> recipe {
do! need ["ver.cs"; "somelib.dll"]
...
Recipe will put the requested targets to the build queue (unless they are not built already) and will pause execution until all artifacts are ready.
It will also record that currently executing target depends on requested files and will skip the build next time in case dependencies were not modified.
Inner tasks such as
csc
,fsc
,copyFile
request all source files and libraries automatically.
Recipe computation allow async functions to be called:
recipe {
let! result = downLoadFileAsync "http://nowhere.com/file.zip"
...
Internal trace
function writes the message to the log. The message is written to all log targets (such as console and file), messages are prefixed with a message level and identifier (index) of currently executing task for tracing the source of message.
do! trace Message "Hello world"
do! trace Info "Hello, %s!" "username"
Level
parameter defines the class/severity of the message. Messages are filtered based on level. level
accepts one of the following values: | Message | Error | Command | Warning | Info | Debug | Verbose | Never
Define a recipe in case any if the following conditions met:
- you need an access the execution context
- asynchronous functions are used
- calling xake functions for tracing, demanding other artifacts etc
Use functions in other cases.
if
, for
and while
statements are supported:
recipe {
if s1 = "2" then
do something()
/// else block is also allowed after if
for i in [1..3] do
do! trace Info "%A" i
let j = ref 3
while !j < 5 do
do something (sprintf "j=%i" !j)
j := !j + 1
}
recipe
computation expression supports try/with and try/finally blocks.
// create a helper task/recipe
let log = trace Message
...
recipe {
do! log "before try"
try
try
do! log "Body executed"
failwith "Ouch"
with e ->
do! log "Exception: %s" e.Message
finally
printfn "Error!"
}
tasks (with do! notation) are allowed in
with
block but aren't infinally
block. This is limitation of F#'s computation expressions.
Intercepts errors (exceptions) and allows to define a custom handler.
phony "main" (recipe{
do! trace Message "The exception thrown below will be silently ignored"
failwith "some error"
} |> WhenError ignore)
Raises the exception if action's result meet specified condition. E.g. the following code raises error in case errorlevel (result of shell command execution) gets non-zero value.
do! shell {cmd "dir"} |> FailWhen ((<>) 0) "Failed to list files in folder"
// or just
do! shell {cmd "dir"} |> CheckErrorLevel
- Creating simple script
- Running the first build
- What the rule and recipe is?
- Filesets defined
- Editing the script
- Configure your project and CI
- Defining filesets
- Recipe computation
- Declaring the rules
- Error handling and exceptions
- Script and environment settings
- Command line interface (CLI)
- Writing cross-platform scripts
- Build-in functions
- .NET tasks
- System tasks
- Other
- ...