Nullean.Make
0.23.0
See the version list below for details.
dotnet add package Nullean.Make --version 0.23.0
NuGet\Install-Package Nullean.Make -Version 0.23.0
<PackageReference Include="Nullean.Make" Version="0.23.0" />
<PackageVersion Include="Nullean.Make" Version="0.23.0" />
<PackageReference Include="Nullean.Make" />
paket add Nullean.Make --version 0.23.0
#r "nuget: Nullean.Make, 0.23.0"
#:package Nullean.Make@0.23.0
#addin nuget:?package=Nullean.Make&version=0.23.0
#tool nuget:?package=Nullean.Make&version=0.23.0
Nullean.Make
Typed build targets for .NET, with Argh-quality help. Your targets are the cases of a C# union; each one runs commands, and dependencies run first.
#!/usr/bin/env -S dotnet run --
#:package Nullean.Make@0.23.0
#:property GenerateDocumentationFile=true
#:property NoWarn=CS1591
using Nullean.Make;
using static Nullean.Make.Shell;
var app = new UnionMakeApp<Target>("build");
var config = app.Option<string>("--config", "Build configuration", defaultValue: "Release");
app.Bind(t => t.Value switch
{
Clean => app.Target(() => Exec("dotnet clean")),
Build => app.Target([new Clean()], () => Exec($"dotnet build -c {config.Value}")),
Test test => app.Target([new Build()], () =>
{
if (test.Filter is { } filter) Exec($"dotnet test -c {config.Value} --filter:{filter}");
else Exec($"dotnet test -c {config.Value}");
}),
Pack => app.Target(() => Exec("dotnet pack -c Release -o build/output")),
Release => app.Command([new Test()], [new Pack()]),
_ => throw new InvalidOperationException($"unmapped target {t.Value}")
});
return await app.RunAsync(args);
/// <summary>Clean known output locations</summary>
record Clean;
/// <summary>Run build</summary>
record Build;
/// <summary>Run build then tests</summary>
record Test(string? Filter = null);
/// <summary>Pack the NuGet packages</summary>
record Pack;
/// <summary>Test, then pack</summary>
record Release;
union Target(Clean, Build, Test, Pack, Release);
./build.cs --help
./build.cs test --filter Unit --config Debug
./build.cs release
./build.cs release -s # skip the tests, run only pack
Commands: (pipeline entry points — compose and sequence targets)
release Test, then pack
Targets: (atomic steps — can also be run directly)
clean Clean known output locations
build Run build (depends on: clean)
test Run build then tests (depends on: build)
pack Pack the NuGet packages
Targets
app.Target(body) and app.Target(dependsOn, body) take a plain lambda, so a body can branch, loop and read the case's fields. A Func<Task> body works too. Dependencies run first, once each, and -s / --single-target skips them.
A case record's primary-constructor parameters become the target's flags: Test(string? Filter = null) takes --filter.
Commands
app.Command(requires, composes) sequences other targets. requires are gates, such as tests, and -s skips them. composes always run, in order. An optional third argument is a body that runs last.
Running commands
using static Nullean.Make.Shell; brings in Exec:
Exec("dotnet build -c Release")splits on whitespace. Double quotes group an argument that contains spaces ("My App.csproj"), and\"is a literal quote.Exec("dotnet", "build", "-c", config)passes each argument as is. Use it for arguments built in code.
A command shares the console. A non-zero exit code fails the target, and RunAsync returns 1.
Descriptions
A target's description is the <summary> of its case type's XML doc comment. The comment is read from the XML documentation file, so set GenerateDocumentationFile=true: #:property GenerateDocumentationFile=true in a file-based app, or <GenerateDocumentationFile> in a project. .Description("...") overrides it.
Global options
app.Flag(...) and app.Option<T>(...) declare options that every target can read through .Value. A value that does not parse, or a missing value, exits 2 before any target runs.
Namespaces
A case that is itself a union becomes a namespace: union Db(Migrate, Seed) inside union Target(..., Db) gives db migrate and db seed, and db --help lists them. Case type names must be unique across the whole union, including nested unions.
Class-based targets
MakeApp.Execute<TBuild>(args) discovers targets from a MakeBuild class instead: Target properties, [Flag] and [GlobalOption] properties, and nested Namespace classes. build.cs in this repository is a complete example.
For F#, see Nullean.Make.Fs.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net11.0 is compatible. |
-
net11.0
- Nullean.Argh.Core (>= 0.23.0)
- Proc (>= 0.15.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Nullean.Make:
| Package | Downloads |
|---|---|
|
Nullean.Make.Fs
F# DU/match binding over Nullean.Make — exhaustive, typed, namespaced build targets. |
GitHub repositories
This package is not used by any popular GitHub repositories.