| MSBuild-4 :👈 | 👉:MSBuild-6 |
MSBuild Day 5 – Advanced Concepts |
Today you will learn the advanced features of MSBuild that make automation powerful: Property Functions, Conditions, Incremental Builds, Inputs and Outputs, Build Graphs, and Diagnostic Logging. These are essential for writing efficient, maintainable build logic.
Property functions allow you to use .NET-like methods inside MSBuild properties.
They work inside $() expressions.
$(ProjectName.ToUpper())
$(Configuration.StartsWith('D'))
$([System.DateTime]::Now.ToString())
$([System.Guid]::NewGuid())
$(BasePath)\bin\$(Configuration)
$([MSBuild]::Add(3, 5)) $([MSBuild]::Multiply(4, 10))
Property functions are extremely powerful for dynamic build logic.
Conditions exist on almost every MSBuild element: properties, items, targets, tasks. They use simple string comparison or numeric comparison.
<PropertyGroup> <IsDebug Condition=" '$(Configuration)' == 'Debug' ">true</IsDebug> </PropertyGroup>
<ItemGroup>
<LogFiles Include="logs\*.txt" Condition="Exists('logs')" />
</ItemGroup>
<Target Name="OnlyRunInRelease" Condition=" '$(Configuration)'=='Release' ">
<Message Text="Running Release only logic..." />
</Target>
MSBuild supports incremental builds — tasks only run if needed. A target becomes incremental when you define:
If all outputs are newer than inputs, MSBuild skips the target.
<Target Name="ProcessImages"
Inputs="@(Images)"
Outputs="@(Images->'processed\%(Filename).png')">
<Message Text="Processing %(Images.Identity)..." />
</Target>
If none of the source images changed, the target will not run again.
MSBuild compares timestamps of Inputs and Outputs. If output exists and is newer → skip target. If output missing or older → execute target.
Source.txt -> modified today Output.txt -> modified yesterday
MSBuild will rerun the target because output is older.
MSBuild can build multiple projects at once using its dependency graph. This happens automatically when you build a solution.
To force parallel builds:
dotnet build -m
To visualize project build graph:
dotnet msbuild -graph
Diagnostics are crucial for understanding what MSBuild is doing.
dotnet build -v:diag
This prints every imported file, target, task, property, and item.
dotnet build -v:diag -fl -flp:LogFile=msbuild.log
Useful for debugging Directory.Build files, SDK imports, and props/targets:
dotnet msbuild -pp:expanded.xml
Open the file to see exactly what MSBuild sees after all imports.
<ItemGroup>
<TxtFiles Include="data\*.txt" />
</ItemGroup>
<ItemGroup>
<ProcessedFiles Include="@(TxtFiles->'output\%(Filename).out')" />
</ItemGroup>
<Target Name="ProcessText"
Inputs="@(TxtFiles)"
Outputs="@(ProcessedFiles)">
<Message Text="Processing: %(TxtFiles.Identity)" />
</Target>
dotnet build -t:ProcessText
Edit one text file → run again → MSBuild processes only the changed file.
Tomorrow you will learn:
| MSBuild-4 :👈 | 👉:MSBuild-6 |