In my previous post, I described how to use Cake.CoreCLR and Cake.Tool versions of Cake to run build scripts on Linux, without requiring Mono. This post acts as a short addendum to that one, by providing a PowerShell bootstrapper script equivalent of the bash bootstrapper.

One of the big advantages of Cake build scripts is that they are cross platform, so the same build script can be run across Windows Linux and Mac. Unfortunately, the bootstrapping scripts are generally platform-specific.

PowerShell Core provides a possible solution to this given that it's cross platform, but I don't know how widespread it really is on the Linux side. The addition of PowerShell Core to the .NET Core 3.0 SDK images may go some way to improving the situation for .NET developers.

In the previous post I provided bootstrapping scripts for Linux, which is how all of the .NET Core apps I work on are built and deployed. When developing locally I use Windows, so the bash scripts I provided are no good. Instead, I use a PowerShell script.

Installing the Cake.Tool global tool locally with PowerShell

On Windows, you can feasibly choose any of the three versions of Cake to run your build scripts. However it's definitely a good idea to use the same version as you use in your CI process, to avoid subtle differences between local builds and your build servers.

The following PowerShell script, uses the global tool approach from the previous post. This script is Windows specific, and assumes you already have .NET Core installed - for a much more exhaustive script that uses PowerShell Core, see the bootstrapper from the Cake project itself.

[CmdletBinding()]
Param(
    [string]$Script = "build.cake",
    [string]$CakeVersion = "0.33.0",
    [string]$Target,
    [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
    [string[]]$ScriptArgs
)

# Define directories.
if(!$PSScriptRoot){
    $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
}

$ToolsDir = Join-Path $PSScriptRoot "tools"
$CakePath = Join-Path $ToolsDir "dotnet-cake.exe"
$CakeInstalledVersion = Get-Command $CakePath -ErrorAction SilentlyContinue  | % {&$_.Source --version}

if ($CakeInstalledVersion -ne $CakeVersion) {
    if(Test-Path $CakePath -PathType leaf) {
        & dotnet tool uninstall Cake.Tool --tool-path "$ToolsDir"
    }
    Write-Output  "Installing Cake $CakeVersion..."
    & dotnet tool install Cake.Tool --tool-path "$ToolsDir" --version $CakeVersion
}

# Build Cake arguments
$cakeArguments = @("$Script");
if ($Target) { $cakeArguments += "--target=$Target" }
$cakeArguments += $ScriptArgs

& "$CakePath" $cakeArguments
exit $LASTEXITCODE

Hopefully the script is fairly self explanatory. It starts by checking the installed version of Cake.Tool (if any). If the correct version is not installed, it installs the global tool using dotnet tool install, providing a --tool-path to install the tool locally, instead of globally. After building the script arguments, it runs the tool!

If you compare this script to the Cake project's version, you'll see that this one is definitely minimalist! Consider your use cases, such as whether you want to automate the install of .NET Core, and whether you want a cross-platform PowerShell script, and choose whichever works for you.

Another alternative is to use Cake.CoreCLR instead of the Cake.Tool global tool. This gist by Dmitriy Litichevskiy shows a PowerShell version of the "dummy project" approach I used in my previous post if you prefer. Personally I think the global tool is the cleaner approach, but to each their own!

Summary

In this post I show a Windows PowerShell bootstrapping script for running Cake build scripts using the Cake.Tool .NET Core global tool. The script checks the version of the Cake global tool installed, and replaces it with the correct version if necessary. For a cross-platform PowerShell Core script that also scripts installing .NET Core, see this example from the Cake project.