-
Notifications
You must be signed in to change notification settings - Fork 0
Reference | Rules
Rules map targets to recipes. Add them using the rules directive inside xakeScript. The "main" target is the default entry point when no targets are specified on the command line.
do xakeScript {
rules [
"main" <== ["build"; "test"]
command "build" {
do! sh "dotnet build src/core -c Release" {}
}
command "test" {
do! sh "dotnet test src/tests" {}
}
target "out/version.txt" {
let! ver = getVar "VERSION"
do! writeText ver
}
]
}Creates a phony rule that always re-runs. AlwaysRerun is added automatically if the recipe does not already include it. Use for build, test, deploy, and clean actions.
command "build" {
do! sh "dotnet build src/core" {}
}
command "clean" {
do! rm {dir "out"}
}Creates a rule that produces a single file. The recipe runs only when the file is missing or its dependencies have changed.
target "out/version.txt" {
let! version = getVar "VERSION"
do! writeText version
}Creates a rule that produces multiple files from a single recipe. The recipe runs once regardless of how many of its outputs are demanded.
targets ["out/netstandard2.0/Xake.dll"; "out/netstandard2.0/Xake.xml"] {
do! sh "dotnet build src/core -o out/netstandard2.0" {}
}The builder syntax shown above has equivalent operator forms:
| Builder | Operator | Rule type |
|---|---|---|
command "name" { ... } |
— |
PhonyRule + AlwaysRerun
|
target "pattern" { ... } |
"pattern" ..> recipe { ... } |
FileRule |
targets ["a";"b"] { ... } |
["a";"b"] *..> recipe { ... } |
MultiFileRule |
| — | "name" => recipe { ... } |
PhonyRule without AlwaysRerun
|
Note that => creates a plain phony rule without AlwaysRerun, unlike command which adds it automatically. Use => for one-off actions like "clean" => rm {dir "out"} where re-run tracking is not needed.
// operator examples
"out/app.dll" ..> recipe {
do! sh "dotnet build -o out" {}
}
["out/app.exe"; "out/app.xml"] *..> recipe {
do! sh "dotnet publish -o out" {}
}
"clean" => rm {dir "out"}Both create phony rules with AlwaysRerun that demand a list of targets.
<== demands targets in parallel:
"main" <== ["build"; "test"]<<< demands targets sequentially, one after another:
"deploy" <<< ["build"; "test"; "package"]Creates a file rule where the pattern is a predicate function instead of a glob:
(fun name -> name.EndsWith ".generated.cs") ..?> recipe {
let! target = getTargetFullName()
do! trace Info "Generating %s" target
}Rules can use wildcard patterns in file names:
"*.dll" ..> recipe {
let! target = getTargetFullName()
do! trace Info "Building %s" target
}Patterns can include path fragments: "bin/*/app.exe" matches both bin/release/app.exe and bin/debug/app.exe.
Wildcards can be named using parentheses to extract matched parts:
"bin/(config:*)/app.exe" ..> recipe {
let! config = getRuleMatch "config"
// config = "release" for target "bin/release/app.exe"
do! sh "dotnet publish" {
args ["-c"; config; "-o"; "bin/" + config]
}
}A more complex example with multiple groups:
"(dir:*)/(file:*).(ext:c*)" ..> recipe {
let! dir = getRuleMatch "dir"
let! file = getRuleMatch "file"
let! ext = getRuleMatch "ext"
// for "src/hello.cs": dir="src", file="hello", ext="cs"
}Groups can span multiple path elements: "(src:a/**)/bin/*.exe".
Note:
**in rule patterns does not match an empty directory segment, unlike filesets.
The teardown custom operation specifies targets to run during shutdown. It accepts a list of target names that must be defined as regular rules in the same script.
In xakeEngine mode, teardown targets run sequentially during StopAsync after all in-flight tasks complete:
let engine = xakeEngine {
rules [
command "cleanup" {
do! trace Message "Releasing resources..."
}
]
teardown ["cleanup"]
start
}
// ... use engine ...
do! engine.StopAsync() // runs "cleanup" after in-flight work finishesIn xakeScript mode, the teardown target names are stored in ExecOptions.Teardown and passed through to EngineOptions. To run teardown targets in script mode, use xakeEngine with start/StopAsync, or demand them explicitly after your main build.
The rule, rules with operators, and phony custom operations still work but the builder syntax inside rules [...] is preferred.
do xakeScript {
// Single rule via custom operation
rule ("build" => recipe { do! sh "dotnet build" {} })
// Phony shorthand
phony "hello" (recipe { do! trace Message "Hi!" })
// Multiple rules with operators
rules [
"main" <== ["build"]
"clean" => rm {dir "out"}
]
}