Design Goals

FsMake is a batteries excluded, extendable, task runner.

The core is designed to be dependency free and easy to use to run other processes.
This makes it easier to maintain and reduces churn when other tools have breaking changes.

It uses a simple pipeline approach to define execution order that is easy to reason about.


Getting Started

In your project root create a build.cmd file for Windows users:

dotnet fsi build.fsx -- %*

Create a build.sh for non Windows users:


dotnet fsi build.fsx -- "$@"

Don't forget to chmod +x build.sh!

Create a build.fsx file:

// Uses the latest stable version of FsMake
#r "nuget: FsMake"
// It is recommended to specify a version
// #r "nuget: FsMake, x.x.x"

open FsMake

let args = fsi.CommandLineArgs

// Creates a restore step.
let restore =
    Step.create "restore" {
        // Commands that return an exit code other than 0 fail the step by default.
        // This can be controlled with [Cmd.exitCodeCheck].
        do! Cmd.createWithArgs "dotnet" [ "restore" ] |> Cmd.run

let build =
    Step.create "build" {
        do! Cmd.createWithArgs "dotnet" [ "build" ] |> Cmd.run

// Define your pipelines, for now we just want a simple "build" pipeline.
// You can define pipelines with parallel/conditional steps.
// You can also define pipelines from other pipelines.
Pipelines.create {
    let! build =
        Pipeline.create "build" {
            run restore
            run build

    default_pipeline build
|> Pipelines.runWithArgsAndExit args

To run this pipeline:


Further Example

FsMake uses FsMake to run its own pipelines!

Check the FsMake build.fsx for a more extensive example.

namespace FsMake
val args: string[]
val restore: Step
Multiple items
module Step from FsMake
<summary> Module for creating and working with steps. </summary>

type Step = { Name: string Make: Make<unit> }
<summary> Represents a pipeline step. </summary>
val create: name: string -> Step.Builder
<summary> Creates a step using a <see cref="T:FsMake.StepModule.Builder" /> computation expression. </summary>
<param name="name">The name of the step.</param>
<returns>A <see cref="T:FsMake.StepModule.Builder" />.</returns>
<example><code lang="fsharp"> let emptyStep = Step.create "emptyStep" { () } </code></example>
module Cmd from FsMake
<summary> Module for building and executing commands or processes. </summary>
<example><code lang="fsharp"> let step = Step.create "mStep" { do! Cmd.createWithArgs "dotnet" [ "build" ] |&gt; Cmd.run let! result = Cmd.createWithArgs "dotnet" [ "gitversion" ] |&gt; Cmd.result printfn "%s" result.Output.Std } </code></example>
val createWithArgs: cmd: string -> args: string list -> Cmd.CmdOptions<unit>
<summary> Creates a <see cref="T:FsMake.Cmd.CmdOptions`1" /> with a command to run. </summary>
<example><code lang="fsharp"> let cmd = Cmd.createWithArgs "dotnet" [ "build"; "--no-restore" ] </code></example>
<param name="cmd">The command to run.</param>
<param name="args">A list of arguments to be passed to the command.</param>
<returns>The new <see cref="T:FsMake.Cmd.CmdOptions`1" />.</returns>
val run: opts: Cmd.CmdOptions<'a> -> ctx: MakeContext -> Result<unit,MakeError>
<summary> Runs a command/process with the specified options. </summary>
<param name="opts">The <see cref="T:FsMake.Cmd.CmdOptions`1" />.</param>
<param name="ctx">The <see cref="T:MakeContext" /> of the current <see cref="T:Make`1" />.</param>
<typeparam name="'a">The command output type.</typeparam>
<returns>The result.</returns>
<example><code lang="fsharp"> let build = Step.create "build" { do! Cmd.createWithArgs "dotnet" [ "build" ] |&gt; Cmd.run } </code></example>
val build: Step
Multiple items
module Pipelines from FsMake
<summary> Module for creating and working with <see cref="T:Pipelines" />. </summary>

type Pipelines = { Default: Pipeline option Pipelines: Pipeline list StepPrefix: PrefixOption }
<summary> Represents a set of pipelines and settings. </summary>
val create: Pipelines.Builder
<summary> Use a computation expression builder to define <see cref="T:Pipelines" />. </summary>
<returns>A <see cref="T:Pipelines.Builder" />.</returns>
<example><code lang="fsharp"> let clean = Step.create "clean" { () } let build = Step.create "build" { () } let testUnit = Step.create "test:unit" { () } let testInt = Step.create "test:integration" { () } let pipelines = Pipelines.create { // adds the build pipeline to the `Pipelines` let! build = Pipeline.create "build" { run clean run build } // adds the test pipeline to the <see cref="Pipelines" /> do! Pipeline.createFrom build "test" { run_parallel [ testUnit; testInt ] } default_pipeline build } </code></example>
val build: Pipeline
Multiple items
module Pipeline from FsMake
<summary> Module for creating and working with a <see cref="T:Pipeline" />. </summary>

type Pipeline = { Name: string Description: string option Stages: Stage list }
<summary> Represents a pipeline and its stages. </summary>
val create: name: string -> Pipeline.Builder
<summary> Creates a pipeline using a <see cref="T:FsMake.PipelineModule.Builder" /> computation expression. </summary>
<param name="name">The name of the pipeline.</param>
<returns>A <see cref="T:FsMake.PipelineModule.Builder" />.</returns>
<example><code lang="fsharp"> let emptyStep = Step.create "emptyStep" { () } let pipeline = Pipeline.create "pipeline" { run emptyStep } </code></example>
custom operation: run (Step) Calls Pipeline.Builder.RunStep
<summary> Adds a <see cref="T:Step" /> that will always be run. </summary>
<param name="state">Unused.</param>
<param name="step">The <see cref="T:Step" /> to add.</param>
custom operation: default_pipeline (Pipeline) Calls Pipelines.Builder.DefaultPipeline
<summary> Sets the default <see cref="T:Pipeline" /> to be run when a pipeline is not specified in the arguments. </summary>
<param name="state">The current state of the computation expression.</param>
<param name="pipeline">The <see cref="T:Pipeline" /> to be used as the default.</param>
<typeparam name="'a">The types of the variables in the computation expression's state.</typeparam>
<returns>Updated computation expression state.</returns>
val runWithArgsAndExit: args: string[] -> pipelines: Pipelines -> unit
<summary> Runs a <see cref="T:Pipeline" /> from the given <c>pipelines</c> based on the command line arguments given in <c>args</c>. <para> Based on success or failure, exits the process with a <c>0</c> or <c>1</c> exit code. </para></summary>
<param name="args">Command line arguments to be parsed.</param>
<param name="pipelines"><see cref="T:Pipelines" /> definition.</param>