Restore, Build and Clean
|
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. |
dotnet build is the command run most often, and most of its options decide which build you get: the
configuration, the target framework, the runtime, the output folder, whether it restores and whether it builds
references. This page runs each option on Ledgerline with .NET SDK 10.0.402 and shows the result. The engine
underneath is described on
How a .NET Build Works.
Restore, then build
dotnet build restores first (it is dotnet msbuild -restore), so a separate dotnet restore is optional on a
developer machine. In CI, separating them makes the restore a cacheable, separately-timed step and lets the build run
offline:
dotnet restore --locked-mode
dotnet build -c Release --no-restore
Ledgerline.Build -> ~/ledgerline/src/Ledgerline.Build/bin/Release/netstandard2.0/Ledgerline.Build.dll
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Release/netstandard2.0/Ledgerline.dll
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Release/net10.0/Ledgerline.dll
Ledgerline: 4 journal lines balance.
Ledgerline.Cli -> ~/ledgerline/src/Ledgerline.Cli/bin/Release/net10.0/Ledgerline.Cli.dll
Ledgerline.Report -> ~/ledgerline/samples/Ledgerline.Report/bin/Release/net10.0/Ledgerline.Report.dll
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Release/net8.0/Ledgerline.dll
Ledgerline.Tests -> ~/ledgerline/tests/Ledgerline.Tests/bin/Release/net10.0/Ledgerline.Tests.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.63
The Ledgerline: 4 journal lines balance. line is the ValidateLedger task from the Ledgerline.Build package
(Writing Custom Tasks).
With --no-restore, a project that was never restored fails with NETSDK1004:
~/.dotnet/sdk/10.0.402/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(266,5): error NETSDK1004: Assets file '~/ledgerline/samples/Ledgerline.Report/obj/project.assets.json' not found. Run a NuGet package restore to generate this file. [~/ledgerline/samples/Ledgerline.Report/Ledgerline.Report.csproj]
The restore must also have been run with the same -r (and, for some options, the same properties) as the build;
dotnet restore -r linux-x64 before dotnet build -r linux-x64 --no-restore. The restore options — -s/--source, --configfile, --packages, --locked-mode, --force-evaluate, --no-http-cache,
--ignore-failed-sources — are covered on
Package Restore.
The options
dotnet build -h lists the CLI’s own options; MSBuild switches (-p, -bl, -tl, -m, -warnaserror, …) are not
in the list but are passed through unchanged.
| Option | Effect |
|---|---|
|
|
|
Build one target framework of a multi-targeted project. The framework must be listed in |
|
Build for a runtime identifier: the output gains a RID folder and an apphost for that platform. |
|
|
|
Include the runtime (relevant for publish; see Publish and Deployment Models). |
|
Skip the implicit restore. |
|
Build only the named project; its project references must already be built. |
|
Rebuild: ignore the up-to-date checks (equivalent to |
|
Put one project’s output in a folder (not supported for solutions). |
|
Put all output of every project under one folder, one subfolder per project. |
|
Set |
|
|
|
Allow restore to prompt for credentials (device-flow login of a credential provider). |
|
Do not use or start MSBuild nodes, the compiler server or MSBuild Server for this command. |
|
Set a global property (MSBuild). |
|
Write a binary log (MSBuild). |
|
Terminal Logger (MSBuild); on by default in an interactive terminal since .NET 9. |
Source: dotnet build: Options, dotnet build: MSBuild.
Framework, references and rebuilds
dotnet build src/Ledgerline -f net8.0 --no-restore
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Debug/net8.0/Ledgerline.dll
--no-dependencies trusts that references are already built. After a Release-only build, building the Debug CLI that
way fails, because the referenced Debug Ledgerline.dll does not exist:
dotnet build src/Ledgerline.Cli --no-restore --no-dependencies
~/.dotnet/sdk/10.0.402/Microsoft.Common.CurrentVersion.targets(5096,5): error MSB3030: Could not copy the file "~/ledgerline/src/Ledgerline/bin/Debug/net10.0/Ledgerline.dll" because it was not found. [~/ledgerline/src/Ledgerline.Cli/Ledgerline.Cli.csproj]
It is meant for the inner loop, after a full build; never use it in CI.
Source: dotnet build: Options.
Global properties reach every project
-p sets a global property for the whole build, so it reaches project references too:
dotnet build src/Ledgerline.Cli -bl:logs/cli.binlog -p:Version=1.2.3 -p:InformationalVersion=1.2.3-local
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Debug/net10.0/Ledgerline.dll
Ledgerline.Cli -> ~/ledgerline/src/Ledgerline.Cli/bin/Debug/net10.0/Ledgerline.Cli.dll
BinaryLogger wrote to: ~/ledgerline/logs/cli.binlog
Both Ledgerline.Cli.dll and Ledgerline.dll now carry version 1.2.3.0 and the informational version
1.2.3-local+e33226ff… (Source Link appended the commit). To version one project only, set the property in that
project or its Directory.Build.props. The last line is MSBuild 18.8’s end-of-build summary of log files written
(Logging and Binary Logs).
The runtime options behave differently. -r linux-x64 gave Ledgerline.Cli a RID folder but built the referenced
library without one; --ucr (which sets the UseCurrentRuntimeIdentifier property) built both with the RID:
dotnet build src/Ledgerline.Cli -r linux-x64
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Debug/net10.0/Ledgerline.dll
Ledgerline.Cli -> ~/ledgerline/src/Ledgerline.Cli/bin/Debug/net10.0/linux-x64/Ledgerline.Cli.dll
dotnet build src/Ledgerline.Cli --ucr
Ledgerline -> ~/ledgerline/src/Ledgerline/bin/Debug/net10.0/linux-x64/Ledgerline.dll
Ledgerline.Cli -> ~/ledgerline/src/Ledgerline.Cli/bin/Debug/net10.0/linux-x64/Ledgerline.Cli.dll
The SDK removes RuntimeIdentifier from the global properties it passes to referenced libraries, so they are built
once and shared; a property that only sets the RID indirectly is not removed.
Source: dotnet build, dotnet restore.
Library versus executable output
src/Ledgerline/bin/Debug/net10.0/:
Ledgerline.deps.json Ledgerline.dll Ledgerline.pdb Ledgerline.xml
src/Ledgerline.Cli/bin/Debug/net10.0/:
Ledgerline.Cli Ledgerline.Cli.deps.json Ledgerline.Cli.dll Ledgerline.Cli.pdb Ledgerline.Cli.runtimeconfig.json
Ledgerline.dll Ledgerline.pdb Ledgerline.xml
An executable adds the apphost (Ledgerline.Cli, Ledgerline.Cli.exe on Windows), the runtimeconfig.json that
names the runtime to load, and copies of its references. A library’s output is not runnable; its dependencies come
from the consuming application. For a framework-dependent app, dotnet build output is runnable on the build machine
but is not a deployment — use dotnet publish.
Output folders
-o is for one project. On a solution it warns, because every project would copy into one folder:
~/.dotnet/sdk/10.0.402/Current/SolutionFile/ImportAfter/Microsoft.NET.Sdk.Solution.targets(36,5): warning NETSDK1194: The "--output" option isn't supported when building a solution. Specifying a solution-level output path results in all projects copying outputs to the same directory, which can lead to inconsistent builds. [~/ledgerline/Ledgerline.slnx]
The artifacts layout (.NET 8 and later) is the supported way to collect output in one place. --artifacts-path
enables it for one command; <UseArtifactsOutput>true</UseArtifactsOutput> in Directory.Build.props enables it for
the repository (in an artifacts/ folder next to the props file):
dotnet build src/Ledgerline.Cli --artifacts-path artifacts/out
find artifacts/out -maxdepth 3 -type d | sort
Ledgerline -> ~/ledgerline/artifacts/out/bin/Ledgerline/debug_net10.0/Ledgerline.dll
Ledgerline.Cli -> ~/ledgerline/artifacts/out/bin/Ledgerline.Cli/debug/Ledgerline.Cli.dll
artifacts/out
artifacts/out/bin
artifacts/out/bin/Ledgerline
artifacts/out/bin/Ledgerline.Cli
artifacts/out/bin/Ledgerline.Cli/debug
artifacts/out/bin/Ledgerline/debug_net10.0
artifacts/out/obj
artifacts/out/obj/Ledgerline
artifacts/out/obj/Ledgerline.Cli
artifacts/out/obj/Ledgerline.Cli/debug
artifacts/out/obj/Ledgerline/debug_net10.0
The layout is <artifacts>/<type>/<project>/<pivot>: the type is bin, obj, publish or package; the pivot
combines the configuration, the target framework (only for multi-targeted projects, hence debug_net10.0 for
Ledgerline and debug for the CLI) and the RID. Ledgerline keeps its packages in artifacts/feed, which does not
collide with these folders.
dotnet clean
dotnet clean runs the Clean target: it deletes the files the previous build recorded writing
(obj/<config>/<tfm>/*.FileListAbsolute.txt) for one configuration, framework and RID — not the bin and obj
folders. After Debug, Release and linux-x64 builds of the CLI:
find src/Ledgerline.Cli/bin src/Ledgerline.Cli/obj -type f | wc -l
dotnet clean src/Ledgerline.Cli
find src/Ledgerline.Cli/bin src/Ledgerline.Cli/obj -type f | wc -l
77
58
The Release and linux-x64 outputs and the restore files in obj survived. Pass the same -c, -f and -r as the
build, or delete bin/obj (or the artifacts folder) when a truly clean state is needed, for example after changing
TargetFrameworks.
Source: dotnet clean: Options.
Building with the wrong SDK
A project that targets a framework newer than the SDK fails in evaluation with NETSDK1045 — here, net11.0 with
SDK 10.0.402:
<sdk>/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.TargetFrameworkInference.targets(184,5): error NETSDK1045: The current .NET SDK does not support targeting .NET 11.0. Either target .NET 10.0 or lower, or use a version of the .NET SDK that supports .NET 11.0. Download the .NET SDK from https://aka.ms/dotnet/download [~/demo/App.csproj]
Install the newer SDK and select it in global.json
(Installing and Selecting SDKs).
Source: NETSDK1045.
Common mistakes
-
dotnet build -o outon a solution — NETSDK1194; use--artifacts-path. -
--no-restorewithout a matching restore — NETSDK1004, or stale assets after changing-r. -
--no-dependenciesin CI — MSB3030 or a build against stale references. -
Expecting
-p:Versionto touch one project — global properties reach every reference. -
Trusting
dotnet cleanto reset everything — it cleans one configuration/framework/RID. -
Shipping
dotnet buildoutput — usedotnet publish.