Xake is a build utility that uses the full power of the F# programming language. Xake is inspired by shake build tool.
The simple script looks like:
#r "nuget: Xake"
open Xake
open Xake.Dotnet
do xakeScript {
"main" <== ["helloworld.exe"]
"helloworld.exe" ..> csc {
targetfwk "net-4.6.2"
src !!"helloworld.cs"
grefs ["System.dll"]
}
}This script compiles helloworld assembly from helloworld.cs file, on any OS. Rules are written
straight in the body of xakeScript — no rules [ ... ] wrapper needed.
The single Xake package contains both the engine (Xake, Xake.Tasks) and the tasks for the
full .NET Framework (Xake.Dotnet) — one reference is enough.
Make sure dotnet SDK 8.0 or newer is installed. Save any of the scripts below as build.fsx
and run it with dotnet fsi build.fsx — Xake comes from NuGet, there is nothing else to
install.
The smallest useful script: one phony rule, printing a message. main is the default target,
so no arguments are needed.
#r "nuget: Xake"
open Xake
do xakeScript {
"main" => trace Message "Hello world!"
}..> declares a file target. The recipe writes the target file, and main demands it —
targets are built on demand, and only the ones that are actually needed.
#r "nuget: Xake"
open Xake
open Xake.Tasks
do xakeScript {
"main" => need ["out/hello.txt"]
"out/hello.txt" ..> writeText "Hello world!"
"clean" => rm { dir "out" }
}dotnet fsi build.fsx # builds "main"
dotnet fsi build.fsx -- -- cleanA recipe { ... } is a sequence of steps. Anything it reads through Xake — readText here —
is recorded as a dependency, so the target is rebuilt when, and only when, one of its inputs
changes.
#r "nuget: Xake"
open Xake
open Xake.Tasks
do xakeScript {
"main" => need ["out/hello.txt"]
"out/hello.txt" ..> recipe {
// records name.txt as a dependency of this target
let! name = readText "name.txt"
do! trace Info "greeting %s" (name.Trim())
do! writeText $"Hello, {name.Trim()}!"
}
"clean" => rm { dir "out" }
}Create name.txt next to the script and run it twice: the second run reports
Skipped main (up to date). Change name.txt and it rebuilds.
git clone https://github.com/OlegZee/Xake
cd xake
dotnet fsi build.fsx -- -- build # features.fsx and fullframework.fsx use the local build
cd samples
dotnet fsi gettingstarted.fsx
dotnet fsi features.fsx
dotnet fsi fullframework.fsx- See the features.fsx script for various samples.
- See docs/tasks.md for the task reference and docs/dotnet-build.md for building .NET Framework targets.
- Xake.Hermetic.Dotnet (preview, separate package): lock files, restore from a lock, deterministic packs, SBOMs and signing for .NET builds.
- Xake.Hermetic.Dotnet architecture: design, evidence and known limits, for maintainers and reviewers.
- Xake.Hermetic.Dotnet guide (draft): a task-oriented walk-through from the first lock to packing and signing.
- Roadmap: what is planned and what is open for Xake and Xake.Hermetic.Dotnet.
- We have the introduction page for you to learn more about Xake.
- And there're the documentation notes for more details.
Once you cloned the repository you are ready to compile and test the binaries:
dotnet fsi build.fsx -- -- build test
... or use build.cmd (build.sh) in the root folder. build.fsx (msbuild via dotnet build) is
the build of record: packages and releases come from it.
The same three libraries, compiled by fsc from committed data instead of msbuild: a project
description per project (src/<dir>/xake.project.json), a lock per project and configuration
(locks/<name>/Release.json) and their fingerprints (xake.fingerprints). The script runs on the
published Xake and Xake.Hermetic.Dotnet packages, so a fresh clone needs no bootstrap:
dotnet fsi build.fsc.fsx -- -- build # out/Release/<fwk>/*.dll from the committed locks
dotnet fsi build.fsc.fsx -- -- build check # and fail on a stale description or lock
| Command | What it does |
|---|---|
import |
msbuild evaluates each .fsproj and writes its xake.project.json (only on change) |
update-locks |
writes locks/<name>/Release.json from the descriptions, referenced projects first; packages via msbuild restore, kept versions unless -d LOCK_REFRESH=<ids|*> |
build |
compiles from the committed locks only, no msbuild; warns when a description or lock is stale against its inputs |
check |
fails where build only warns (stale or hand-edited descriptions and locks) |
After changing a project file: import, update-locks, commit the changed descriptions, locks
and xake.fingerprints. The locks name the SDK's compiler by the SDK version (no hash), so they
hold for that SDK version (10.0.401) on any OS (CI runs this build on Linux with that SDK). See
docs/hermetic/lock.md.
Releases are published to nuget.org by CI from a v* tag — see
docs/devprocess.md for the packaging and release procedure.
The csc, fsc, msbuild and resgen tasks build full-framework binaries on any OS with
nothing installed beyond the .NET SDK: the compilers come from the SDK and the reference
assemblies from the Microsoft.NETFramework.ReferenceAssemblies.* packages, restored on first
use. Mono is still supported as a fallback and can be requested explicitly with a mono-
prefixed framework name.
See docs/dotnet-build.md for the discovery rules, the supported runtimes, and how to switch between them.
See documentation for more details.