-
Notifications
You must be signed in to change notification settings - Fork 4
Introduction
The file is created for 0.xx version of xake and is now being rewritten for xake 1.x which targets netcore as primary environment. Bootstrap code will change while the other things are left intact.
The most simple, but structured script looks as follows:
#r "paket:
nuget Xake ~> 1.1 prerelease
nuget Xake.Dotnet ~> 1.1 prerelease //" // (1)
open Xake // (2)
open Xake.Dotnet // (2.1)
do xakeScript { // (3)
rule("main" <== ["hw.exe"]) // (4)
rule("hw.exe" ..> recipe { // (5)
do! Csc {
CscSettings with
Src = !! "hw.cs"
}
})
rule (FileRule ("greet", recipe { do! trace Info "hello" }))
}
Here are we doing the following steps:
- reference f# libraries containing core functionality and dotnet specific tasks
- open Xake namespace, which contains definition of xakeScript and recipe computation expressions, Xake.Dotnet namespace contains definition for
Csc
task - define a "main" function of the build script
- add the rule for "main" target (the default one in case targets are not defined in parameters) which demands "hw.exe" file
- define the rule for "hw.exe" target
Create a new project and save the script to build.fsx file. The build script is a valid F# script and .fsx is a standard file extension.
- Both Fake and Xake are available on Nuget so the first step is to download nuget.exe from nuget/downloads page.
Issue the following commands to get Fake and Xake installed in tools folder.
nuget install Xake -excludeVersion -outputdirectory tools
- Copy the following code to hw.cs file:
class Program
{
public static void Main()
{
System.Console.WriteLine("Hello world!");
}
}
- run the build using following command:
fsi.exe build.fsx
You will need fsi tool in your path. Open Visual Studio Command prompt console which adds path to FSI to PATH. The other option is using mono's fsharpi (available on linux, osx, and Windows).
The option which does not require installing Mono or Visual Studio is described on integration page.
Recipe is block of F# code with some extras such as method for accessing script execution context without using globals or parameters, asynchronous execution, tracking and recording dependencies, and more.
All tasks such as copying files, compiling application (Csc task in the example above) and so on are all recipes. Defining your own recipe is as simple as defining function:
let makePackageName variableName = recipe {
let! ver = getEnv(variableName)
return sprintf "Xake.%s.nupkg" (ver =? "0.0.1")
}
In this example getEnv is internal function (and also recipe) for accessing environment variables. Such call is recorded in dependency tree and respective (calling?) rule will be marked as dependent on particular variable. If on the next run the value is changed Xake will rebuild the target.
In order to call the recipe the "bang" versions of "do" and "let" must be used - that is the way to pass context down to recipe.
Rule is a pair of target name and the recipe defining how to build the target.
The following statement defines the rule (but does not add it to script):
let rule = "hi" ..> recipe {do! trace Info "Hello world"}
// equivalent to
let rule = FileRule ("greet", recipe { do! trace Info "hello" })
..>
is an infix operator for creating file rule.
The rules
directive in script allows to add multiple rules passed as array. For example:
do xake ExecOptions.Default {
rules [
"main" <== ["hw.exe"]
"hw.dll" ..> Csc {CscSettings with Src = !! "util.cs"}
"hw.exe" ..> Csc {CscSettings with Src = !! "hw.cs"; Ref = !! "hw.dll"}
]
}
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.
Filesets are widely used to define source files, list of library modules. Fileset defines the way to get the list of files, but not the list itself.
// define a fileset (!! operator) and add two more files
let refs = !! "bin/FSharp.Core.dll" + "bin/nunit.framework.dll" + "bin/Xake.Core.dll"
// using builder
let sourceFiles = fileset {
basedir "src"
includes "**/*.cs"
includes "../versioninfo.cs"
}
// or...
let sourceFiles2 = +"src" + "**/*.cs" + "../versioninfo.cs"
There's no difference in slash/backslash. Xake will translate it to path separator used in particular operating system. I'm using slash for simplicity (no escaping characters involved).
See some
Operator (example) | Description |
---|---|
let src = !! "src/*.cs" | Creates a new fileset |
let src1 = !! "src/*.cs" + "common.cs" | Adds another filemask to a fileset. |
let src2 = !! "src/*.cs" - "src/tests.cs" | Remove the filemask from fileset |
let src = !! "*.cs" @@ "src" | Changes "base" directory, which the other masks are related to. |
let src3 = src +? (NUNIT, "tests/*.cs") | Adds the filemask if condition is met |
let src = +"src" + "*.cs" | Unary plus creates an empty fileset with specified directory. |
Function Fileset.toFileList
"executes" the fileset and returns the list of files.
There are many good tools for working with F#. Under Windows it is Visual Studio. Xamarin Studio is available on Windows, OSX, and Linux. These IDEs not only allow to edit script but also provide rich debugging and refactoring tools.
My favourite environment however is Visual Studio Code and Ionide plugin. It takes a couple minutes to download and install; and it works everywhere.
- 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
- ...