Skip to content

Reference | Rules

Oleg edited this page Jul 19, 2017 · 7 revisions

Defining rules

Rule is added by a rule directive in xake script body. "main" target is an entry point.

Similarly rules directive allows to add multiple rules passed as array. For example:

do xake ExecOptions.Default {
    rules [
        "main" <== ["hw.exe"]
        "hw.dll" ..> recipe {
          let! exe = getTargetFile()
          do! Csc {
            CscSettings with
              Out = exe
              TargetType = TargetType.Library
              Src = !! "util.cs"
            }
        }

        "hw.exe" ..> recipe {
          do! Csc {
            CscSettings with
              // not defining the output file here, so that Csc will use artifact name (hw.exe in this code)
              Src = !! "hw.cs"
              Ref = !! "hw.dll"
            }
          }
    ]
}

The script defines main rule is to build "hw.exe". <== operator (described in reference) defines a rule which requires other targets to complete. When build tool meet the Ref pointing to hw.dll it looks for rule matching the file name, starts the build step and waits until it completes.

..> operator defines a "file rule". The name of the file can be obtained via getTargetFullName function within recipe body.

File/rule name matching

Rule can be defined either for particular file of for a group files which path name matched the rule mask. For example the following code defines a rule for making any dll assembly from the .cs file with the same name:

        "*.dll" ..> recipe {
          let! asm = getTargetFullName()
          do! Csc {
            CscSettings with
              Src = !! (asm <.-> ".cs")
          }
        }
}

Mask can also contain the path fragment such as "bin/application.exe" or path mask "bin/*/application.exe" which will define the rule both for "bin/release/application.exe" and "bin/debug/application.exe".

"**" matches nested folders similarly to fileset masks.

Mask fragments matching

Xake script allows to get part of artifact name by defining matching groups in the rule:

rules [`"bin/(releaseType:*)/application.exe"` ..> recipe {
  let! typ = getRuleMatch "releaseType"
  // typ will contain "release" for artifact "bin/release/application.exe"
  ...
}]

Named groups vs numbered groups

Function getRuleMatch retrieves the value for named group or for numbered group. Numbered groups are 1 based and refer to wildcards (such as **, * and ?) in rule pattern.

E.g. for rule pattern "*/bin/*.exe" and file x86/bin/myfile.exe:

  • getRuleMath "1" returns "x86" |
  • getRuleMatch "2" returns "myfile"

Matching groups can be nested one in another. Group can cross multiple path elements, e.g. "(releaseType:bin/*)/application.exe".

Important: ** behavior in rule pattern behaves differently compared to fileset's ** wildcard. In rule ** will not (!) match missing directory structure.

Multitarget rules

Multitarget rules were added in version 0.12 and allows to define a rule which produces multiple targets. For example C# compiler builds both assembly and xml documentation file.

["(src:a/**)/bin/*.exe"; "(src:a/**)/bin/*.xml"] *..> recipe {
    let! [_; xmlfile] = getTargetFiles()
    let! srcFolder = getRuleMatch "src"
    do! csc {
        src !!(srcFolder </> "*.cs")
        args ["--doc:" + xmlfile.FullName]
    }
}

Function getTargetFiles returns list of full names of target files, one per pattern in rule definition. getTargetFullName() returns name of primary (first in the patterns) target.

Clone this wiki locally