| MSBuild-4 :👈 | 👉:MSBuild-6 |
MSBuild Day 5 – Advanced Concepts |
Day 5 – Advanced MSBuild: Property Functions, Conditions, Incremental Builds, Inputs/Outputs, Diagnostics
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.
1. Property Functions
Property functions allow you to use .NET-like methods inside MSBuild properties.
They work inside $() expressions.
Examples:
$(ProjectName.ToUpper())
$(Configuration.StartsWith('D'))
$([System.DateTime]::Now.ToString())
$([System.Guid]::NewGuid())
Combine strings:
$(BasePath)\bin\$(Configuration)
Create numbers:
$([MSBuild]::Add(3, 5))
$([MSBuild]::Multiply(4, 10))
Property functions are extremely powerful for dynamic build logic.
2. Conditions in MSBuild
Conditions exist on almost every MSBuild element: properties, items, targets, tasks. They use simple string comparison or numeric comparison.
Property example:
<PropertyGroup>
<IsDebug Condition=" '$(Configuration)' == 'Debug' ">true</IsDebug>
</PropertyGroup>
Item example:
<ItemGroup>
<LogFiles Include="logs\*.txt" Condition="Exists('logs')" />
</ItemGroup>
Target example:
<Target Name="OnlyRunInRelease" Condition=" '$(Configuration)'=='Release' ">
<Message Text="Running Release only logic..." />
</Target>
3. Incremental Builds
MSBuild supports incremental builds — tasks only run if needed. A target becomes incremental when you define:
- Inputs – files or values checked for changes
- Outputs – files produced
If all outputs are newer than inputs, MSBuild skips the target.
Example:
<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.
4. Inputs and Outputs Logic
MSBuild compares timestamps of Inputs and Outputs. If output exists and is newer → skip target. If output missing or older → execute target.
Example of timestamp behavior:
Source.txt -> modified today
Output.txt -> modified yesterday
MSBuild will rerun the target because output is older.
5. Build Graph and Parallel Builds
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
6. Diagnostic Logging
Diagnostics are crucial for understanding what MSBuild is doing.
Common verbosity levels:
- q – quiet
- m – minimal
- n – normal
- d – detailed
- diag – diagnostic (very large output)
Enable diagnostic logging:
dotnet build -v:diag
This prints every imported file, target, task, property, and item.
Write logs to a file:
dotnet build -v:diag -fl -flp:LogFile=msbuild.log
7. Inspect Final Project After Imports
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.
8. Hands-On Exercise (15 minutes)
Step 1 — Add a transform
<ItemGroup>
<TxtFiles Include="data\*.txt" />
</ItemGroup>
<ItemGroup>
<ProcessedFiles Include="@(TxtFiles->'output\%(Filename).out')" />
</ItemGroup>
Step 2 — Create an incremental target
<Target Name="ProcessText"
Inputs="@(TxtFiles)"
Outputs="@(ProcessedFiles)">
<Message Text="Processing: %(TxtFiles.Identity)" />
</Target>
Step 3 — Run
dotnet build -t:ProcessText
Edit one text file → run again → MSBuild processes only the changed file.
9. Summary
- Property functions let you perform dynamic string and logic operations.
- Conditions allow selective execution of MSBuild elements.
- Incremental builds avoid unnecessary work.
- Inputs/Outputs determine whether a target runs.
- The build graph enables parallel builds.
- Diagnostic logging is essential for troubleshooting.
10. Day 6 Preview
Tomorrow you will learn:
- Creating and reusing custom .props and .targets files
- Overriding targets and imports safely
- Shared company-wide MSBuild logic
- Extending MSBuild without modifying individual projects
| MSBuild-4 :👈 | 👉:MSBuild-6 |