Florian Winkelbauer

Building C# using C#

Having your own pet project gives you the great possibility to try things you would not want to explore in a serious project. One of my latest experiments made me rethink how I create build scripts (which I have mentioned before in a previous blog post): What if I would use C# as a “scripting language” in order to create a build script. Or even better: What if I could create a CLI tool which deals with all my build tasks? The advantages are rather nice:

Here’s an example of a class which contains all command line interface verbs such as clean, build, or test. Most of the methods found in this class simply call the git or the dotnet CLI with parameters. You can run the tool using dotnet run:

dotnet run --project MyProject.Build.csproj -- clean -c Debug
dotnet run --project MyProject.Build.csproj -- build -c Debug

dotnet run --project MyProject.Build.csproj -- clean
dotnet run --project MyProject.Build.csproj -- build

Using dotnet run to run a C# program which in turn calls dotnet build to build some other C# program might be weird in the beginning, but we can use wrapper scripts in PowerShell or Bash to forget about these messy details. Here’s an example written in PowerShell:

$root = git rev-parse --show-toplevel
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

try {
    Push-Location $root

    $project = git ls-files '*.Build.csproj'
    if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

    dotnet run --project $project -- $args
    if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
finally {
    Pop-Location
}

This script (let’s call it make.ps1) changes the above dotnet run command to something like this:

./make.ps1 clean
./make.ps1 build

You could even copy this script to a place which is in your PATH variable so that you could call it from anywhere inside your project/repository. This is why the above script changes the root directory using a call to git rev-parse.

Some experiments give you an opportunity to learn. Some may end up nowhere. This one sparks joy. Well, at least for me.