What's the difference between using dotnet and MSBuild for building .NET applications?
Asked Answered
P

2

69

I've just had to do some builds without using Visual Studio for the first time, and clearly there is a gap in my knowledge regarding MSBuild and the build process.

So, what are the differences between the two build processes below?


Option 1:

dotnet build C:\Dev\trunk\Mvc.sln

This option uses "Build Engine version 16.8.3+39993bd9d for .NET" - I presume this means this way can be used for .NET Core as it has no reference to "Framework"?


Option 2:

msbuild C:\Dev\trunk\Mvc.sln

This option uses "Build Engine version 16.8.2+25e4d540b for .NET Framework".


My assumption was that the "dotnet build" command was just a shorthand way of using MSBuild. However, the logging provided by both is pretty different and they both produce different results.

Papuan answered 24/2, 2021 at 11:23 Comment(6)
Same underlying compiler, different things that invoke it. The compiler itself targets .NET Standard 2.0, and can run on both .NET Framework and .NET Core/5. MSBuild (like VS) runs on .NET Framework, while dotnet build runs on .NET Core. They are by-and-large equivalent, although there are differences (e.g. Analyzers which target .NET Core/5 will only run under dotnet build). MSBuild can handle non-SDK-style projects, whereas dotnet build can only handle SDK-style projects (remember that the compiler itself doesn't interpret .csproj files)Henrion
@Henrion thanks for the comment. When building in VS, how does it do it then? Would a .NET Core project use dotnet build and a .NET Framework project use msbuild?Papuan
No, building in VS will always run the compiler on top of .NET Framework: VS effectively uses MSBuild. The target runtime of the application which is being compiled is (technically) completely independent of the runtime the compiler itself is currently executing on: Roslyn running on .NET Framework can emit IL which is executed by .NET Core just fine. dotnet build does however mean that the compiler can be run on targets which don't support .NET Framework (e.g. Linux), and it's a much nicer interface overall for command-line useHenrion
Okay great, that makes a lot of sense. Thanks for taking the time to explain it to help me understand it, and not just downvoting because it's easy!Papuan
It's also worth noting that the compiler is shipped with VS, so its versions line up with the VS versions, and you get new compiler versions by upgrading VS. The compiler is also included in the .NET SDKs, and dotnet build loads the compiler from one of the installed SDKs, so you can upgrade it by installing a later SDKHenrion
@Henrion You read my mind with that last comment, thanks for the info again. if you'd like to package all this info up into a nicely presented answer, I would be happy to accept it. This is information I struggled to find elsewhere (in a format so easily understandable to me atleast) and I have found your comments extremely helpful.Papuan
H
101

Roslyn -- the C# compiler platform -- is a .NET Standard 2.0 library, meaning that it can run on both .NET Framework 4.6.1+ and .NET Core 2.0+(1).

Visual Studio, which includes MSBuild, runs on .NET Framework. When you build a project using Visual Studio (or directly using MSBuild), it runs Roslyn on .NET Framework. Visual Studio knows how to process both SDK-style csprojs and the legacy non-SDK-style csprojs, and invoke Roslyn accordingly. The version of Roslyn which is used is tied to the Visual Studio version.

dotnet build is a separate tool, and is a .NET Core application. It knows how to build SDK-style csprojs only, and it does this by running Roslyn on .NET Core. Roslyn is distributed with the .NET Core SDKs, and dotnet build loads Roslyn from one of these installed SDK versions (normally the latest).

These two ways of building a C# project are more-or-less equivalent, and they invoke the same compiler code. However, they differ on where they can run (Visual Studio is .NET Framework and Windows-only, dotnet build is .NET Core and can run on multiple platforms), and whether they can build legacy non-SDK-style csprojs. dotnet build is also a bit nicer to use from the command-line.

Note that the runtime which Roslyn is loaded into has no bearing on the compiled IL which Roslyn can emit: Roslyn running on .NET Framework can emit IL which is executed by .NET Core just fine, and vice versa.

If you are using analyzers which target .NET Core (unlikely, as Analyzers are encouraged to target .NET Standard 2.0), these will only run from dotnet build.


(1) I'm using ".NET Core" to refer to both .NET Core and .NET 5+.

Henrion answered 25/2, 2021 at 10:19 Comment(0)
D
11

MSBuild stands for "Microsoft Build Engine", which is a platform for building applications. Before the appearance of the platform-independent .NET with .NET Core, MSBuild was a Windows-only tool and could only be obtained as part of a Visual Studio licence.

With the appearance of .NET Core it is possible to get MSBuild by installing a .NET SDK, which is not bound to Visual Studio and platform independent. When using .NET SDK via CLI, running dotnet build is equivalent to dotnet msbuild --restore. Under the hood, the latter command also runs MSBuild, but in this case the one that comes with .NET SDK.

As far as I know, running the msbuild CLI command is only possible on windows with Visual Studio installed (haven't tried on a Mac with VS for Mac). This command, however, is equivalent to running dotnet msbuild on a system with .NET SDK. So, in a way, both commands that you mention are essentially the same, except that dotnet build also silently call restores the project before running dotnet msbuild (which, as mentioned, is equivalent to msbuild on Windows with Visual Studio.

Deferment answered 3/6, 2023 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.