Build Automation Tools (MSBuild, dotnet CLI & NuGet)
|
This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The C# Reference bibliography lists the reference material consulted while preparing these pages. |
"Build automation" in .NET means that a single command — dotnet build, dotnet test, dotnet pack or
dotnet publish — turns a source tree into tested binaries, NuGet packages or a deployable application, the same way on
every developer machine and every CI agent. Unlike the JVM world, where Maven and Gradle compete, or Python, where
standards connect interchangeable tools, .NET ships one tool chain from one vendor, split into three parts that are
always used together:
-
MSBuild, the engine. It reads the XML project files (
.csproj,.props,.targets), evaluates their properties and items, and runs targets made of tasks. Every .NET build, whether started from a terminal, Visual Studio, Rider or VS Code, is an MSBuild build. -
The .NET SDK and its
dotnetCLI, the driver. The SDK carries MSBuild, the Roslyn compilers, NuGet, the project SDKs (Microsoft.NET.Sdkand friends) and the templates; thedotnetcommand is a thin front end that picks an SDK, translates its options into MSBuild switches and invokes the right targets. -
NuGet, the package manager. It is built into both MSBuild (the
RestoreandPacktargets) and the CLI (dotnet package,dotnet nuget). It resolvesPackageReferenceitems against package sources, downloads.nupkgfiles into the global-packages folder and writes the assets file that the compiler reads.
The introduction to these tools is already on two pages of the C# Reference:
Build and Tooling (the dotnet CLI, a first look at packing,
tools, MSBuild, symbols and CI) and
Namespaces, Assemblies and Projects
(SDK-style projects, multi-targeting, global.json, NuGet consuming and authoring, deployment models). This section
goes much deeper and does not repeat them. It is the .NET counterpart of the JVM build tools section (issue #300) and the
Python build tools section (issue #305); the sections share no pages.
The pages were written against MSBuild 18.9, the .NET SDK 10.0.402 and NuGet 7.9.0. Every example was run
with SDK 10.0.402 installed by dotnet-install.sh --version 10.0.402 into a scratch directory on Ubuntu 24.04 (x64),
on 2026-10-23; long absolute paths in the output are shortened to ~/ledgerline and <sdk> (the SDK folder).
One engine, one driver, one package manager
The diagram is the life of every build; the next page, How a .NET Build Works, follows it step by step. The table below shows which part of the tool chain owns each step.
| Step | MSBuild | .NET SDK / dotnet CLI |
NuGet |
|---|---|---|---|
Choose the tools |
— |
The |
— |
Get dependencies |
Runs the |
|
Resolves versions, downloads packages, writes |
Describe the build |
Evaluates the project, |
Provides the project SDKs ( |
Generates |
Run the build |
Executes targets and tasks ( |
|
— |
Produce packages and apps |
Runs |
|
Writes the |
The dotnet CLI is a driver in the strict sense: the documentation states that "running dotnet build is equivalent
to running dotnet msbuild -restore; however, the default verbosity of the output is different", and every building
command accepts MSBuild switches such as -p: and -v:.
NuGet appears twice: as MSBuild targets (Restore, Pack) inside every build, and as the dotnet nuget /
dotnet package commands for everything outside a build (sources, push, signing, search).
Checking which tools you have
The three versions come from one SDK installation. dotnet --version prints the SDK that the current directory
selects (through global.json, if any); dotnet msbuild -version prints the MSBuild that SDK carries; and
dotnet nuget --version prints the NuGet client in it.
dotnet --version
dotnet msbuild -version
dotnet nuget --version
dotnet --list-sdks
10.0.402
18.9.15.50611
7.9.0-rc.611+a8dd0577c5c13f43a2f57fe33b4ff11b90f6371e.a8dd0577c5c13f43a2f57fe33b4ff11b90f6371e
10.0.402 [<dotnet>/sdk]
The NuGet line deserves a remark: the NuGet assemblies inside SDK 10.0.402 carry the informational version
7.9.0-rc.611+<commit>, although the SDK’s release notes and nuget.exe call the release 7.9.0. The NuGet release
notes list SDK 10.0.400 as the SDK that ships NuGet 7.9; the suffix is a build label, not a sign of a preview client.
Release baseline
These are the releases the section documents, re-verified on 2026-10-23 against the .NET release metadata, the NuGet APIs and the release notes. Newer releases are mentioned only in clearly labelled passages.
| Tool | Baseline | Also covered | Notes |
|---|---|---|---|
.NET SDK |
10.0.402 (2026-10-13; runtime 10.0.13; .NET 10 is LTS, supported until 2028-11-14) |
11.0.100-rc.2.26504.105 (2026-10-13, "go-live" release candidate) in preview passages; 9.0.319 and 8.0.426 where behaviour differs |
.NET 8 (LTS) and .NET 9 (STS) both reach end of support on 2026-11-10. |
MSBuild |
18.9.15, the version inside SDK 10.0.402 |
18.11 (Visual Studio 2026 18.11.1; GitHub release v18.11.0); 18.12 preview inside SDK 11 RC 2 |
There is no "what’s new in MSBuild 18" page; the changes are in the GitHub releases and the SDK what’s-new pages. |
NuGet |
7.9.0 (SDK 10.0.400 and later; |
7.10.0 (Visual Studio 2026 18.10 only); 8.0 prerelease inside SDK 11 RC 2 |
NuGet releases with each SDK feature band; there are no 7.1 and 7.2 release-note pages. |
Visual Studio |
2026 18.11.1 (2026-10-20) |
Used only in the Visual Studio, Package Manager Console and |
|
Publishing tools |
Microsoft.SourceLink.* 10.0.402 (built into the SDK), Microsoft.DotNet.ApiCompat.Tool 10.0.402, |
MinVer, Nerdbank.GitVersioning and BaGetter are third-party; each appears in one worked example only. |
|
CI actions |
|
Some learn.microsoft.com pages still show |
|
nuget.org policy |
API keys expire after at most 30 days (since 2026-08-17); older keys expire on 2026-11-01 |
Trusted Publishing (announced 2025-09-22) |
Announced on the NuGet blog; the API key documentation still describes 365-day keys. |
The running example: Ledgerline
Almost every example in the section uses one original repository, Ledgerline, a small library for double-entry
bookkeeping ledgers. It reads a CSV journal (date,entry,account,debit,credit,memo), checks that every entry balances
and exports a trial balance per account as JSON. No package named Ledgerline exists on nuget.org, and the examples
never push one there: they publish to a folder feed (./artifacts/feed) and to a BaGetter server running in a container
on http://localhost:5555.
ledgerline/
├── Ledgerline.slnx solution (XML format, the .NET 10 default)
├── global.json pins SDK 10.0.402, selects the MTP test runner
├── nuget.config nuget.org + the local feeds, with package source mapping
├── Directory.Build.props shared properties (Nullable, TreatWarningsAsErrors, package metadata)
├── Directory.Build.targets packs README.md and icon.png into every packable project
├── Directory.Packages.props Central Package Management: every package version in one place
├── .editorconfig README.md LICENSE icon.png CHANGELOG.md
├── src/
│ ├── Ledgerline/ the library: net10.0;net8.0;netstandard2.0
│ ├── Ledgerline.Build/ an MSBuild task (ValidateLedger) + buildTransitive targets
│ ├── Ledgerline.Cli/ a .NET tool (command: ledgerline)
│ └── Ledgerline.Templates/ a template package (dotnet new ledgerline-app)
├── tests/Ledgerline.Tests/ xUnit v3 tests (VSTest and Microsoft.Testing.Platform)
└── samples/
├── Ledgerline.Report/ console app that consumes Ledgerline from the local feed
└── quick-ledger.cs a file-based app (#:package directive)
Building the consumer app shows all three tools at work in a few lines: NuGet restores Ledgerline and
Ledgerline.Build from the local feed, MSBuild runs the LedgerlineValidateJournals target that the
Ledgerline.Build package added to the build, and the compiler writes the app.
cd ledgerline/samples/Ledgerline.Report
dotnet build -tl:off
dotnet run --no-build -- journal.ledger.csv
Determining projects to restore...
Restored ~/ledgerline/samples/Ledgerline.Report/Ledgerline.Report.csproj (in 355 ms).
Ledgerline: 4 journal lines balance.
Ledgerline.Report -> ~/ledgerline/samples/Ledgerline.Report/bin/Debug/net10.0/Ledgerline.Report.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.03
[
{
"Account": "1000-Cash",
"Debit": 500.00,
"Credit": 120.00,
"Balance": 380.00
},
…
]
-tl:off turns off the Terminal Logger (the default console logger since .NET 9), whose live, redrawn output does not
survive copying into a page; the section uses it, or -v:n, wherever output is shown.
Reading path
The section has five groups. Read the shared pages first; the other four can be read in any order.
Shared foundations (this group) — the concepts that cut across the three tools:
-
How a .NET Build Works — SDK resolution, restore, evaluation, execution and outputs
-
SDK-Style Project Files and Target Frameworks and Runtime Identifiers
-
Reproducible and Deterministic Builds, CI Builds and Caching and Supply-Chain Security
-
Choosing and Combining the Tools, Ecosystem and Learning Resources and the cheat sheet
MSBuild — the engine: project file anatomy, properties, items, functions, conditions, targets, incremental builds, tasks, imports, customisation, the command line, binary logs, parallel and graph builds, BuildCheck, the API and troubleshooting.
.NET SDK & dotnet CLI — the driver: installing and
selecting SDKs, every dotnet command (including file-based apps, dnx and the .NET 10 noun-first commands), templates,
the SDK property reference, environment variables and SDK errors.
NuGet — the package manager from the consumer’s side:
versions and ranges, dependency resolution, PackageReference, Central Package Management, lock files, nuget.config,
source mapping, restore, auditing, signatures, authenticated feeds, the commands and the server API.
Publishing & Distributing Libraries — the life of
a library from design to a published, maintained package: metadata, dotnet pack, layout, versioning, symbols and Source
Link, package validation, signing, tools and templates, nuget.org, Trusted Publishing, private feeds and CI release
workflows.
The sources consulted for every page are listed in the C# Reference bibliography; each page also ends with its own references.