What is MSBuild?
MSBuild (Microsoft Build Engine) is a build system and platform for building applications, primarily in the .NET ecosystem. It orchestrates how code is compiled, tested, packaged, and deployed by processing XML project files like .csproj
, .fsproj
and .vbproj
. Visual Studio uses MSBuild, but you can use MSBuild without Visual Studio to build .NET applications.
Key Features of MSBuild
- Project Building:
- Compiles your source code into Intermediate Language (IL) and packages it into binaries (
.dll
,.exe
). - Resolves project dependencies (e.g., NuGet packages) and includes them in the build process.
- Executes additional build tasks (e.g., running tests, creating packages, deployment tasks).
- Compiles your source code into Intermediate Language (IL) and packages it into binaries (
- XML-Based Configuration:
- Uses XML-based project files to define build instructions in a clear and extensible format.
- Project files are used to define build steps, configurations, dependencies, and more.
- Highly Customizable:
- You can write custom targets and tasks to extend its functionality.
- Integrated with .NET CLI:
- Commands from .NET CLI like
dotnet build
,dotnet restore
, anddotnet publish
use MSBuild under the hood to build projects. - Visual Studio has a built-in support for MSBuild. For editors that are not integrated with MSBuild like VS Code and Zed, the .NET CLI is commonly used to manage builds.
- Commands from .NET CLI like
- Build Automation and CI/CD Integration:
- Integrates with CI/CD systems like GitHub Actions, Azure Pipelines, and Jenkins to automate builds, tests, and deployments.
- Defines build and deployment pipelines entirely in MSBuild scripts.
- Cross-Platform:
- Initially Windows-only, MSBuild became cross-platform starting with .NET Core, allowing builds on Linux and macOS.
- Ensures the same build logic works across operating systems, making it ideal for CI/CD pipelines.
MSBuild Project File
MSBuild processes an XML-based project file format which is configured to describe build items, configurations, and reusable build rules for consistency across projects.
There are different types of project files such as .csproj
for C# projects, .fsproj
for F# projects and .vbproj
for visual basic projects.
MSBuild Project File Structure
The following is an overview of the key elements that make up an MSBuild project file, explaining how each contributes to the build process and project configuration.
File Root
-
The project file begins with the
<Project>
root element which acts as the container for all other elements.
<Project> </Project>
Modern .NET projects use SDK-style projects, where the SDK specifies a predefined set of build logic, properties, and imports.
-
Some available SDKs:
-
Microsoft.NET.Sdk
: For console apps or libraries. -
Microsoft.NET.Sdk.Web
: For web projects lika Web APIs or MVC apps. -
Microsoft.NET.Sdk.Worker
: For worker services and background jobs. -
Aspire.AppHost.Sdk
: For Aspire app host. -
MSTest.Sdk
: For MSTest apps.
-
-
Ways of declaring SDK:
-
Inline SDK declaration:
<Project Sdk="Microsoft.NET.Sdk"> </Project>
-
Using the
<Sdk>
element:
<Project> <Sdk Name="Microsoft.NET.Sdk" /> </Project>
-
Properties
- Key-value pairs used to configure builds and global settings like target framework, build configuration, and output paths.
-
They are defined within a
<PropertyGroup>
. Multiple<PropertyGroup>
sections can be added.
<PropertyGroup> <TargetFramework>net9.0</TargetFramework> </PropertyGroup>
-
Conditions can be specified to dynamically enable properties:
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <Optimize>true</Optimize> </PropertyGroup>
Examples on properties:
-
Target Framework
-
<TargetFramework>
used to specify a single .NET version and<TargetFrameworks>
for multiple versions:
<TargetFramework>net9.0</TargetFramework> <TargetFrameworks>net9.0;net40;net45</TargetFrameworks>
Common TFMs:
net9.0
,net8.0
,netstandard2.1
,netcoreapp3.1
,net481
. OS-specific TFMs (e.g.,net5.0-windows
,net6.0-ios
) include platform-specific bindings.-
You can add to source code preprocessor directives for conditional compilation by framework:
#if NET40 Console.WriteLine("Target framework: .NET Framework 4.0"); #endif
-
-
Implicit using Directives
- Starting with .NET 6, C# projects automatically include commonly used namespaces via implicit global using directives, reducing the need to manually add them.
- Enabled by default for SDKs like
Microsoft.NET.Sdk
,Microsoft.NET.Sdk.Web
,Microsoft.NET.Sdk.Worker
, andMicrosoft.NET.Sdk.WindowsDesktop
. -
<ImplicitUsings>
is used to enable/disable the feature:
<PropertyGroup> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup>
-
Additional implicit global using directives can be specified by adding
Using
items to project file:
<ItemGroup> <Using Include="System.IO.Pipes" /> </ItemGroup>
-
Compiler and Code Analyzer Warnings
-
<TreatWarningsAsErrors>
: Converts all compiler warnings into errors. -
<WarningsAsErrors>
: Converts specific compiler warnings into errors. -
<CodeAnalysisTreatWarningsAsErrors>
: Converts code analysis warnings into errors. -
<NoWarn>
: Suppresses specific warnings and doesn't show them in build outputs.
<PropertyGroup> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <WarningsAsErrors>CS0168</WarningsAsErrors> <CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors> <NoWarn>CS2002</NoWarn> </PropertyGroup>
-
Items
- Specify inputs to the build process, such as source files, packages, dependencies, and resources.
- They are defined within a
<ItemGroup>
. Multiple<ItemGroup>
sections can be added. -
For simplicity, use
dotnet add package
to add a package instead of manually adding it to the project file.
<ItemGroup> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" /> <ProjectReference Include="..\OtherProject\OtherProject.csproj" /> <Compile Include="Program.cs" /> </ItemGroup>
Tasks
- Individual steps within targets to perform certain actions.
-
MSBuild includes built-in tasks (e.g., Copy, Exec, MakeDir, Csc) and supports custom ones (by implementing
ITask
or deriving from the helper classTask
)
<Target Name="CustomTarget"> <Exec Command="dotnet restore" /> <Copy SourceFiles="README.md" DestinationFolder="bin\docs\" /> <Csc Sources="@(Compile)" OutputAssembly="bin\MyApp.dll" /> </Target>
Targets
- Group tasks and define sections of the project file as entry points for the build process.
-
BeforeTargets
,AfterTargets
andDependsOnTargets
attributes can be used to order targets.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Exec Command="echo pre build" /> </Target> <Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Exec Command="echo post build" /> </Target> <Target Name="PostPostBuild" DependsOnTargets="PostBuild"> <Exec Command="echo post post build" /> </Target>
C# Web API Project Example
Lets create a dummy C# Web API project from scratch, without using Visual Studio nor dotnet new
command to generate a template. Instead, we’ll manually create the required files, use the dotnet CLI to build and run the project, and test it using a simple HTTP request. Feel free to use your favorite editor to edit the files.
-
Create the project directory:
mkdir DemoApp cd DemoApp
-
Create the
.csproj
file:
vim DemoApp.csproj
-
Add the following content to the
.csproj
file -<TargetFramework>
is required:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net9.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> </Project>
-
Create the
Program.cs
File:
vim Program.cs
-
Add the following content to
Program.cs
to define a simple/welcome
API endpoint.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/welcome", () => "Hello, you!"); app.Run();
-
Build the project - The output binaries will be placed in the
bin/Debug/net9.0
directory by default.
dotnet build
-
Run the project - The output will indicate that the app is listening on:
http://localhost:5000
.
dotnet run
-
Test the project - The output should be:
Hello, you!
.
curl http://localhost:5000/welcome
Final output via Zed editor:
And that's all! You can play around .csproj
configurations and explore other properties.
Learning Resources
Refer to the following resources if you would like to learn more about MSBuild and project files:
Top comments (0)